Neural Networks篇(二),让AI分辨猫和狗并优化 | Word count: 642 | Reading time: 2min | Post View:
前言 今天再来做一个神经网络的分类任务,完整代码见 https://github.com/zong4/AILearning。
代码 来看看比上次多了什么。
数据增强 首先是考虑到图像比较少,所以通过旋转缩放来生成新的图像供 AI 训练。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 train_image_generator = ImageDataGenerator(rescale=1. /255 , rotation_range=45 , width_shift_range=.15 , height_shift_range=.15 , horizontal_flip=True , zoom_range=0.5 ) train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size, directory=train_dir, target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary' ) augmented_images = [train_data_gen[0 ][0 ][0 ] for i in range (5 )] plotImages(augmented_images)
效果如下。
模型结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 model = Sequential([ Conv2D(16 , 3 , padding='same' , activation='relu' , input_shape=(IMG_HEIGHT, IMG_WIDTH ,3 )), MaxPooling2D(), Conv2D(32 , 3 , padding='same' , activation='relu' ), MaxPooling2D(), Conv2D(64 , 3 , padding='same' , activation='relu' ), MaxPooling2D(), Flatten(), Dense(512 , activation='relu' ), tf.keras.layers.Dropout(0.5 ), Dense(1 ) ]) model.summary()
可以通过 model.summary() 来查看模型的结构。
结果 这是没有 Dropout 层的结果。
1 accuracy: 0.6516 - loss: 0.6097 - val_accuracy: 0.6931 - val_loss: 0.5868
加上 Dropout 层后,正确率变低了,说明之前的模型过拟合了。
1 accuracy: 0.6129 - loss: 0.6371 - val_accuracy: 0.6618 - val_loss: 0.6068
优化 又加了一层卷积,还是不够。
1 accuracy: 0.6103 - loss: 0.6333 - val_accuracy: 0.6808 - val_loss: 0.5937
提了一下 epoch,正确率提高了。
1 accuracy: 0.7266 - loss: 0.5674 - val_accuracy: 0.7199 - val_loss: 0.5659
提供了更丰富的数据增强。
1 2 3 4 5 6 7 8 9 10 11 train_datagen = ImageDataGenerator( rescale=1. /255 , rotation_range=45 , width_shift_range=0.3 , height_shift_range=0.3 , shear_range=0.3 , zoom_range=[0.7 , 1.3 ], horizontal_flip=True , vertical_flip=True , fill_mode='nearest' )
直接给训练集的正确率干飞掉了,过拟合无疑了。
引入批量归一化层(Batch Normalization)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 model = Sequential([ Conv2D(16 , 3 , padding='same' , input_shape=(IMG_HEIGHT, IMG_WIDTH ,3 )), BatchNormalization(), Activation('relu' ), MaxPooling2D(), Conv2D(32 , 3 , padding='same' ), BatchNormalization(), Activation('relu' ), MaxPooling2D(), Conv2D(64 , 3 , padding='same' ), BatchNormalization(), Activation('relu' ), MaxPooling2D(), Conv2D(128 , 3 , padding='same' ), BatchNormalization(), Activation('relu' ), MaxPooling2D(), Flatten(), Dense(512 , activation='relu' ), tf.keras.layers.Dropout(0.5 ), Dense(1 ) ])
正确率直接烂掉了,应该是数据集太小了。
所以干脆和上一步合一起来训练,好像没什么变化,那我就没头绪了。
修改学习率调度器为余弦退火学习率调度器。
1 2 3 def cosine_annealing_lr (epoch, lr, T_max=100 ): return 0.001 * 0.5 * (1 + np.cos(np.pi * epoch / T_max)) lr_scheduler = LearningRateScheduler(cosine_annealing_lr)
看上去,epoch 不够,还在跳,不过貌似效果还可以。
后记 总之,现在对好多调参手段还没法说出个所以然,只能靠试,所以还是得进行更深入的理论学习,期待以后的文章吧。