Tự học Tensorflow [P3] - Dataset, Layer

Tự học Tensorflow [P3] - Dataset, Layer

2019, Mar 11    

Ở phần trước Tự học Tensorflow [P2] - Session, Feeding, mình đã nhắc tới 2 thành phần cơ bản của Tensorflow đó là tf.SessionFeeding. Trong phạm vi bài viết này, mình xin đề cập tới 2 nội dung quan trọng khi training một models với Tensorflow. Nếu chưa theo dõi nhưng phần trước thì bạn có thể tham khảo thêm:

Dataset

Ở bài trước, chúng ta đã biết tf.placeholder hoạt động giống như một parameter đầu vào của một phương thức. Vậy khi muốn nạp dữ liệu vào theo một luồng dữ liệu thì thứ chúng ta cần là gì? Câu trả lời chính là tf.data, nó cung cấp một phương thức cho phép truyền một dòng dữ liệu vào trong model.

Để chuyển dữ liệu đầu vào thành một tf.Tensor chúng ta cần chuyển nó thành dạng tf.data.Iterator trước tiên. Sau đó sử dụng phương thức tf.data.Iterator.get_next. Cách đơn giản nhất để tạo một Iterator là dùng phương thức tf.data.Dataset.make_one_shot_iterator

my_data = [
    [0, 1,],
    [2, 3,],
    [4, 5,],
    [6, 7,],
]
slices = tf.data.Dataset.from_tensor_slices(my_data)
next_item = slices.make_one_shot_iterator().get_next()

Ở đây, tensor next_item sẽ trả lại giá trị một dòng từ my_data mỗi khi được run.

print(sess.run(next_item))

Output:

[0, 1]

Khi các giá trị của Iterator được lấy hết, Dataset sẽ ném ra một exception tf.errors.OutOfRangeError.

while True:
  try:
    print(sess.run(next_item))
  except tf.errors.OutOfRangeError:
    break

Nếu Dataset được xây dựng lên từ một phương thức của Tensor, chúng ta cần khởi tạo Iterator trước khi sử dụng, giống như việc gọi sess.run để Tensor trả về giá trị vậy. Chúng ta sử dụng tf.data.Dataset.make_initializable_iterator() để khởi tạo chúng.

r = tf.random_normal([10,3])
dataset = tf.data.Dataset.from_tensor_slices(r)
iterator = dataset.make_initializable_iterator()
next_row = iterator.get_next()

sess.run(iterator.initializer)
while True:
  try:
    print(sess.run(next_row))
  except tf.errors.OutOfRangeError:
    break

Layers

Để training một model, giá trị của các parameter trong Graph cần được xác định bằng cách sử dụng tf.layers. Các Layer sẽ đóng gói các biến và phương thức hoạt động trên nó. Điển hình có thể nói đến đó là fully-connected layers cùng với hàm kích hoạt. Các kết nối giữa các weightsbiases được quản lý bởi đối tượng Layer.

x = tf.placeholder(tf.float32, shape=[None, 3])
linear_model = tf.layers.Dense(units=1)
y = linear_model(x)

Khởi tạo layer

Nếu Layer chứa biến thì cần phải được khởi tạo trước khi sửa dụng. Mặc dù có thể khởi tạo các biến một cách độc lập, Tensorflow cung cấp phương thức để có thể dễ dàng khởi tạo tất cả các biến có mặt trong Graph:

init = tf.global_variables_initializer()
sess.run(init)

Chú ý: global__variables_initializer() chỉ khởi tạo giá trị cho các biến đã xuất hiện trong Graph khi thực thi khởi tạo. Vậy nên hãy luôn đặt khởi tạo ở cuối cùng của Graph.

Thực thi Layer

Lúc này Layer đã được khởi tạo, chúng ta có thể bắt đầu khởi chạy một model Linear đơn giản.

print(sess.run(y, {x: [[1, 2, 3],[4, 5, 6]]}))

Output:

[[-3.41378999]
 [-9.14999008]]

Giá trị trả về là weight và bias của Layer Dense mà chúng ta đã tạo ở trên với số lượng unint bằng 1 vậy nên chỉ có 1 weight khi thực thi fully-connected.

Lối tắt của phương thức Layer

Với mỗi lớp Layer (VD: tf.layers.Dense), Tensorflow cũng hỗ trợ lối tắt (VD: tf.layers.dense). Cách sử dụng:

x = tf.placeholder(tf.float32, shape=[None, 3])
linear_model = tf.layers.Dense(units=1)
y = linear_model(x)

Chuyển thành:

x = tf.placeholder(tf.float32, shape=[None, 3])
y = tf.layers.dense(x, units=1)

Chú ý: Tuy cách sử dụng này khá tiện lợi nhưng vì sử dụng lối tắt nên lúc này bạn không thể can thiệp vào layer Dense để debug thông qua biến linear_model như bình thường vì lúc này vai trò của biến linear_model đã biến mất và thay thế bằng cách gọi trực tiếp hàm dense.

Bài viết tham khảo và sử dụng hình ảnh từ: