Trang này được dịch bởi Cloud Translation API.
Switch to English

Mô hình tuần tự

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải vở

Thiết lập

 import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
 

Khi nào nên sử dụng mô hình tuần tự

Một mô hình Sequential thích hợp cho một lớp đơn giản các lớp trong đó mỗi lớp có chính xác một tenxơ đầu vào và một tenxơ đầu ra .

Theo sơ đồ, mô hình Sequential sau:

 # Define Sequential model with 3 layers
model = keras.Sequential(
    [
        layers.Dense(2, activation="relu", name="layer1"),
        layers.Dense(3, activation="relu", name="layer2"),
        layers.Dense(4, name="layer3"),
    ]
)
# Call model on a test input
x = tf.ones((3, 3))
y = model(x)
 

tương đương với chức năng này:

 # Create 3 layers
layer1 = layers.Dense(2, activation="relu", name="layer1")
layer2 = layers.Dense(3, activation="relu", name="layer2")
layer3 = layers.Dense(4, name="layer3")

# Call layers on a test input
x = tf.ones((3, 3))
y = layer3(layer2(layer1(x)))
 

Mô hình tuần tự không phù hợp khi:

  • Mô hình của bạn có nhiều đầu vào hoặc nhiều đầu ra
  • Bất kỳ lớp nào của bạn có nhiều đầu vào hoặc nhiều đầu ra
  • Bạn cần chia sẻ lớp
  • Bạn muốn cấu trúc liên kết phi tuyến tính (ví dụ: kết nối dư, mô hình đa nhánh)

Tạo mô hình tuần tự

Bạn có thể tạo mô hình Tuần tự bằng cách chuyển danh sách các lớp cho hàm tạo tuần tự:

 model = keras.Sequential(
    [
        layers.Dense(2, activation="relu"),
        layers.Dense(3, activation="relu"),
        layers.Dense(4),
    ]
)
 

Các lớp của nó có thể truy cập thông qua thuộc tính layers :

 model.layers
 
[<tensorflow.python.keras.layers.core.Dense at 0x7f37ffe66668>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f37f553fc50>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f37680de2b0>]

Bạn cũng có thể tạo mô hình tuần tự tăng dần thông qua phương thức add() :

 model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
 

Lưu ý rằng cũng có một phương thức pop() tương ứng để loại bỏ các lớp: một mô hình tuần tự hoạt động rất giống như một danh sách các lớp.

 model.pop()
print(len(model.layers))  # 2
 
2

Cũng lưu ý rằng hàm tạo tuần tự chấp nhận một đối số name , giống như bất kỳ lớp hoặc mô hình nào trong Keras. Điều này rất hữu ích để chú thích các biểu đồ TensorBoard với các tên có ý nghĩa về mặt ngữ nghĩa.

 model = keras.Sequential(name="my_sequential")
model.add(layers.Dense(2, activation="relu", name="layer1"))
model.add(layers.Dense(3, activation="relu", name="layer2"))
model.add(layers.Dense(4, name="layer3"))
 

Chỉ định hình dạng đầu vào trước

Nói chung, tất cả các lớp trong Keras cần biết hình dạng của đầu vào của chúng để có thể tạo trọng lượng của chúng. Vì vậy, khi bạn tạo một lớp như thế này, ban đầu, nó không có trọng số:

 layer = layers.Dense(3)
layer.weights  # Empty
 
[]

Nó tạo ra các trọng số của nó trong lần đầu tiên được gọi trên một đầu vào, vì hình dạng của các trọng số phụ thuộc vào hình dạng của các đầu vào:

 # Call layer on a test input
x = tf.ones((1, 4))
y = layer(x)
layer.weights  # Now it has weights, of shape (4, 3) and (3,)
 
[<tf.Variable 'dense_6/kernel:0' shape=(4, 3) dtype=float32, numpy=
 array([[-0.8131663 , -0.49988765, -0.02397203],
        [-0.3190418 ,  0.01101786,  0.85226357],
        [-0.602435  , -0.10381919,  0.63280225],
        [-0.3388477 ,  0.11859643, -0.10677373]], dtype=float32)>,
 <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

Đương nhiên, điều này cũng áp dụng cho các mô hình tuần tự. Khi bạn khởi tạo một mô hình Tuần tự mà không có hình dạng đầu vào, nó không được "xây dựng": nó không có trọng số (và gọi model.weights dẫn đến một lỗi chỉ nêu điều này). Các trọng số được tạo khi mô hình lần đầu tiên nhìn thấy một số dữ liệu đầu vào:

 model = keras.Sequential(
    [
        layers.Dense(2, activation="relu"),
        layers.Dense(3, activation="relu"),
        layers.Dense(4),
    ]
)  # No weights at this stage!

# At this point, you can't do this:
# model.weights

# You also can't do this:
# model.summary()

# Call the model on a test input
x = tf.ones((1, 4))
y = model(x)
print("Number of weights after calling the model:", len(model.weights))  # 6
 
Number of weights after calling the model: 6

Khi một mô hình được "xây dựng", bạn có thể gọi phương thức summary() của nó để hiển thị nội dung của nó:

 model.summary()
 
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_7 (Dense)              multiple                  10        
_________________________________________________________________
dense_8 (Dense)              multiple                  9         
_________________________________________________________________
dense_9 (Dense)              multiple                  16        
=================================================================
Total params: 35
Trainable params: 35
Non-trainable params: 0
_________________________________________________________________

Tuy nhiên, nó có thể rất hữu ích khi xây dựng mô hình Tuần tự tăng dần để có thể hiển thị tóm tắt của mô hình cho đến nay, bao gồm cả hình dạng đầu ra hiện tại. Trong trường hợp này, bạn nên khởi động mô hình của mình bằng cách chuyển một đối tượng Input mô hình của bạn để nó biết hình dạng đầu vào của nó từ đầu:

 model = keras.Sequential()
model.add(keras.Input(shape=(4,)))
model.add(layers.Dense(2, activation="relu"))

model.summary()
 
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_10 (Dense)             (None, 2)                 10        
=================================================================
Total params: 10
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________

Lưu ý rằng đối tượng Input không được hiển thị như một phần của model.layers , vì nó không phải là một lớp:

 model.layers
 
[<tensorflow.python.keras.layers.core.Dense at 0x7f37680deb00>]

Một cách khác đơn giản là chỉ truyền đối số input_shape cho lớp đầu tiên của bạn:

 model = keras.Sequential()
model.add(layers.Dense(2, activation="relu", input_shape=(4,)))

model.summary()
 
Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_11 (Dense)             (None, 2)                 10        
=================================================================
Total params: 10
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________

Các mô hình được xây dựng với hình dạng đầu vào được xác định trước như thế này luôn có trọng số (ngay cả trước khi nhìn thấy bất kỳ dữ liệu nào) và luôn có hình dạng đầu ra được xác định.

Nói chung, cách tốt nhất là luôn luôn chỉ định hình dạng đầu vào của mô hình Tuần tự nếu bạn biết nó là gì.

Một quy trình gỡ lỗi phổ biến: add() + summary()

Khi xây dựng một kiến ​​trúc tuần tự mới, sẽ rất hữu ích khi tăng dần các lớp với add() và thường xuyên in các bản tóm tắt mô hình. Chẳng hạn, điều này cho phép bạn theo dõi cách một chồng các Conv2DMaxPooling2D là bản đồ tính năng hình ảnh xuống dưới:

 model = keras.Sequential()
model.add(keras.Input(shape=(250, 250, 3)))  # 250x250 RGB images
model.add(layers.Conv2D(32, 5, strides=2, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))

# Can you guess what the current output shape is at this point? Probably not.
# Let's just print it:
model.summary()

# The answer was: (40, 40, 32), so we can keep downsampling...

model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(2))

# And now?
model.summary()

# Now that we have 4x4 feature maps, time to apply global max pooling.
model.add(layers.GlobalMaxPooling2D())

# Finally, we add a classification layer.
model.add(layers.Dense(10))
 
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 123, 123, 32)      2432      
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 121, 121, 32)      9248      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 40, 40, 32)        0         
=================================================================
Total params: 11,680
Trainable params: 11,680
Non-trainable params: 0
_________________________________________________________________
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 123, 123, 32)      2432      
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 121, 121, 32)      9248      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 40, 40, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 38, 38, 32)        9248      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 36, 36, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 32)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 10, 10, 32)        9248      
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 8, 8, 32)          9248      
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 32)          0         
=================================================================
Total params: 48,672
Trainable params: 48,672
Non-trainable params: 0
_________________________________________________________________

Rất thực tế, phải không?

Phải làm gì khi bạn có một mô hình

Khi kiến ​​trúc mô hình của bạn đã sẵn sàng, bạn sẽ muốn:

Trích xuất tính năng với mô hình tuần tự

Khi một mô hình tuần tự đã được xây dựng, nó hoạt động giống như một mô hình API chức năng . Điều này có nghĩa là mỗi lớp có một thuộc tính inputoutput . Các thuộc tính này có thể được sử dụng để làm những việc gọn gàng, như nhanh chóng tạo ra một mô hình trích xuất đầu ra của tất cả các lớp trung gian trong mô hình Tuần tự:

 initial_model = keras.Sequential(
    [
        keras.Input(shape=(250, 250, 3)),
        layers.Conv2D(32, 5, strides=2, activation="relu"),
        layers.Conv2D(32, 3, activation="relu"),
        layers.Conv2D(32, 3, activation="relu"),
    ]
)
feature_extractor = keras.Model(
    inputs=initial_model.inputs,
    outputs=[layer.output for layer in initial_model.layers],
)

# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
 

Đây là một ví dụ tương tự chỉ trích xuất các tính năng từ một lớp:

 initial_model = keras.Sequential(
    [
        keras.Input(shape=(250, 250, 3)),
        layers.Conv2D(32, 5, strides=2, activation="relu"),
        layers.Conv2D(32, 3, activation="relu", name="my_intermediate_layer"),
        layers.Conv2D(32, 3, activation="relu"),
    ]
)
feature_extractor = keras.Model(
    inputs=initial_model.inputs,
    outputs=initial_model.get_layer(name="my_intermediate_layer").output,
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
 

Chuyển giao việc học với mô hình tuần tự

Học chuyển giao bao gồm đóng băng các lớp dưới cùng trong một mô hình và chỉ đào tạo các lớp trên cùng. Nếu bạn không quen thuộc với nó, hãy nhớ đọc hướng dẫn của chúng tôi để chuyển việc học .

Dưới đây là hai kế hoạch học tập chuyển giao phổ biến liên quan đến các mô hình tuần tự.

Đầu tiên, giả sử rằng bạn có một mô hình Tuần tự và bạn muốn đóng băng tất cả các lớp trừ lớp cuối cùng. Trong trường hợp này, bạn chỉ cần lặp lại trên model.layers và đặt layer.trainable = False trên mỗi lớp, ngoại trừ lớp cuối cùng. Như thế này:

 model = keras.Sequential([
    keras.Input(shape=(784))
    layers.Dense(32, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(10),
])

# Presumably you would want to first load pre-trained weights.
model.load_weights(...)

# Freeze all layers except the last one.
for layer in model.layers[:-1]:
  layer.trainable = False

# Recompile and train (this will only update the weights of the last layer).
model.compile(...)
model.fit(...)
 

Một kế hoạch chi tiết phổ biến khác là sử dụng mô hình Tuần tự để xếp chồng mô hình được đào tạo trước và một số lớp phân loại mới được khởi tạo. Như thế này:

 # Load a convolutional base with pre-trained weights
base_model = keras.applications.Xception(
    weights='imagenet',
    include_top=False,
    pooling='avg')

# Freeze the base model
base_model.trainable = False

# Use a Sequential model to add a trainable classifier on top
model = keras.Sequential([
    base_model,
    layers.Dense(1000),
])

# Compile & train
model.compile(...)
model.fit(...)
 

Nếu bạn học chuyển, có lẽ bạn sẽ thấy mình thường xuyên sử dụng hai mẫu này.

Đó là tất cả những gì bạn cần biết về các mô hình Tuần tự!

Để tìm hiểu thêm về các mô hình xây dựng trong Keras, hãy xem: