Python: Mô hình tuần tự (Sequential model)
Cài đặt
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ự (Sequeltial model)
Một mô hình Tuần tự (Sequential model)
phù hợp với một chồng các lớp đơn giản trong đó mỗi lớp có chính xác một tenxơ đầu vào và một tenxơ đầu ra.
Sơ đồ, mô hình Sequential
như 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 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ột mô hình Tuần tự bằng cách truyền danh sách các lớp tới hàm tạo Sequential:
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
[<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 dần dần một mô hình Tuần tự 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 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 Sequential 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 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 đầu vào để có thể tạo trọng số 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 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ó hình dạng đầu vào, nó sẽ không được "xây dựng": nó không có trọng số (và lời gọi model.weights
sẽ dẫn đến kết quả là lỗi cho đ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) (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ột 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 mình bằng cách truyền một đối tượng Input
vào mô hình của bạn để mô hình 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 đố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
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Một cách thay thế đơn giản là chỉ truyền một đố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 đượ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 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 xếp chồng dần các lớp bằng cách sử dụng 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 lớp Conv2D
và MaxPooling2D
đang lấy mẫu xuống các bản đồ đặc trưng của 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
Rất thiết thực đúng 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:
- Huấn luyện mô hình của bạn, đánh giá nó và chạy suy luận. Xem hướng dẫn của chúng tôi về đào tạo & đánh giá với các vòng lặp tích hợp
- Lưu mô hình của bạn vào đĩa và khôi phục nó. Xem hướng dẫn của chúng tôi về lập số sê-ri và lưu.
- Tăng tốc độ đào tạo mô hình bằng cách tận dụng nhiều GPU. Xem hướng dẫn của chúng tôi về đào tạo đa GPU và phân tá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ó sẽ 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 đều có thuộc tính input
và output
. 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 kết quả đầ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)
Học dịch chuyển với một mô hình Tuần tự
Học dịch chuyển 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 đảm bảo đọc hướng dẫn của chúng tôi để chuyển giao học tập .
Dưới đây là hai kế hoạch học tập chuyển đổi phổ biến liên quan đến các mô hình Tuần tự.
Đầu tiên, giả sử 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 chỉ cần lặp lại thông qua model.layers
và đặt layer.trainable = False
trên từng 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 một 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(...)