Một phép toán hữu ích mà chúng ta có thể thực hiện với các tenxơ tùy ý là tính tổng các phần tử của chúng. Trong toán học chúng ta diễn tả sum (tổng) sử dụng ký hiệu
[imath]\sum[/imath]
. Để ký hiệu tổng các phần tử trong 1 vector
[imath]x[/imath]
có độ dài là
[imath]d[/imath]
, chúng ta có thể viết như sau:
[imath]\sum_{i=1}^d x_i[/imath]
.
Trong code thì chúng ta chỉ cần gọi 1 hàm để tính tổng rất đơn giản.
x = tf.range(4, dtype=tf.float32)
x, tf.reduce_sum(x)
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 1., 2., 3.], dtype=float32)>,
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>)
Chúng ta có thể ký hiệu tổng của các tensor có kích thước tuỳ ý. Ví dụ tổng của các phần từ của một ma trận A có kích thước m x n có thể viết như sau
[imath]\sum_{i=1}^{m} \sum_{j=1}^{n} a_{ij}[/imath]
. (Bên trên là 1 vector dạng [1, 2, 3, 4, 5, 2]
còn đây là tổng quát cho tensor nhiều chiều hơn nhé)
Đầu tiên ta khởi tạo 1 tensor A
A = tf.reshape(tf.range(20, dtype=tf.float32), (5, 4))
Kết quả:
<tf.Tensor: shape=(5, 4), dtype=float32, numpy=
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]], dtype=float32)>
Sau đó chúng ta thực hiện tính tổng
A.shape, tf.reduce_sum(A)
(TensorShape([5, 4]), <tf.Tensor: shape=(), dtype=float32, numpy=190.0>)
Theo mặc định việc gọi hàm reduce sẽ biến tensor đó thành 1 scalar (1 giá trị duy nhất). Ví dụ ta có thể tính tổng theo trục dọc của ma trận A như sau.
A_sum_axis0 = tf.reduce_sum(A, axis=0)
A_sum_axis0, A_sum_axis0.shape
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([40., 45., 50., 55.], dtype=float32)>,
TensorShape([4]))
Bạn để ý trong kết quả ở trên ta có 40 = 0 + 4 + 8 + 12 + 16
, 45 = 1 + 5 + 9 + 13 + 17
, .. xem lại giá trị của tensor A ở trên nhé.
Còn nếu bạn muốn tính tổng theo trục ngang thì ta chỉ cần điều chỉnh tham số axis=1
A_sum_axis1 = tf.reduce_sum(A, axis=1)
A_sum_axis1, A_sum_axis1.shape
Kết quả:
(<tf.Tensor: shape=(5,), dtype=float32, numpy=array([ 6., 22., 38., 54., 70.], dtype=float32)>,
TensorShape([5]))
Chúng ta tính tổng cả theo trục dọc và ngang sẽ tương đương với việc chúng ta tính tổng trên cả ma trận.
tf.reduce_sum(A, axis=[0, 1]) # tương tự `tf.reduce_sum(A)`
<tf.Tensor: shape=(), dtype=float32, numpy=190.0>
Một đại lượng là mean hay cũng có thể gọi là trung bình chúng ta có thể tính nó bằng cách lấy tổng tất cả các phần tử của ma trận chia cho số phần tử.
tf.reduce_mean(A), tf.reduce_sum(A) / tf.size(A).numpy()
(<tf.Tensor: shape=(), dtype=float32, numpy=9.5>,
<tf.Tensor: shape=(), dtype=float32, numpy=9.5>)
Tương tự chúng ta cũng có thể tính mean theo 1 trục đặc biệt nào đó ví dụ trục 0 hoặc trục 1 chỉ cần thay axis tương ứng.
tf.reduce_mean(A, axis=0), tf.reduce_sum(A, axis=0) / A.shape[0]
Kết quả:
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 8., 9., 10., 11.], dtype=float32)>,
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 8., 9., 10., 11.], dtype=float32)>)
Non-reduction sum
Tuy nhiên trong 1 số trường hợp sẽ hữu ích khi chúng ta gọi hàm để tính sum hoặc mean mà không cần thay đổi số trục của ma trận.
sum_A = tf.reduce_sum(A, axis=1, keepdims=True)
sum_A
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[ 6.],
[22.],
[38.],
[54.],
[70.]], dtype=float32)>