Keras - 分类器不从预训练模型的转移值中学习
Keras - Classifier not learning from Transfer-Values of a Pre-Trained Model
我目前正在尝试使用预训练网络并在 this dataset 上进行测试。
最初,我使用的是 VGG19,只是微调了最后的分类器以适应我的 120 类。我让所有层都可以训练,以便通过更深入的训练来提高性能。问题是模型非常慢(即使我让它 运行 一晚上,我也只得到几个 epoch 并达到大约 45% 的准确率——我有一个 GPU GTX 1070)。
然后,我的想法是冻结该模型的所有层,因为我只有 10k 图像并且只训练最后几个 Denses 层,但它仍然不是很快。
看了 this video 之后(大约 2 分 30 秒),我决定用 InceptionResnetv2 复制 Transfer-Values 的原理。
我处理了每张图片并使用以下代码将输出保存在一个 numpy 矩阵中。
# Loading pre-trained Model + freeze layers
model = applications.inception_resnet_v2.InceptionResNetV2(
include_top=False,
weights='imagenet',
pooling='avg')
for layer in model.layers:
layer.trainable = False
# Extraction of features and saving
a = True
for filename in glob.glob('train/resized/*.jpg'):
name_img = os.path.basename(filename)[:-4]
class_ = label[label["id"] == name_img]["breed"].values[0]
input_img = np.expand_dims(np.array(Image.open(filename)), 0)
pred = model.predict(input_img)
if a:
X = np.array(pred)
y = np.array(class_)
a = False
else:
X = np.vstack((X, np.array(pred)))
y = np.vstack((y, class_))
np.savez_compressed('preprocessed.npz', X=X, y=y)
X 是形状为 (10222, 1536) 的矩阵,y 是 (10222, 1)。
之后,我设计了我的分类器(几个拓扑),我不知道为什么它不能进行任何学习。
# Just to One-Hot-Encode labels properly to (10222, 120)
label_binarizer = sklearn.preprocessing.LabelBinarizer()
y = label_binarizer.fit_transform(y)
model = Sequential()
model.add(Dense(512, input_dim=X.shape[1]))
# model.add(Dense(2048, activation="relu"))
# model.add(Dropout(0.5))
# model.add(Dense(256))
model.add(Dense(120, activation='softmax'))
model.compile(
loss = "categorical_crossentropy",
optimizer = "Nadam", # I tried several ones
metrics=["accuracy"]
)
model.fit(X, y, epochs=100, batch_size=64,
callbacks=[early_stop], verbose=1,
shuffle=True, validation_split=0.10)
您可以在下面找到模型的输出:
Train on 9199 samples, validate on 1023 samples
Epoch 1/100
9199/9199 [==============================] - 2s 185us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 2/100
9199/9199 [==============================] - 1s 100us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 3/100
9199/9199 [==============================] - 1s 98us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 4/100
9199/9199 [==============================] - 1s 96us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 5/100
9199/9199 [==============================] - 1s 99us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 6/100
9199/9199 [==============================] - 1s 96us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
我尝试更改拓扑、激活函数、添加 dropout,但没有任何改进。
我不知道我这样做有什么问题。 X 矩阵不正确吗?难道只允许使用预训练模型作为特征提取器,然后用第二个模型进行分类吗?
非常感谢您的反馈,
问候,
尼古拉斯
您需要先调用 preprocess_input
,然后再将图像数组提供给模型。它将 input_img
的值从 [0, 255] 标准化为 [-1, 1],这是 InceptionResNetV2
.
所需的输入范围
input_img = np.expand_dims(np.array(Image.open(filename)), 0)
input_img = applications.inception_resnet_v2.preprocess_input(input_img.astype('float32'))
pred = model.predict(input_img)
我目前正在尝试使用预训练网络并在 this dataset 上进行测试。 最初,我使用的是 VGG19,只是微调了最后的分类器以适应我的 120 类。我让所有层都可以训练,以便通过更深入的训练来提高性能。问题是模型非常慢(即使我让它 运行 一晚上,我也只得到几个 epoch 并达到大约 45% 的准确率——我有一个 GPU GTX 1070)。
然后,我的想法是冻结该模型的所有层,因为我只有 10k 图像并且只训练最后几个 Denses 层,但它仍然不是很快。
看了 this video 之后(大约 2 分 30 秒),我决定用 InceptionResnetv2 复制 Transfer-Values 的原理。
我处理了每张图片并使用以下代码将输出保存在一个 numpy 矩阵中。
# Loading pre-trained Model + freeze layers
model = applications.inception_resnet_v2.InceptionResNetV2(
include_top=False,
weights='imagenet',
pooling='avg')
for layer in model.layers:
layer.trainable = False
# Extraction of features and saving
a = True
for filename in glob.glob('train/resized/*.jpg'):
name_img = os.path.basename(filename)[:-4]
class_ = label[label["id"] == name_img]["breed"].values[0]
input_img = np.expand_dims(np.array(Image.open(filename)), 0)
pred = model.predict(input_img)
if a:
X = np.array(pred)
y = np.array(class_)
a = False
else:
X = np.vstack((X, np.array(pred)))
y = np.vstack((y, class_))
np.savez_compressed('preprocessed.npz', X=X, y=y)
X 是形状为 (10222, 1536) 的矩阵,y 是 (10222, 1)。
之后,我设计了我的分类器(几个拓扑),我不知道为什么它不能进行任何学习。
# Just to One-Hot-Encode labels properly to (10222, 120)
label_binarizer = sklearn.preprocessing.LabelBinarizer()
y = label_binarizer.fit_transform(y)
model = Sequential()
model.add(Dense(512, input_dim=X.shape[1]))
# model.add(Dense(2048, activation="relu"))
# model.add(Dropout(0.5))
# model.add(Dense(256))
model.add(Dense(120, activation='softmax'))
model.compile(
loss = "categorical_crossentropy",
optimizer = "Nadam", # I tried several ones
metrics=["accuracy"]
)
model.fit(X, y, epochs=100, batch_size=64,
callbacks=[early_stop], verbose=1,
shuffle=True, validation_split=0.10)
您可以在下面找到模型的输出:
Train on 9199 samples, validate on 1023 samples
Epoch 1/100
9199/9199 [==============================] - 2s 185us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 2/100
9199/9199 [==============================] - 1s 100us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 3/100
9199/9199 [==============================] - 1s 98us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 4/100
9199/9199 [==============================] - 1s 96us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 5/100
9199/9199 [==============================] - 1s 99us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
Epoch 6/100
9199/9199 [==============================] - 1s 96us/step - loss: 15.9639 - acc: 0.0096 - val_loss: 15.8975 - val_acc: 0.0137
我尝试更改拓扑、激活函数、添加 dropout,但没有任何改进。
我不知道我这样做有什么问题。 X 矩阵不正确吗?难道只允许使用预训练模型作为特征提取器,然后用第二个模型进行分类吗?
非常感谢您的反馈, 问候, 尼古拉斯
您需要先调用 preprocess_input
,然后再将图像数组提供给模型。它将 input_img
的值从 [0, 255] 标准化为 [-1, 1],这是 InceptionResNetV2
.
input_img = np.expand_dims(np.array(Image.open(filename)), 0)
input_img = applications.inception_resnet_v2.preprocess_input(input_img.astype('float32'))
pred = model.predict(input_img)