Giới thiệu về phương pháp cắt tensor

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Khi làm việc trên các ứng dụng ML như phát hiện đối tượng và NLP, đôi khi cần phải làm việc với các phần phụ (lát cắt) của tensor. Ví dụ: nếu kiến ​​trúc mô hình của bạn bao gồm định tuyến, trong đó một lớp có thể kiểm soát ví dụ đào tạo nào được chuyển đến lớp tiếp theo. Trong trường hợp này, bạn có thể sử dụng các thao tác cắt tensor để tách các tensor ra và đặt chúng lại với nhau theo đúng thứ tự.

Trong các ứng dụng NLP, bạn có thể sử dụng phương pháp cắt lớp căng để thực hiện việc che chữ trong khi đào tạo. Ví dụ: bạn có thể tạo dữ liệu đào tạo từ danh sách các câu bằng cách chọn một chỉ mục từ để tạo dấu hiệu trong mỗi câu, lấy từ đó làm nhãn, sau đó thay thế từ đã chọn bằng mã thông báo mặt nạ.

Trong hướng dẫn này, bạn sẽ học cách sử dụng các API TensorFlow để:

  • Trích xuất các lát từ tensor
  • Chèn dữ liệu tại các chỉ số cụ thể trong một tensor

Hướng dẫn này giả định bạn đã quen với lập chỉ mục tensor. Đọc các phần lập chỉ mục của hướng dẫn TensorTensorFlow NumPy trước khi bắt đầu với hướng dẫn này.

Thành lập

import tensorflow as tf
import numpy as np

Trích xuất các lát tensor

Thực hiện cắt tensor giống NumPy bằng tf.slice .

t1 = tf.constant([0, 1, 2, 3, 4, 5, 6, 7])

print(tf.slice(t1,
               begin=[1],
               size=[3]))
tf.Tensor([1 2 3], shape=(3,), dtype=int32)

Ngoài ra, bạn có thể sử dụng một cú pháp Pythonic khác. Lưu ý rằng các lát tensor cách đều nhau trong phạm vi start-stop.

print(t1[1:4])
tf.Tensor([1 2 3], shape=(3,), dtype=int32)

print(t1[-3:])
tf.Tensor([5 6 7], shape=(3,), dtype=int32)

Đối với bộ căng 2 chiều, bạn có thể sử dụng một số thứ như:

t2 = tf.constant([[0, 1, 2, 3, 4],
                  [5, 6, 7, 8, 9],
                  [10, 11, 12, 13, 14],
                  [15, 16, 17, 18, 19]])

print(t2[:-1, 1:3])
tf.Tensor(
[[ 1  2]
 [ 6  7]
 [11 12]], shape=(3, 2), dtype=int32)

Bạn cũng có thể sử dụng tf.slice trên các máy căng kích thước cao hơn.

t3 = tf.constant([[[1, 3, 5, 7],
                   [9, 11, 13, 15]],
                  [[17, 19, 21, 23],
                   [25, 27, 29, 31]]
                  ])

print(tf.slice(t3,
               begin=[1, 1, 0],
               size=[1, 1, 2]))
tf.Tensor([[[25 27]]], shape=(1, 1, 2), dtype=int32)

Bạn cũng có thể sử dụng tf.strided_slice để trích xuất các lát của tensor bằng cách 'sải bước' trên các kích thước tensor.

Sử dụng tf.gather để trích xuất các chỉ số cụ thể từ một trục đơn của tensor.

print(tf.gather(t1,
                indices=[0, 3, 6]))

# This is similar to doing

t1[::3]
tf.Tensor([0 3 6], shape=(3,), dtype=int32)
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([0, 3, 6], dtype=int32)>

tf.gather không yêu cầu các chỉ số phải cách đều nhau.

alphabet = tf.constant(list('abcdefghijklmnopqrstuvwxyz'))

print(tf.gather(alphabet,
                indices=[2, 0, 19, 18]))
tf.Tensor([b'c' b'a' b't' b's'], shape=(4,), dtype=string)

Để trích xuất các lát từ nhiều trục của tensor, hãy sử dụng tf.gather_nd . Điều này hữu ích khi bạn muốn thu thập các phần tử của ma trận thay vì chỉ các hàng hoặc cột của nó.

t4 = tf.constant([[0, 5],
                  [1, 6],
                  [2, 7],
                  [3, 8],
                  [4, 9]])

print(tf.gather_nd(t4,
                   indices=[[2], [3], [0]]))
tf.Tensor(
[[2 7]
 [3 8]
 [0 5]], shape=(3, 2), dtype=int32)

t5 = np.reshape(np.arange(18), [2, 3, 3])

print(tf.gather_nd(t5,
                   indices=[[0, 0, 0], [1, 2, 1]]))
tf.Tensor([ 0 16], shape=(2,), dtype=int64)
# Return a list of two matrices

print(tf.gather_nd(t5,
                   indices=[[[0, 0], [0, 2]], [[1, 0], [1, 2]]]))
tf.Tensor(
[[[ 0  1  2]
  [ 6  7  8]]

 [[ 9 10 11]
  [15 16 17]]], shape=(2, 2, 3), dtype=int64)
# Return one matrix

print(tf.gather_nd(t5,
                   indices=[[0, 0], [0, 2], [1, 0], [1, 2]]))
tf.Tensor(
[[ 0  1  2]
 [ 6  7  8]
 [ 9 10 11]
 [15 16 17]], shape=(4, 3), dtype=int64)

Chèn dữ liệu vào tensors

Sử dụng tf.scatter_nd để chèn dữ liệu tại các lát / chỉ số cụ thể của tensor. Lưu ý rằng tensor mà bạn chèn các giá trị không được khởi tạo.

t6 = tf.constant([10])
indices = tf.constant([[1], [3], [5], [7], [9]])
data = tf.constant([2, 4, 6, 8, 10])

print(tf.scatter_nd(indices=indices,
                    updates=data,
                    shape=t6))
tf.Tensor([ 0  2  0  4  0  6  0  8  0 10], shape=(10,), dtype=int32)

Các phương thức như tf.scatter_nd yêu cầu các tensor khởi tạo bằng 0 tương tự như các bộ khởi tạo tensor thưa thớt. Bạn có thể sử dụng tf.gather_ndtf.scatter_nd để bắt chước hành vi của các hoạt động tensor thưa thớt.

Hãy xem xét một ví dụ trong đó bạn xây dựng một tensor thưa thớt bằng cách sử dụng hai phương pháp này kết hợp với nhau.

# Gather values from one tensor by specifying indices

new_indices = tf.constant([[0, 2], [2, 1], [3, 3]])
t7 = tf.gather_nd(t2, indices=new_indices)

# Add these values into a new tensor

t8 = tf.scatter_nd(indices=new_indices, updates=t7, shape=tf.constant([4, 5]))

print(t8)
tf.Tensor(
[[ 0  0  2  0  0]
 [ 0  0  0  0  0]
 [ 0 11  0  0  0]
 [ 0  0  0 18  0]], shape=(4, 5), dtype=int32)

Điều này tương tự như:

t9 = tf.SparseTensor(indices=[[0, 2], [2, 1], [3, 3]],
                     values=[2, 11, 18],
                     dense_shape=[4, 5])

print(t9)
SparseTensor(indices=tf.Tensor(
[[0 2]
 [2 1]
 [3 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([ 2 11 18], shape=(3,), dtype=int32), dense_shape=tf.Tensor([4 5], shape=(2,), dtype=int64))
# Convert the sparse tensor into a dense tensor

t10 = tf.sparse.to_dense(t9)

print(t10)
tf.Tensor(
[[ 0  0  2  0  0]
 [ 0  0  0  0  0]
 [ 0 11  0  0  0]
 [ 0  0  0 18  0]], shape=(4, 5), dtype=int32)

Để chèn dữ liệu vào tensor với các giá trị tồn tại trước, hãy sử dụng tf.tensor_scatter_nd_add .

t11 = tf.constant([[2, 7, 0],
                   [9, 0, 1],
                   [0, 3, 8]])

# Convert the tensor into a magic square by inserting numbers at appropriate indices

t12 = tf.tensor_scatter_nd_add(t11,
                               indices=[[0, 2], [1, 1], [2, 0]],
                               updates=[6, 5, 4])

print(t12)
tf.Tensor(
[[2 7 6]
 [9 5 1]
 [4 3 8]], shape=(3, 3), dtype=int32)

Tương tự, sử dụng tf.tensor_scatter_nd_sub để trừ các giá trị từ tensor với các giá trị tồn tại trước.

# Convert the tensor into an identity matrix

t13 = tf.tensor_scatter_nd_sub(t11,
                               indices=[[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [2, 1], [2, 2]],
                               updates=[1, 7, 9, -1, 1, 3, 7])

print(t13)
tf.Tensor(
[[1 0 0]
 [0 1 0]
 [0 0 1]], shape=(3, 3), dtype=int32)

Sử dụng tf.tensor_scatter_nd_min để sao chép các giá trị tối thiểu của phần tử từ tensor này sang tensor khác.

t14 = tf.constant([[-2, -7, 0],
                   [-9, 0, 1],
                   [0, -3, -8]])

t15 = tf.tensor_scatter_nd_min(t14,
                               indices=[[0, 2], [1, 1], [2, 0]],
                               updates=[-6, -5, -4])

print(t15)
tf.Tensor(
[[-2 -7 -6]
 [-9 -5  1]
 [-4 -3 -8]], shape=(3, 3), dtype=int32)

Tương tự, sử dụng tf.tensor_scatter_nd_max để sao chép các giá trị lớn nhất của phần tử từ tensor này sang tensor khác.

t16 = tf.tensor_scatter_nd_max(t14,
                               indices=[[0, 2], [1, 1], [2, 0]],
                               updates=[6, 5, 4])

print(t16)
tf.Tensor(
[[-2 -7  6]
 [-9  5  1]
 [ 4 -3 -8]], shape=(3, 3), dtype=int32)

Đọc thêm và tài nguyên

Trong hướng dẫn này, bạn đã học cách sử dụng các hoạt động cắt tensor có sẵn với TensorFlow để kiểm soát tốt hơn các phần tử trong tensor của bạn.