我正在运行一个CNN用于左右鞋印分类。我有190,000个训练图像,我使用其中的10%进行验证。我的模型设置如下所示。我获取所有图像的路径,读取它们并调整它们的大小。我将图像标准化,然后将其拟合到模型中。我的问题是,我坚持了62.5%的训练准确率,损失约为0.6615-0.6619。我做错了什么吗?我怎么才能阻止这一切的发生?
只是一些有趣的点要注意:
1.我首先在10张图片上测试了这个,我有同样的问题,但将优化器改为adam,批量大小改为4工作。
1.然后,我在越来越多的图像上进行测试,但每次我都需要改变批量大小以提高精度和损失。对于10,000张图像,我不得不使用500的批量大小和优化器rmsprop。然而,精度和损失只有在第10个纪元后才真正开始改变。
1.我现在正在训练190,000张图像,我不能增加批量大小,因为我的GPU是最大的。
imageWidth = 50
imageHeight = 150
def get_filepaths(directory):
file_paths = []
for filename in files:
filepath = os.path.join(root, filename)
file_paths.append(filepath) # Add it to the list.
return file_paths
def cleanUpPaths(fullFilePaths):
cleanPaths = []
for f in fullFilePaths:
if f.endswith(".png"):
cleanPaths.append(f)
return cleanPaths
def getTrainData(paths):
trainData = []
for i in xrange(1,190000,2):
im = image.imread(paths[i])
im = image.imresize(im, (150,50))
im = (im-255)/float(255)
trainData.append(im)
trainData = np.asarray(trainData)
right = np.zeros(47500)
left = np.ones(47500)
trainLabels = np.concatenate((left, right))
trainLabels = np_utils.to_categorical(trainLabels)
return (trainData, trainLabels)
#create the convnet
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(imageWidth,imageHeight,1),strides=1))#32
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu',strides=1))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(1, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (1, 2), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 1)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2, activation='softmax'))
sgd = SGD(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop',metrics=['accuracy'])
#prepare the training data*/
trainPaths = get_filepaths("better1/train")
trainPaths = cleanUpPaths(trainPaths)
(trainData, trainLabels) = getTrainData(trainPaths)
trainData = np.reshape(trainData,(95000,imageWidth,imageHeight,1)).astype('float32')
trainData = (trainData-255)/float(255)
#train the convnet***
model.fit(trainData, trainLabels, batch_size=500, epochs=50, validation_split=0.2)
#/save the model and weights*/
model.save('myConvnet_model5.h5');
model.save_weights('myConvnet_weights5.h5');
字符串
6条答案
按热度按时间ruoxqz4g1#
我已经有这个问题很多次了,所以想做一个小小的回顾和可能的解决方案等,以帮助人们在未来。
问题:模型为它看到的所有数据预测2个(或更多)可能的类之一 *
正在发生建模问题:* 方法1:* 训练时模型的准确率保持在0.5左右(或1/n,其中n是类的数量)。* 方法2:* 获取预测中每个类的计数,并确认它正在预测所有一个类。
修复/检查(按顺序排列):
*复查模型架构:使用
model.summary()
,检查模型。*检查数据标签:确保训练数据的标签在预处理等过程中没有混淆(这种情况会发生!)
*检查Train Data Feeding Is Randomised:确保您不是一次一个类地将训练数据送入模型。例如,如果使用
ImageDataGenerator().flow_from_directory(PATH)
,请检查参数shuffle=True
和batch_size
是否大于1。*检查Pre-Trained Layers Are Not Trainable:**如果使用预训练模型,请确保使用预训练权重的任何层 * 最初 * 都不可训练。对于第一个epoch,只有新添加的(随机初始化的)层应该是可训练的;
for layer in pretrained_model.layers: layer.trainable = False
应该在代码中的某个位置。*降低学习率:将学习率降低10倍并重试。请注意,每次尝试新的学习率时,您都必须完全重新初始化您尝试训练的层。(例如,我遇到了这个问题,直到我降低到
lr=1e-6
才解决,所以继续!)如果你们中的任何人知道更多的修复/检查,可以正确地获得模型训练,那么请做出贡献,我会尝试更新列表。
**请注意,一旦新层最初训练得“足够”,通常会使更多的预训练模型可训练。
5cnsuln72#
你可以尝试在
MaxPooling2D()
之后添加一个BatchNornmalization()
层。这对我很有效。vfhzx4xs3#
我只是有两件事要添加到DBCerigo的伟大名单。
*检查激活函数:有些层默认有
linear
激活函数,如果你不把一些非线性插入到你的模型中,它就不能泛化,所以网络会尝试学习如何线性分离一个非线性的特征空间。确保你有你的非线性设置是一个很好的检查点。*检查模型复杂度:如果你有一个相对简单的模型,它只学习到第一个或第二个epoch,然后就停止了,可能是它试图学习太复杂的东西。尝试使模型更深。这通常发生在使用冻结模型时,只有1或2层未冻结。
虽然第二个可能是显而易见的,我遇到了他的问题一次,我失去了很多时间检查一切(数据,批次,LR.)之前弄清楚。
希望这有帮助
y53ybaqx4#
我会尝试几件事。较低的学习率应该有助于更多的数据。通常,调整优化器应该有所帮助。此外,您的网络似乎非常小,您可能希望通过添加层或增加层中的过滤器数量来增加模型的容量。
关于如何在实践中应用深度学习的更好描述是here。
a64a0gku5#
这可能会帮助那些来自Google的人:
您可能需要检查您的TensorFlow版本。
我在尝试训练一个CNN时遇到了麻烦,无论我怎么尝试,它都不会收敛。我尝试了不同的学习率,优化器,架构,你能想到的。在这一点上,我使用的是我的本地机器,我已经用tensorflow设置了一个conda环境(使用
conda create -n tf-gpu tensorflow-gpu
),安装了tensorflow 2.4.1版本。然后,我决定尝试在Google Colab上使用相同的数据集训练相同的模型,它有tf版本2.15.0,在第一次尝试时,模型收敛得很好。我不确定是什么导致了这种行为。qxgroojn6#
在我的情况下,它是激活功能的问题。我从'sgd'改为'a'