Ngày Cộng đồng ML là ngày 9 tháng 11! Tham gia với chúng tôi để cập nhật từ TensorFlow, JAX, và nhiều hơn nữa Tìm hiểu thêm

Mô hình tuần tự

Xem trên TensorFlow.org Xem nguồn trên GitHub Tải xuống sổ ghi chép

Cài đặt

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

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

Một Sequential mô hình phù hợp với một chồng đơn giản của lớp mà mỗi lớp có chính xác một tensor đầu vào và một đầu ra tensor.

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

# 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ột tuần tự mô hình không thích 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 đều có nhiều đầu vào hoặc nhiều đầu ra
  • Bạn cần thực hiệ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 nhiều 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 đến phương thức khởi tạo Tuần tự:

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

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

model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>,
 <keras.layers.core.Dense at 0x7fdbbc3c4650>,
 <keras.layers.core.Dense at 0x7fdbbc3c4a10>]

Bạn cũng có thể tạo ra một mô hình tuần tự từng bước thông qua add() phương pháp:

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 tương ứng pop() phương pháp để loại bỏ lớp: một tuần tự cư xử mô hình rất giống với một danh sách các lớp.

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

Cũng lưu ý rằng các nhà xây dựng tuần tự chấp nhận một name đối số, giống như bất kỳ lớp hoặc mô hình trong Keras. Điều này rất hữu ích để chú thích đồ thị TensorBoard bằng 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 trước hình dạng đầu vào

Nói chung, tất cả các lớp trong Keras cần biết hình dạng của các đầu vào để có thể tạo ra 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ố lần đầu tiên 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.5319189 , -0.8767905 , -0.63919735],
        [-0.6276014 ,  0.1689707 , -0.57695866],
        [ 0.6710613 ,  0.5354214 , -0.00893992],
        [ 0.15670097, -0.15280598,  0.8865864 ]], 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ó một hình dạng đầu vào, nó không phải là "xây dựng": nó không có trọng lượng (và gọi model.weights kết quả trong một báo lỗi chỉ 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 nó summary() phương pháp để hiển thị nội dung của nó:

model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_7 (Dense)              (1, 2)                    10        
_________________________________________________________________
dense_8 (Dense)              (1, 3)                    9         
_________________________________________________________________
dense_9 (Dense)              (1, 4)                    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 bắt đầu mô hình của bạn bằng cách thông qua một Input đối tượng để mô hình của bạn, vì vậy mà nó biết hình dạng đầu vào của nó ngay 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 các Input đối tượng 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
[<keras.layers.core.Dense at 0x7fdbbc37c390>]

Một sự thay thế đơn giản là chỉ cần vượt qua một input_shape lập luận để 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 xác định.

Nói chung, cách tốt nhất được khuyến nghị là luôn chỉ định trước 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 gỡ lỗi quy trình làm việc chung: add() + summary()

Khi xây dựng một kiến trúc tuần tự mới, nó là hữu ích để từng bước ngăn xếp lớp với add() và thường xuyên in tóm tắt mô hình. Ví dụ, điều này cho phép bạn giám sát như thế nào một chồng Conv2DMaxPooling2D lớp được downsampling bản đồ tính năng hình ảnh:

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 bằng mô hình Tuần tự

Khi một mô hình tuần tự đã được xây dựng, nó hoạt động như một mô hình API chức năng . Điều này có nghĩa rằng mỗi lớp có một inputoutput thuộc tính. Các thuộc tính này có thể được sử dụng để thực hiện những việc gọn gàng, chẳng hạn như tạo nhanh một mô hình trích xuất đầu ra của tất cả các lớp trung gian trong một 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 chắc chắn để đọc của chúng tôi hướng dẫn để học tập chuyển giao .

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

Đầu tiên, hãy nói 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 ngoại trừ lớp cuối cùng. Trong trường hợp này, bạn sẽ chỉ đơn giản lặp trên model.layers và bộ layer.trainable = False trên mỗi lớp, ngoại trừ người 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ột mô hình được đào tạo trước và một số lớp phân loại mới 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 tiếp, có thể 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ề mô hình Tuần tự!

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