Các hàm toán học cơ bản

Khi làm việc với machine learning, chúng ta phải thực hiện rất nhiều các thao tác toán học như cộng, trừ, nhân, chia, lũy thừa, v.v. TensorFlow cung cấp một tập hợp các hàm toán học giúp chúng ta thực hiện các thao tác toán học dễ dàng hơn.

Phép toán cộng

Chúng ta có thể tính tổng hai tensor bằng cách dùng hàm tf.add của TensorFlow như đoạn mã minh họa sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# tính tổng 3 và 4

print(sess.run(tf.add(3,4))) # kết quả: 7

Phép toán trừ

Chúng ta có thể tính hiệu hai tensor bằng cách dùng hàm tf.subtract của TensorFlow như đoạn mã minh họa sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# tính hiệu 3 và 4

print(sess.run(tf.subtract(3,4))) # kết quả: -1

Phép toán nhân

Chúng ta có thể tính tích hai tensor bằng cách dùng hàm tf.multiply của TensorFlow như đoạn mã minh họa sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# tính tích 3 và 4

print(sess.run(tf.multiply(3,4))) # kết quả: 12

Phép toán chia

Chúng ta có thể tính thương của hai tensor bằng cách dùng hàm tf.div của TensorFlow. Kết quả trả về cùng kiểu với các giá trị input, nghĩa là, nếu các giá trị input có kiểu số nguyên thì kết quả phép chia sẽ được làm tròn đến giá trị nguyên cận dưới như đoạn mã sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# tính thương 3 và 4

print(sess.run(tf.div(3,4))) # kết quả: 0

Nếu chúng ta muốn hiển thị chính xác kết quả của phép chia 3 và 4, chúng ta có thể chuyển các giá trị này sang kiểu float, tức là 3.0 và 4.0:


print(sess.run(tf.div(3.0,4.0))) # kết quả: 0.75

Tensorflow cũng hỗ trợ hàm tf.truediv để trả về kết quả chính xác cho phép chia nếu hai giá trị input có kiểu số nguyên. Phép chia 3 và 4 có thể viết lại:


print(sess.run(tf.truediv(3,4))) # kết quả: 0.75

Khi các input là số nguyên, hàm tf.div sẽ trả về kết quả là giá trị nguyên cận dưới và TensorFlow cũng cung cấp hàm tf.floordiv có ý nghĩa tương tự hàm tf.div nhưng áp dụng cho các input có kiểu float như sau:


print(sess.run(tf.floordiv(3.0,4.0))) # kết quả: 0.0

Phép toán lấy dư

TensorFlow cung cấp hàm tf.mod trả về số dư của một phép chia như đoạn mã minh họa sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# trả về số dư của phép chia 7 và 2

print(sess.run(tf.mod(7,2))) # kết quả: 1

Phép toán lũy thừa

TensorFlow cung cấp hàm tf.pow trả về lũy thừa như đoạn mã minh họa sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# trả về lũy thừa 2 của 7

print(sess.run(tf.pow(7,2))) # kết quả: 49

Các hàm toán học khác

Bên cạnh các hàm toán học cơ bản trên, TensorFlow cung cấp một tập hợp các hàm toán học phục vụ cho nhiều mục đích tính toán phức tạp hơn. Bảng dưới đây liệt kê các hàm toán học hỗ trợ bởi TensorFlow và chúng ta có thể tra cứu về các hàm này tại tensorflow.org:

Các hàm toán học phổ biến Các hàm toán học đặc biệt
abs() digamma()
ceil() erf()
cos() igamma()
exp() igammac()
floor() lbeta()
inv() lgamma()
log() squared_difference()
maximum()  
minimum()  
neg()  
pow()  
round()  
rsqrt()  
sign()  
sin()  
sqrt()  
square()  

Các vectơ

Vectơ là một trong những đối tượng cơ bản nhất khi làm việc với các thuật toán trong machine learning và là một trong những cách đơn giản nhất để thể hiện các dữ liệu số.

Cho vectơ X = (x1,x2,…,xn), với xi = 1,..,n là các tọa độ của X. Vec tơ X trong trường hợp này có n chiều. Độ lớn của vectơ X, kí hiệu |X|, được tính như sau:

Ví dụ độ lớn của vectơ a = (1,2,3)

Nhân vectơ X với một hằng số c (c được gọi là vô hướng hay scalar) sẽ được một vectơ:

cX = (c*x1, c*x2,…,c*x3)

Cho vec tơ Y = (y1,y2,…,yn), với yi = 1,..,n là các tọa độ của Y. Tổng hai vectơ X và Y là một vectơ:

X + Y = addXY = (x1 + y1, x2  + y2,…,xn + yn)

Tương tự hiệu hai vectơ X và Y là một vectơ:

X – Y = subXY = (x1 – y1, x2 – y2,…,xn – yn)

Tích vô hướng hai vectơ X và Y là một giá trị số:

XY = mulXY = x1y1 + x2 y2 +… + xnyn

Trong TensoFlow, chúng ta có thể tạo các vectơ dùng hàm tf.constant như sau:


vec_1 = tf.constant([1,2,3]) # vec_1 = (1,2,3)

vec_2 = tf.constant([4,5,6]) # vec_2 = (4,5,6)

TensorFlow cung cấp một số hàm cơ bản giúp chúng ta thực hiện các thao tác với vectơ được dễ dàng hơn như sau:

  • Cộng hai vectơ: dùng hàm add từ thư viện TensorFlow
  • Trừ hai vectơ c: dùng hàm subtract từ thư viện TensorFlow
  • Nhân một vectơ với một giá trị số (còn gọi là scalar): dùng hàm multiply từ thư viện TensorFlow
  • Độ lớn của một vectơ: dùng hàm norm từ TensorFlow. Lưu ý kiểu dữ liệu của vectơ đầu vào là một trong các kiểu float32, float64, complex64, complex128. Có thể dùng hàm tf.cast để chuyển kiểu (xem ví dụ bên dưới).
  • Tích vô hướng của hai vectơ: dùng hàm tensordot từ TensorFlow

Đoạn mã sau thực hiện các thao tác cơ bản với hai vectơ vec_1vec_2 như sau:


import tensorflow as tf

# tạo một graph session

sess = tf.Session()

# tạo hai vec tơ

vec_1 = tf.constant([1,2,3])

vec_2 = tf.constant([4,5,6])

# tổng hai vectơ

print(sess.run(tf.add(vec_1,vec_2))) # kết quả: [4 7 9]

# hiệu hai vectơ

print(sess.run(tf.subtract(vec_1,vec_2))) # kết quả: [-3 -3 -3]

#  tích vectơ vec_1 và 3

print(sess.run(tf.multiply(vec_1,3))) # kết quả: [3 6 9]

# độ lớn của vec_1, lưu ý chuyển kiểu của vec_1 sang float32 dùng tf.cast

print(sess.run(tf.norm(tf.cast(vec_1,tf.float32)))) # kết quả: 3.7416575

# tích vô hướng của hai vectơ

print(sess.run(tf.tensordot(vec_1,vec_2,1))) # kết quả: 32

Có thể viết lại đoạn mã trên dùng các placeholder. Tham khảo tại https://github.com/TranNgocMinh/TensorFlow/blob/master/Vectors.md

Ma trận

Trước khi bắt đầu tìm hiểu về ma trận và các hàm liên quan trong TensorFlow, chúng ta hãy xem một clip minh họa sinh động về ma trận:

Ma trận hai chiều là ma trận có n hàng và k cột hay còn gọi là ma trận kích thước nxk. Ví dụ ma trận A 2 hàng 3 cột như sau:

Ma trận có số hàng và số cột bằng n gọi là ma trận vuông cấp n. Ví dụ ma trận vuông cấp 3 như sau:

Sử dụng các hàm trong TensorFlow chúng ta có thể tạo hai ma trận A và B như sau:


import tensorflow as tf

import numpy as np

# create a graph session

sess = tf.Session()

A = tf.constant([[1,2,3],[4,5,6]])

# dùng NumPy

B = tf.convert_to_tensor(np.array([[-2, 2, -3],[-1, 1,3],[2, 0, -1]]))

print("A = ", sess.run(A))

print("B =  ", sess.run(B))

Ma trận đường chéo là một ma trận vuông mà mọi phần tử nằm bên ngoài đường chéo chính đều bằng 0. Ví dụ ma trận đường chéo cấp 3:

Chúng ta có thể dùng hàm tf.diag để tạo một ma trận đường chéo. Ví dụ tạo ma trận Diagmat như sau:


Diagmat = tf.diag([1,2,3])

Ma trận đơn vị là ma trận đường chéo với các phần tử trên đường chéo chính bằng 1. Ví dụ ma trận đơn vị cấp 3 như sau:

Chúng ta có thể dùng hàm tf.diag để tạo một ma trận đơn vị (chẳng qua là một ma trận đường chéo). Ví dụ tạo ma trận Matidentity như sau:


Matidentity =  tf.diag([1,1,1])

Tổng và hiệu hai ma trận cùng kích thước

Cho ma trận A có kích thước n x k:

Và ma trận B có cùng kích thước n x k:

Kết quả của tổng A và B là một ma trận addAB cấp n x k:

Tương tự hiệu A và B là ma trận subAB cùng cấp:

Ví dụ:

Trong TensorFlow chúng ta có thể thực hiện việc khởi tạo và tính tổng hiệu các ma trận A và B từ ví dụ trên như sau:


A = tf.constant([[1,-2,3],[2,5,-4]])

B = tf.constant([[3, -1, 1],[2, 2,-2]])

addAB = A + B

subAB = A - B

print("A + B =  ", sess.run(addAB))

print("A - B =  ", sess.run(subAB))

Tích một ma trận và một số

Cho ma trận A cấp n x k:

Tích hằng số c và ma trận A:

Ví dụ c = 3 và A:

Tích c và A:

Tính tích c và A  từ ví dụ trên dùng TensorFlow như sau:


A = tf.constant([[1,-2,3],[2,5,-4]])

c = 3

cA = c * A

print("cA =  ", sess.run(c*A))

Tích hai ma trận

Cho ma trận A cấp n x k:

Và ma trận B cấp k x m:

Để ý rằng số cột của A bằng số hàng của B ( bằng k), khi đó tích hai ma trận A và B là một ma trận AB cấp n x m với phần tử ABij là tích của hàng i trong ma trận A và cột j trong ma trận B:

Chú ý quan trọng rằng AB ≠ BA.

Ví dụ cho các ma trận A cấp 2×3:

Và ma trận B cấp 3×2 như sau:

Tích A và B sẽ là ma trận AB cấp 2×2 như sau:

Một điều kiện quan trọng để tính tích A và B là số hàng của A phài bằng số cột của B. Trong trường hợp A và B từ ví dụ trên chúng ta có thể tính được tích của B và A là ma trận BA cấp 3×3:

Rõ ràng AB ≠ BA.

Trong TensorFlow chúng ta có thể dùng hàm tf.matmul để tính tích hai ma trận thỏa điều kiện. Ví dụ tính AB và BA từ ví dụ trên:


A = tf.constant([[1,-2,3],[2,5,-4]])

B = tf.constant([[1, 0],[2, 1],[1,1]])

AB = tf.matmul(A,B)

BA = tf.matmul(B,A)

print("AB =  ", sess.run(AB))

print("BA =  ", sess.run(BA))

Ma trận chuyển vị

Chuyển vị của ma trận A cấp nxk là một ma trận kí hiệu là AT cấp kxn tạo ra bằng cách chuyển hàng thành cột và cột thành hàng. Ví dụ ma trận A:

Ma trận AT cấp 3×2

Trong TensorFlow chúng ta có thể dùng hàm tf.transpose để tạo ra ma trận chuyển vị của ma trận A từ ví dụ trên như sau:


A = tf.constant([[1,-2,3],[2,5,-4]])

AT = tf.transpose(A)

print ("AT = ", sess.run(AT))

Định thức

Định thức của ma trận vuông A, kí hiệu det(A) hay |A|, là một khái niệm quan trọng trong đại số tuyến tính. Trình bày chi tiết về cách tính định thức của ma trận vuông A vượt quá phạm vi của bài viết này. Chúng ta có thể tìm hiểu một cách ngắn gọn về định thức tại https://vi.wikipedia.org/wiki/%C4%90%E1%BB%8Bnh_th%E1%BB%A9c. Bài viết này sử dụng lại ma trận A và kết quả det(A) từ https://vi.wikipedia.org/wiki/%C4%90%E1%BB%8Bnh_th%E1%BB%A9c:

det(A) = 18

Việc tính định thức không quá khó nhưng cũng không đơn giản cho những người không có “cảm tình” với toán học. TensoFlow cung cấp hàm tf.matrix_determinant giúp chúng ta tính định thức ma trận vuông A một cách nhanh chóng. Chú ý rằng các giá trị của tensor đầu vào của hàm tf.matrix_determinant là một trong các kiểu float32, float64, complex64 hay complex128, do đó, chúng ta cần dùng hàm tf.cast để chuyển kiểu nếu ban đầu chúng ta khai báo ma trận A là các giá trị nguyên (như đoạn mã minh họa dưới đây). Đoạn mã tính det(A) từ ví dụ trên:


A = tf.constant([[0,2,-3],[0,1,3],[2,0,-1]])

detA = tf.matrix_determinant(tf.cast(A,tf.float32))

print("A = ", sess.run(A))

print ("detA = ", sess.run(detA))

Ma trận nghịch đảo

Tương tự khái niệm định thức, trình bày chi tiết về ma trận nghịch đảo của một ma trận vuông A vượt quá phạm vi của bài viết này. Chúng ta có thể tìm hiểu một cách ngắn gọn về ma trận nghịch đảo tại  https://vi.wikipedia.org/wiki/Ma_tr%E1%BA%ADn_kh%E1%BA%A3_ngh%E1%BB%8Bch. Với mục đích kiểm tra, bài viết này sẽ sử dụng ví dụ ma trận A và kết quả ma trận nghịch đảo A-1 từ đường dẫn này:

Điều kiện bắt buộc để tính được A-1 là det(A)≠0.

TensorFlow cung cấp hàm tf.matrix_inverse giúp chúng ta tính ma trận nghịch đảo một cách nhanh chóng và lưu ý rằng rằng các giá trị của tensor đầu vào của hàm tf.matrix_inverse là một trong các kiểu float32, float64, complex64 hay complex128, do đó, chúng ta cần dùng hàm tf.cast để chuyển kiểu nếu ban đầu chúng ta khai báo ma trận A là các giá trị nguyên (như đoạn mã dưới đây). Có thể kiểm tra kết quả từ ví dụ trên qua đoạn mã sau:


A = tf.constant([[1,-2],[3,2]])

inverseA = tf.matrix_inverse(tf.cast(A,tf.float32))

print("A = ", sess.run(A))

print ("detA = ", sess.run(inverseA))

Lời kết

Bài viết này chỉ cung cấp một số hàm cơ bản trong TensorFlow dùng trong xử lý toán học hay tương tác với các đối tượng như vectơ hay ma trận. Để hiểu rõ hơn chúng ta cần tìm hiểu kỹ các hàm từ thư viện tensorflow.org cũng như đọc trở lại các khái niệm cơ bản liên quan tới vectơ hay ma trận từ các cuốn sách về đại số tuyến tính.

Học tensorflow >