ช่วยปกป้อง Great Barrier Reef กับ TensorFlow บน Kaggle เข้าร่วมท้าทาย

ความรู้เบื้องต้นเกี่ยวกับเทนเซอร์

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค
import tensorflow as tf
import numpy as np

เทนเซอร์เป็นอาร์เรย์หลายมิติที่มีประเภทสม่ำเสมอ (เรียกว่า dtype ) คุณสามารถดู dtypes ที่รองรับทั้งหมดได้ที่ tf.dtypes.DType

หากคุณคุ้นเคยกับ NumPy เทนเซอร์ก็เหมือนกับ np.arrays

เทนเซอร์ทั้งหมดจะไม่เปลี่ยนรูปเหมือนตัวเลขและสตริงของ Python: คุณไม่สามารถอัปเดตเนื้อหาของเทนเซอร์ได้ แต่สร้างใหม่เท่านั้น

พื้นฐาน

มาสร้างเมตริกซ์พื้นฐานกัน

นี่คือเทนเซอร์ "สเกลาร์" หรือ "อันดับ-0" สเกลาร์มีค่าเดียว และไม่มี "แกน"

# This will be an int32 tensor by default; see "dtypes" below.
rank_0_tensor = tf.constant(4)
print(rank_0_tensor)
tf.Tensor(4, shape=(), dtype=int32)

เทนเซอร์ "เวกเตอร์" หรือ "อันดับ-1" เป็นเหมือนรายการค่า เวกเตอร์มีแกนเดียว:

# Let's make this a float tensor.
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
print(rank_1_tensor)
tf.Tensor([2. 3. 4.], shape=(3,), dtype=float32)

"เมทริกซ์" หรือ "อันดับ-2" เทนเซอร์มีสองแกน:

# If you want to be specific, you can set the dtype (see below) at creation time
rank_2_tensor = tf.constant([[1, 2],
                             [3, 4],
                             [5, 6]], dtype=tf.float16)
print(rank_2_tensor)
tf.Tensor(
[[1. 2.]
 [3. 4.]
 [5. 6.]], shape=(3, 2), dtype=float16)
สเกลาร์ รูปร่าง: [] เวกเตอร์ รูปร่าง: [3] เมทริกซ์, รูปร่าง: [3, 2]
สเกลาร์ ตัวเลข 4บรรทัดที่มี 3 ส่วน แต่ละบรรทัดมีตัวเลขตาราง 3x2 โดยแต่ละเซลล์มีตัวเลข

เทนเซอร์อาจมีแกนมากกว่า นี่คือเทนเซอร์ที่มีสามแกน:

# There can be an arbitrary number of
# axes (sometimes called "dimensions")
rank_3_tensor = tf.constant([
  [[0, 1, 2, 3, 4],
   [5, 6, 7, 8, 9]],
  [[10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19]],
  [[20, 21, 22, 23, 24],
   [25, 26, 27, 28, 29]],])

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

มีหลายวิธีที่คุณอาจนึกภาพเมตริกซ์ที่มีมากกว่าสองแกน

เทนเซอร์แบบ 3 แกน รูปร่าง: [3, 2, 5]

คุณสามารถแปลงเทนเซอร์เป็นอาร์เรย์ NumPy โดยใช้ np.array หรือวิธี tensor.numpy :

np.array(rank_2_tensor)
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)
rank_2_tensor.numpy()
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)

เทนเซอร์มักประกอบด้วยทุ่นและอินท์ แต่มีหลายประเภท ได้แก่:

  • ตัวเลขเชิงซ้อน
  • สตริง

คลาส tf.Tensor พื้นฐานต้องการให้เทนเซอร์เป็น "สี่เหลี่ยม" นั่นคือ ทุกองค์ประกอบจะมีขนาดเท่ากันตามแกนแต่ละแกน อย่างไรก็ตาม มีเทนเซอร์ประเภทพิเศษที่สามารถจัดการกับรูปร่างที่แตกต่างกันได้:

  • RaggedTensor (ดู RaggedTensor ด้านล่าง)
  • เทนเซอร์แบบเบาบาง (ดู SparseTensor ด้านล่าง)

คุณสามารถคำนวณพื้นฐานเกี่ยวกับเทนเซอร์ รวมถึงการบวก การคูณตามองค์ประกอบ และการคูณเมทริกซ์

a = tf.constant([[1, 2],
                 [3, 4]])
b = tf.constant([[1, 1],
                 [1, 1]]) # Could have also said `tf.ones([2,2])`

print(tf.add(a, b), "\n")
print(tf.multiply(a, b), "\n")
print(tf.matmul(a, b), "\n")
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

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

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)
print(a + b, "\n") # element-wise addition
print(a * b, "\n") # element-wise multiplication
print(a @ b, "\n") # matrix multiplication
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

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

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)

เทนเซอร์ถูกใช้ในการทำงานทุกประเภท (ops)

c = tf.constant([[4.0, 5.0], [10.0, 1.0]])

# Find the largest value
print(tf.reduce_max(c))
# Find the index of the largest value
print(tf.argmax(c))
# Compute the softmax
print(tf.nn.softmax(c))
tf.Tensor(10.0, shape=(), dtype=float32)
tf.Tensor([1 0], shape=(2,), dtype=int64)
tf.Tensor(
[[2.6894143e-01 7.3105854e-01]
 [9.9987662e-01 1.2339458e-04]], shape=(2, 2), dtype=float32)

เกี่ยวกับรูปร่าง

เทนเซอร์มีรูปร่าง คำศัพท์บางส่วน:

  • รูปร่าง : ความยาว (จำนวนองค์ประกอบ) ของแต่ละแกนของเทนเซอร์
  • อันดับ : จำนวนแกนเทนเซอร์ สเกลาร์มีอันดับ 0 เวกเตอร์มีอันดับ 1 เมทริกซ์มีอันดับ 2
  • แกน หรือ มิติ : มิติเฉพาะของเทนเซอร์
  • ขนาด : จำนวนรวมของรายการในเทนเซอร์ เวกเตอร์รูปร่างของผลิตภัณฑ์

เทนเซอร์และ tf.TensorShape มีคุณสมบัติที่สะดวกสำหรับการเข้าถึงสิ่งเหล่านี้:

rank_4_tensor = tf.zeros([3, 2, 4, 5])
เทนเซอร์อันดับ 4, รูปร่าง: [3, 2, 4, 5]
รูปร่างเทนเซอร์เป็นเหมือนเวกเตอร์เทนเซอร์ 4 แกน
print("Type of every element:", rank_4_tensor.dtype)
print("Number of axes:", rank_4_tensor.ndim)
print("Shape of tensor:", rank_4_tensor.shape)
print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0])
print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1])
print("Total number of elements (3*2*4*5): ", tf.size(rank_4_tensor).numpy())
Type of every element: <dtype: 'float32'>
Number of axes: 4
Shape of tensor: (3, 2, 4, 5)
Elements along axis 0 of tensor: 3
Elements along the last axis of tensor: 5
Total number of elements (3*2*4*5):  120
ตัวยึดตำแหน่ง22

แม้ว่าดัชนีของแกนนั้นมักจะอ้างถึง แต่คุณควรติดตามความหมายของแต่ละแกนเสมอ มักจะเรียงลำดับแกนจากส่วนกลางไปยังท้องถิ่น: แกนชุดงานก่อน ตามด้วยมิติเชิงพื้นที่ และคุณลักษณะสำหรับแต่ละตำแหน่งสุดท้าย วิธีนี้ทำให้เวกเตอร์คุณลักษณะเป็นพื้นที่ต่อเนื่องกันของหน่วยความจำ

ลำดับแกนทั่วไป
ติดตามว่าแต่ละแกนคืออะไร เทนเซอร์แบบ 4 แกนอาจเป็น: Batch, Width, Height, Features

การจัดทำดัชนี

การทำดัชนีแบบแกนเดียว

TensorFlow ปฏิบัติตามกฎการจัดทำดัชนี Python มาตรฐาน คล้ายกับการ จัดทำดัชนีรายการหรือสตริงใน Python และกฎพื้นฐานสำหรับการจัดทำดัชนี NumPy

  • ดัชนีเริ่มต้นที่ 0
  • ดัชนีติดลบนับถอยหลังจากจุดสิ้นสุด
  • โคลอน, : , ใช้สำหรับสไลซ์: start:stop:step
rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])
print(rank_1_tensor.numpy())
[ 0  1  1  2  3  5  8 13 21 34]

การทำดัชนีด้วยสเกลาร์จะลบแกน:

print("First:", rank_1_tensor[0].numpy())
print("Second:", rank_1_tensor[1].numpy())
print("Last:", rank_1_tensor[-1].numpy())
First: 0
Second: 1
Last: 34

การสร้างดัชนีด้วย a : slice ช่วยให้แกน:

print("Everything:", rank_1_tensor[:].numpy())
print("Before 4:", rank_1_tensor[:4].numpy())
print("From 4 to the end:", rank_1_tensor[4:].numpy())
print("From 2, before 7:", rank_1_tensor[2:7].numpy())
print("Every other item:", rank_1_tensor[::2].numpy())
print("Reversed:", rank_1_tensor[::-1].numpy())
Everything: [ 0  1  1  2  3  5  8 13 21 34]
Before 4: [0 1 1 2]
From 4 to the end: [ 3  5  8 13 21 34]
From 2, before 7: [1 2 3 5 8]
Every other item: [ 0  1  3  8 21]
Reversed: [34 21 13  8  5  3  2  1  1  0]

การทำดัชนีแบบหลายแกน

เทนเซอร์อันดับที่สูงกว่าจะถูกสร้างดัชนีโดยผ่านดัชนีหลายตัว

กฎเดียวกันกับในกรณีของแกนเดียวใช้กับแต่ละแกนอย่างอิสระ

print(rank_2_tensor.numpy())
[[1. 2.]
 [3. 4.]
 [5. 6.]]

การผ่านจำนวนเต็มสำหรับแต่ละดัชนี ผลลัพธ์จะเป็นสเกลาร์

# Pull out a single value from a 2-rank tensor
print(rank_2_tensor[1, 1].numpy())
4.0
ตัวยึดตำแหน่ง32

คุณสามารถสร้างดัชนีโดยใช้จำนวนเต็มและการแบ่งส่วน:

# Get row and column tensors
print("Second row:", rank_2_tensor[1, :].numpy())
print("Second column:", rank_2_tensor[:, 1].numpy())
print("Last row:", rank_2_tensor[-1, :].numpy())
print("First item in last column:", rank_2_tensor[0, -1].numpy())
print("Skip the first row:")
print(rank_2_tensor[1:, :].numpy(), "\n")
Second row: [3. 4.]
Second column: [2. 4. 6.]
Last row: [5. 6.]
First item in last column: 2.0
Skip the first row:
[[3. 4.]
 [5. 6.]]

นี่คือตัวอย่างที่มีเทนเซอร์แบบ 3 แกน:

print(rank_3_tensor[:, :, 4])
tf.Tensor(
[[ 4  9]
 [14 19]
 [24 29]], shape=(3, 2), dtype=int32)
ตัวยึดตำแหน่ง36
การเลือกคุณสมบัติสุดท้ายในทุกสถานที่ในแต่ละตัวอย่างในชุด
เทนเซอร์ 3x2x5 พร้อมค่าทั้งหมดที่ดัชนี-4 ของแกนสุดท้ายที่เลือกค่าที่เลือกถูกรวมไว้ในเทนเซอร์ 2 แกน

อ่าน คู่มือการแบ่งเทนเซอร์ เพื่อเรียนรู้วิธีนำการจัดทำดัชนีมาใช้เพื่อจัดการองค์ประกอบแต่ละส่วนในเมตริกซ์ของคุณ

การจัดการรูปร่าง

การปรับรูปร่างเทนเซอร์มีประโยชน์อย่างมาก

# Shape returns a `TensorShape` object that shows the size along each axis
x = tf.constant([[1], [2], [3]])
print(x.shape)
(3, 1)
# You can convert this object into a Python list, too
print(x.shape.as_list())
[3, 1]

คุณสามารถเปลี่ยนเทนเซอร์ให้เป็นรูปร่างใหม่ได้ การดำเนินการ tf.reshape นั้นรวดเร็วและราคาถูก เนื่องจากไม่จำเป็นต้องทำซ้ำข้อมูลพื้นฐาน

# You can reshape a tensor to a new shape.
# Note that you're passing in a list
reshaped = tf.reshape(x, [1, 3])
print(x.shape)
print(reshaped.shape)
(3, 1)
(1, 3)

ข้อมูลจะรักษาเลย์เอาต์ของมันไว้ในหน่วยความจำและสร้างเทนเซอร์ใหม่ โดยมีรูปร่างที่ร้องขอ โดยชี้ไปที่ข้อมูลเดียวกัน TensorFlow ใช้การเรียงลำดับหน่วยความจำ "แถวหลัก" แบบ C โดยที่การเพิ่มดัชนีขวาสุดจะสอดคล้องกับขั้นตอนเดียวในหน่วยความจำ

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

หากคุณปรับเทนเซอร์ให้แบนราบ คุณจะเห็นลำดับที่มันถูกจัดวางในหน่วยความจำ

# A `-1` passed in the `shape` argument says "Whatever fits".
print(tf.reshape(rank_3_tensor, [-1]))
tf.Tensor(
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29], shape=(30,), dtype=int32)

โดยทั่วไปแล้ว การใช้ tf.reshape ที่สมเหตุสมผลเพียงอย่างเดียวคือการรวมหรือแยกแกนที่อยู่ติดกัน (หรือเพิ่ม/ลบ 1 วินาที)

สำหรับเทนเซอร์ 3x2x5 นี้ การปรับรูปร่างใหม่เป็น (3x2)x5 หรือ 3x(2x5) เป็นสิ่งที่สมเหตุสมผลที่ควรทำ เนื่องจากสไลซ์ไม่ผสมกัน:

print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n")
print(tf.reshape(rank_3_tensor, [3, -1]))
tf.Tensor(
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]
 [25 26 27 28 29]], shape=(6, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]], shape=(3, 10), dtype=int32)
รูปร่างที่ดีบางอย่าง
A 3x2x5 เทนเซอร์ข้อมูลเดียวกันเปลี่ยนรูปแบบเป็น (3x2)x5ข้อมูลเดียวกันเปลี่ยนรูปแบบเป็น 3x(2x5)

การปรับรูปร่างใหม่จะ "ใช้งานได้" สำหรับรูปร่างใหม่ใดๆ ที่มีจำนวนองค์ประกอบทั้งหมดเท่ากัน แต่จะไม่มีประโยชน์อะไรหากคุณไม่เคารพลำดับของแกน

การสลับแกนใน tf.reshape ไม่ทำงาน คุณต้องมี tf.transpose สำหรับสิ่งนั้น

# Bad examples: don't do this

# You can't reorder axes with reshape.
print(tf.reshape(rank_3_tensor, [2, 3, 5]), "\n") 

# This is a mess
print(tf.reshape(rank_3_tensor, [5, 6]), "\n")

# This doesn't work at all
try:
  tf.reshape(rank_3_tensor, [7, -1])
except Exception as e:
  print(f"{type(e).__name__}: {e}")
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]]

 [[15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]]], shape=(2, 3, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]
 [24 25 26 27 28 29]], shape=(5, 6), dtype=int32) 

InvalidArgumentError: Input to reshape is a tensor with 30 values, but the requested shape requires a multiple of 7 [Op:Reshape]
ตัวยึดตำแหน่ง51
การเปลี่ยนแปลงรูปร่างที่ไม่ดีบางอย่าง
คุณไม่สามารถเรียงลำดับแกนใหม่ได้ ใช้ tf.transpose สำหรับสิ่งนั้นอะไรก็ตามที่ผสมผสานส่วนของข้อมูลเข้าด้วยกันอาจเป็นสิ่งที่ผิดรูปทรงใหม่ต้องพอดีเป๊ะ

คุณอาจวิ่งข้ามรูปร่างที่ไม่ได้ระบุทั้งหมด รูปร่างอาจมีค่า None (ไม่ทราบความยาวแกน) หรือรูปร่างทั้งหมด None (ไม่ทราบลำดับของเมตริกซ์)

ยกเว้น tf.RaggedTensor รูปร่างดังกล่าวจะเกิดขึ้นในบริบทของ API การสร้างกราฟเชิงสัญลักษณ์ของ TensorFlow เท่านั้น:

เพิ่มเติมเกี่ยวกับ DTypes

ในการตรวจสอบชนิดข้อมูลของ tf.Tensor ให้ใช้คุณสมบัติ Tensor.dtype

เมื่อสร้าง tf.Tensor จากวัตถุ Python คุณสามารถเลือกระบุประเภทข้อมูลได้

หากคุณไม่ทำเช่นนั้น TensorFlow จะเลือกประเภทข้อมูลที่สามารถแสดงข้อมูลของคุณได้ TensorFlow แปลงจำนวนเต็ม Python เป็น tf.int32 และตัวเลขทศนิยมของ Python เป็น tf.float32 มิฉะนั้น TensorFlow จะใช้กฎเดียวกันกับที่ NumPy ใช้เมื่อแปลงเป็นอาร์เรย์

คุณสามารถส่งจากประเภทไปยังประเภท

the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64)
the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16)
# Now, cast to an uint8 and lose the decimal precision
the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)
print(the_u8_tensor)
tf.Tensor([2 3 4], shape=(3,), dtype=uint8)
ตัวยึดตำแหน่ง53

ออกอากาศ

การออกอากาศเป็นแนวคิดที่ยืมมาจาก คุณลักษณะที่เทียบเท่าใน NumPy กล่าวโดยย่อ ภายใต้เงื่อนไขบางประการ เทนเซอร์ขนาดเล็กจะถูก "ยืด" โดยอัตโนมัติเพื่อให้พอดีกับเทนเซอร์ที่ใหญ่ขึ้นเมื่อใช้งานร่วมกัน

กรณีที่ง่ายที่สุดและพบบ่อยที่สุดคือเมื่อคุณพยายามคูณหรือบวกเทนเซอร์ให้กับสเกลาร์ ในกรณีนั้น สเกลาร์จะถูกถ่ายทอดให้เป็นรูปร่างเดียวกับอาร์กิวเมนต์อื่น

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

y = tf.constant(2)
z = tf.constant([2, 2, 2])
# All of these are the same computation
print(tf.multiply(x, 2))
print(x * y)
print(x * z)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
ตัวยึดตำแหน่ง55

ในทำนองเดียวกัน แกนที่มีความยาว 1 สามารถยืดออกเพื่อให้ตรงกับอาร์กิวเมนต์อื่นๆ ได้ อาร์กิวเมนต์ทั้งสองสามารถขยายได้ในการคำนวณเดียวกัน

ในกรณีนี้ เมทริกซ์ 3x1 จะถูกคูณด้วยองค์ประกอบโดยคูณด้วยเมทริกซ์ 1x4 เพื่อสร้างเมทริกซ์ขนาด 3x4 โปรดทราบว่าการนำ 1 เป็นตัวเลือก: รูปร่างของ y คือ [4]

# These are the same computations
x = tf.reshape(x,[3,1])
y = tf.range(1, 5)
print(x, "\n")
print(y, "\n")
print(tf.multiply(x, y))
tf.Tensor(
[[1]
 [2]
 [3]], shape=(3, 1), dtype=int32) 

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

tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)
การเพิ่มที่ออกอากาศ: a [3, 1] คูณ a [1, 4] ให้ [3,4]
การเพิ่มเมทริกซ์ 3x1 ให้กับเมทริกซ์ 4x1 จะทำให้ได้เมทริกซ์ 3x4

นี่คือการดำเนินการเดียวกันโดยไม่ต้องแพร่ภาพ:

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

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

print(x_stretch * y_stretch)  # Again, operator overloading
tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)

ส่วนใหญ่แล้ว การออกอากาศจะเป็นทั้งเวลาและพื้นที่อย่างมีประสิทธิภาพ เนื่องจากการดำเนินการออกอากาศไม่เคยทำให้เทนเซอร์ขยายออกมาเป็นรูปเป็นร่างในหน่วยความจำ

คุณเห็นว่าการออกอากาศเป็นอย่างไรโดยใช้ tf.broadcast_to

print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))
tf.Tensor(
[[1 2 3]
 [1 2 3]
 [1 2 3]], shape=(3, 3), dtype=int32)

ต่างจาก op ทางคณิตศาสตร์เช่น broadcast_to ไม่ได้ทำอะไรพิเศษเพื่อบันทึกหน่วยความจำ ที่นี่คุณกำลังทำให้เมตริกซ์เป็นจริง

มันอาจจะซับซ้อนมากขึ้น ส่วนนี้ ของ คู่มือ Python Data Science Handbook ของ Jake VanderPlas แสดงเทคนิคการออกอากาศเพิ่มเติม (อีกครั้งใน NumPy)

tf.convert_to_tensor

ops ส่วนใหญ่ เช่น tf.matmul และ tf.reshape รับข้อโต้แย้งของคลาส tf.Tensor อย่างไรก็ตาม คุณจะสังเกตเห็นในกรณีข้างต้น ยอมรับวัตถุ Python ที่มีรูปร่างเหมือนเทนเซอร์

ops ส่วนใหญ่ แต่ไม่ใช่ทั้งหมด เรียก convert_to_tensor บนอาร์กิวเมนต์ที่ไม่ใช่เทนเซอร์ มีการลงทะเบียนของการแปลง และคลาสอ็อบเจ็กต์ส่วนใหญ่ เช่น ndarray ของ NumPy , TensorShape , รายการ Python และ tf.Variable จะทำการแปลงทั้งหมดโดยอัตโนมัติ

ดู tf.register_tensor_conversion_function สำหรับรายละเอียดเพิ่มเติม และหากคุณมีประเภทของคุณเอง คุณต้องการแปลงเป็นเมตริกซ์โดยอัตโนมัติ

Ragged Tensors

เทนเซอร์ที่มีจำนวนองค์ประกอบแปรผันตามแกนบางแกนเรียกว่า "มอมแมม" ใช้ tf.ragged.RaggedTensor สำหรับข้อมูลที่ขาดหายไป

ตัวอย่างเช่น สิ่งนี้ไม่สามารถแสดงเป็นเมตริกซ์ปกติได้:

tf.RaggedTensor , รูปร่าง: [4, None]
เทนเซอร์มอมแมม 2 แกน แต่ละแถวสามารถมีความยาวต่างกันได้
ragged_list = [
    [0, 1, 2, 3],
    [4, 5],
    [6, 7, 8],
    [9]]
try:
  tensor = tf.constant(ragged_list)
except Exception as e:
  print(f"{type(e).__name__}: {e}")
ValueError: Can't convert non-rectangular Python sequence to Tensor.

ให้สร้าง tf.RaggedTensor โดยใช้ tf.ragged.constant :

ragged_tensor = tf.ragged.constant(ragged_list)
print(ragged_tensor)
<tf.RaggedTensor [[0, 1, 2, 3], [4, 5], [6, 7, 8], [9]]>

รูปร่างของ tf.RaggedTensor จะมีแกนบางอันที่ไม่ทราบความยาว:

print(ragged_tensor.shape)
(4, None)

เทนเซอร์สตริง

tf.string เป็น dtype ซึ่งก็คือคุณสามารถแสดงข้อมูลเป็นสตริง (อาร์เรย์ไบต์ที่มีความยาวแปรผันได้) ในเทนเซอร์

สตริงเป็นแบบอะตอมมิกและไม่สามารถจัดทำดัชนีแบบสตริง Python ความยาวของสตริงไม่ใช่หนึ่งในแกนของเทนเซอร์ ดู tf.strings สำหรับฟังก์ชันเพื่อจัดการ

นี่คือเทนเซอร์สตริงสเกลาร์:

# Tensors can be strings, too here is a scalar string.
scalar_string_tensor = tf.constant("Gray wolf")
print(scalar_string_tensor)
tf.Tensor(b'Gray wolf', shape=(), dtype=string)

และเวกเตอร์ของสตริง:

เวกเตอร์ของสตริง รูปร่าง: [3,]
ความยาวสตริงไม่ใช่แกนหนึ่งของเทนเซอร์
# If you have three string tensors of different lengths, this is OK.
tensor_of_strings = tf.constant(["Gray wolf",
                                 "Quick brown fox",
                                 "Lazy dog"])
# Note that the shape is (3,). The string length is not included.
print(tensor_of_strings)
tf.Tensor([b'Gray wolf' b'Quick brown fox' b'Lazy dog'], shape=(3,), dtype=string)
ตัวยึดตำแหน่ง72

ในผลงานพิมพ์ด้านบน b คำนำหน้าระบุว่า tf.string dtype ไม่ใช่สตริง Unicode แต่เป็นสตริงไบต์ ดูบทช่วย สอน Unicode สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับข้อความ Unicode ใน TensorFlow

หากคุณส่งอักขระ Unicode อักขระเหล่านี้จะถูกเข้ารหัส utf-8

tf.constant("🥳👍")
<tf.Tensor: shape=(), dtype=string, numpy=b'\xf0\x9f\xa5\xb3\xf0\x9f\x91\x8d'>

ฟังก์ชันพื้นฐานบางอย่างที่มีสตริงสามารถพบได้ใน tf.strings รวมถึง tf.strings.split

# You can use split to split a string into a set of tensors
print(tf.strings.split(scalar_string_tensor, sep=" "))
tf.Tensor([b'Gray' b'wolf'], shape=(2,), dtype=string)
# ...but it turns into a `RaggedTensor` if you split up a tensor of strings,
# as each string might be split into a different number of parts.
print(tf.strings.split(tensor_of_strings))
<tf.RaggedTensor [[b'Gray', b'wolf'], [b'Quick', b'brown', b'fox'], [b'Lazy', b'dog']]>
สามสายแยก, รูปร่าง: [3, None]
การแยกหลายสตริงจะคืนค่า tf.RaggedTensor

และ tf.string.to_number :

text = tf.constant("1 10 100")
print(tf.strings.to_number(tf.strings.split(text, " ")))
tf.Tensor([  1.  10. 100.], shape=(3,), dtype=float32)

แม้ว่าคุณจะใช้ tf.cast เพื่อเปลี่ยนเทนเซอร์สตริงเป็นตัวเลขไม่ได้ แต่คุณแปลงเป็นไบต์แล้วแปลงเป็นตัวเลขได้

byte_strings = tf.strings.bytes_split(tf.constant("Duck"))
byte_ints = tf.io.decode_raw(tf.constant("Duck"), tf.uint8)
print("Byte strings:", byte_strings)
print("Bytes:", byte_ints)
Byte strings: tf.Tensor([b'D' b'u' b'c' b'k'], shape=(4,), dtype=string)
Bytes: tf.Tensor([ 68 117  99 107], shape=(4,), dtype=uint8)
# Or split it up as unicode and then decode it
unicode_bytes = tf.constant("アヒル 🦆")
unicode_char_bytes = tf.strings.unicode_split(unicode_bytes, "UTF-8")
unicode_values = tf.strings.unicode_decode(unicode_bytes, "UTF-8")

print("\nUnicode bytes:", unicode_bytes)
print("\nUnicode chars:", unicode_char_bytes)
print("\nUnicode values:", unicode_values)
Unicode bytes: tf.Tensor(b'\xe3\x82\xa2\xe3\x83\x92\xe3\x83\xab \xf0\x9f\xa6\x86', shape=(), dtype=string)

Unicode chars: tf.Tensor([b'\xe3\x82\xa2' b'\xe3\x83\x92' b'\xe3\x83\xab' b' ' b'\xf0\x9f\xa6\x86'], shape=(5,), dtype=string)

Unicode values: tf.Tensor([ 12450  12498  12523     32 129414], shape=(5,), dtype=int32)

tf.string tf.string ใช้สำหรับข้อมูลไบต์ดิบทั้งหมดใน TensorFlow โมดูล tf.io มีฟังก์ชันสำหรับการแปลงข้อมูลเป็นและจากไบต์ รวมถึงการถอดรหัสรูปภาพและการแยกวิเคราะห์ csv

เทนเซอร์แบบเบาบาง

บางครั้ง ข้อมูลของคุณก็กระจัดกระจาย เช่น พื้นที่ฝังที่กว้างมาก TensorFlow รองรับ tf.sparse.SparseTensor และการดำเนินการที่เกี่ยวข้องเพื่อจัดเก็บข้อมูลแบบกระจายอย่างมีประสิทธิภาพ

tf.SparseTensor , รูปร่าง: [3, 4]
ตาราง 3x4 ที่มีค่าในสองเซลล์เท่านั้น
# Sparse tensors store values by index in a memory-efficient manner
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
                                       values=[1, 2],
                                       dense_shape=[3, 4])
print(sparse_tensor, "\n")

# You can convert sparse tensors to dense
print(tf.sparse.to_dense(sparse_tensor))
SparseTensor(indices=tf.Tensor(
[[0 0]
 [1 2]], shape=(2, 2), dtype=int64), values=tf.Tensor([1 2], shape=(2,), dtype=int32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64)) 

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