我是一个深度学习和Keras/TensorFlow的初学者。我已经按照tensorflow.org上的第一个教程进行了学习:使用时尚MNIST进行基本分类。
在这种情况下,输入数据是60000张28×28的图像,模型如下:
model = keras.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(128, activation=tf.nn.relu), keras.layers.Dense(10, activation=tf.nn.softmax)])
编译方式如下:
model.compile(optimizer=tf.train.AdamOptimizer(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
训练结束时,模型的准确率如下:
10000/10000 [==============================] - 0s 21us/stepTest accuracy: 0.8769
这是正常的。现在我尝试使用另一组数据复制这个模型。新输入是从kaggle下载的数据集。
数据集包含不同大小的狗和猫的图片,因此我创建了一个简单的脚本来获取图片,将它们调整为28×28像素,并转换为numpy数组。
以下是执行此操作的代码:
import tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_imgfrom tensorflow.keras.models import load_modelfrom PIL import Imageimport os# Helper librariesimport numpy as np# base path datasetbase_path = './dataset/'training_path = base_path + "training_set/"test_path = base_path + "test_set/"# size rate of imagessize = 28, 28# train_images = []train_labels = []test_images = []test_labels = []classes = ['dogs', 'cats']# Scorre sulle cartelle contenute nel path e trasforma le immagini in nparraydef from_files_to_nparray(path): images = [] labels = [] for subfolder in os.listdir(path): if subfolder == '.DS_Store': continue for image_name in os.listdir(path + subfolder): if not image_name.endswith('.jpg'): continue img = Image.open(path + subfolder + "/" + image_name).convert("L").resize(size) # convert to grayscale and resize npimage = np.asarray(img) images.append(npimage) labels.append(classes.index(subfolder)) img.close() # convertt to np arrays images = np.asarray(images) labels = np.asarray(labels) # Normalize to [0, 1] images = images / 255.0 return (images, labels)(train_images, train_labels) = from_files_to_nparray(training_path)(test_images, test_labels) = from_files_to_nparray(test_path)
最后,我得到的形状如下:
Train images shape : (8000, 128, 128)Labels images shape : (8000,)Test images shape : (2000, 128, 128)Test images shape : (2000,)
在训练了相同的模型(但最后的Dense层改为2个神经元)后,我得到了以下结果,应该是正常的:
Train images shape : (8000, 28, 28)Labels images shape : (8000,)Test images shape : (2000, 28, 28)Test images shape : (2000,)_________________________________________________________________Layer (type) Output Shape Param # =================================================================flatten (Flatten) (None, 784) 0 _________________________________________________________________dense (Dense) (None, 128) 100480 _________________________________________________________________dense_1 (Dense) (None, 2) 258 =================================================================Total params: 100,738Trainable params: 100,738Non-trainable params: 0_________________________________________________________________NoneEpoch 1/52018-07-27 15:25:51.283117: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA8000/8000 [==============================] - 1s 66us/step - loss: 0.6924 - acc: 0.5466Epoch 2/58000/8000 [==============================] - 0s 39us/step - loss: 0.6679 - acc: 0.5822Epoch 3/58000/8000 [==============================] - 0s 41us/step - loss: 0.6593 - acc: 0.6048Epoch 4/58000/8000 [==============================] - 0s 39us/step - loss: 0.6545 - acc: 0.6134Epoch 5/58000/8000 [==============================] - 0s 39us/step - loss: 0.6559 - acc: 0.60392000/2000 [==============================] - 0s 33us/stepTest accuracy: 0.592
现在,问题是,如果我尝试将输入大小从28×28更改为例如128×128,结果如下:
Train images shape : (8000, 128, 128)Labels images shape : (8000,)Test images shape : (2000, 128, 128)Test images shape : (2000,)_________________________________________________________________Layer (type) Output Shape Param # =================================================================flatten (Flatten) (None, 16384) 0 _________________________________________________________________dense (Dense) (None, 128) 2097280 _________________________________________________________________dense_1 (Dense) (None, 2) 258 =================================================================Total params: 2,097,538Trainable params: 2,097,538Non-trainable params: 0_________________________________________________________________NoneEpoch 1/52018-07-27 15:27:41.966860: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA8000/8000 [==============================] - 4s 483us/step - loss: 8.0341 - acc: 0.4993Epoch 2/58000/8000 [==============================] - 3s 362us/step - loss: 8.0590 - acc: 0.5000Epoch 3/58000/8000 [==============================] - 3s 351us/step - loss: 8.0590 - acc: 0.5000Epoch 4/58000/8000 [==============================] - 3s 342us/step - loss: 8.0590 - acc: 0.5000Epoch 5/58000/8000 [==============================] - 3s 342us/step - loss: 8.0590 - acc: 0.50002000/2000 [==============================] - 0s 217us/stepTest accuracy: 0.5
为什么会这样?即使添加新的Dense层或增加神经元数量,结果仍然相同。
输入大小与模型层之间有什么联系?谢谢!
回答:
问题在于第二个例子中你有更多的参数需要训练。在第一个例子中,你只有10万个参数。你用8千张图像来训练它们。
在第二个例子中,你有200万个参数,你试图用相同数量的图像来训练它们。这行不通,因为自由参数和样本数量之间存在关系。没有确切的公式来计算这种关系,但有一个经验法则,即可训练参数的数量应该少于样本数量。
你可以尝试训练更多的轮次,看看效果如何,但总的来说,复杂模型需要更多的数据。