fine…世界鸽王立flag第一天就咕咕咕了,今天马上立刻学习以抚慰自己的良心(bushi
起床自我暗示:我真的很喜欢机器学习!就会中计真的一开电脑就学习
概念:CNN(Convolutional Neural Network,卷积神经网络)
用途:对待训练图片中所含冗余信息进行过滤(如:图片不在中央;图片角度倾斜;图片颜色等多余信息)
思想:用卷积提取图片特征,保留轮廓线
卷积
像素和过滤器中对应位置的数值相乘,得到的结果累积。(这一步可以突出中心像素,并且对于n*n的过滤器,对图片进行卷积处理后,最后竖直水平方向上都会少掉(n-1)个像素。
Max Pooling
目的:增强特征,减少数据
对于2*2图像,选取四个格子中最大值保留,相当于选择图像中最明显的一点保留下来。可以突出图像特征,同时把数据减少为原来的1/4。
第一步是收集数据。你会注意到,这里和之前有一点变化,训练数据需要改变维度(shape)。这是因为第一次卷积期望一个包含所有数据的单一张量,所以要把训练数据设置为60000x28x28x1的一个4D列表,测试图像也是如此处理。如果不这样做,会在训练时得到一个错误,因为卷积操作将不能识别数据形状。
即:训练数据和测试数据都要增加一步reshape。(这里我还没有理解得很清楚)
import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
接下来是定义模型。首先要添加一个卷积层。参数是
- 你想要生成的卷积数(过滤器数量)。这个数值是任意的,但最好是从32开始的倍数。
- 卷积的大小(过滤器的大小),在本例中为3x3网格。这是最常用的尺寸。
- 要使用的激活函数 – 在本例中,我们将使用relu,你可能还记得它相当于当x>0时返回x,否则返回0。
- 在第一层,设定输入数据的形状。
在卷积层之后加上一个MaxPooling层,用来压缩图像,同时保持卷积所强调的特征内容。通过为MaxPooling指定(2,2),效果是将图像的大小缩小四分之一。它的想法是创建一个2x2的像素数组,然后选取最大的一个,从而将4个像素变成1个,在整个图像中重复这样做,这样做的结果是将水平像素的数量减半,垂直像素的数量减半,有效地将图像缩小25%。
可以调用model.summary()来查看网络的大小和形状,你会注意到,每一个MaxPooling(池化)层之后,图像的大小都会以这种方式减少为原来的1/4。
即:代码在3层全连接网络基础上增加4层。
model = tf.keras.models.Sequential
([
tf.keras.layers.Conv2D(64,(3,3),activation = 'relu',input_shape = (28,28,1)),
#二维卷积层;过滤器(filter)共64个;每个过滤期是3*3个像素;激活函数依然是relu;规定输入的shape是28*28个像素,一个通道
tf.keras.layers.MaxPooling2D(2,2),
#增强特征
tf.keras.layers.Conv2D(64,(3,3),activation = 'relu'),
tf.keras.layers.MaxPooling2D(2,2),
#一样的卷积和增强,但是不用再次指定输入
tf.keras.layers.Flatten(),
#对输出进行扁平化处理。在这之后,你将拥有与非卷积版本相同的DNN结构,即全连接神经元网络。
tf.keras.layers.Dense(128,activation = 'relu'),
tf.keras.layers.Dense(10,activation = 'softmax')
#含有128个神经元的全连接层,以及10个神经元的输出层。
])
也可以:
model = keras.Sequential()
model.add(keras.layers.Conv2D(64,(3,3),activation = 'relu',input_shape = (28,28,1)))
model.add(keras.layers.MaxPooling(2,2))
...
卷积神经网络训练时间要更长,但是和全连接神经网络相比,精度高而loss小。
通过model.summary()函数,可以看到卷积神经网络的结构。
import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.summary()
输出结果:
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 26, 26, 64) 640
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 64) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 11, 11, 64) 36928
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 1600) 0
_________________________________________________________________
dense_2 (Dense) (None, 128) 204928
_________________________________________________________________
dense_3 (Dense) (None, 10) 1290
=================================================================
Total params: 243,786
Trainable params: 243,786
Non-trainable params: 0
可以看到,共有7层。原本输入为28*28。
Conv2D一层处理后,每个方向减少3-1=2个像素,共有64个过滤器。所以parameter = (3×3+1)×64 = 640,+1是加上一个blas。
maxpooling后横竖方向像素减半,parameter无调整。
第二次Conv2D一样。parameter = (3×3×64+1)×64 =36928.
maxpooling同上。
import tensorflow as tf
#print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
#下载数据集
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
#reshape,scaling
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
#convolutional
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
#打印卷积网络结构
model.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)
#编译模型,调用model.fit方法做训练,接着用测试集评估损失和准确率。
下载训练数据,存入硬盘。解压后得到两个文件夹horse、human。
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip \
-O /tmp/horse-or-human.zip
让我们设置训练数据生成器(ImageDataGenerator),它将读取源文件夹中的图片,将它们转换为
float32
多维数组,并将图像数据(连同它们的标签)反馈给神经元网络。总共需要两个生成器,有用于产生训练图像,一个用于产生验证图像。生成器将产生一批大小为300x300的图像及其标签(0或1)。
即:用ImageDataGenerator将图片数据处理成网络可以进行训练的、大小合适(内存放得下)的数据。(也可以手动实现,但是用数据生成器更简单)
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 创建两个数据生成器,指定scaling范围是0-1
train_datagen = ImageDataGenerator(rescale = 1/255)
validation_datagen = ImageDataGenerator(rescale = 1/255)
# 指向训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'/tmp/horse-or-human/', # 训练数据所在文件夹
target_size = (300,300), # 指定输出尺寸
batch_size = 32,
class_mode = 'binary') # 指定二分类
# 指向测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'/tmp/validation-horse-or-human/',
target_size = (300,300),
batch_size = 32,
class_mode = 'binary')
# 1 导入tensorflow import tensorflow as tf # 2 卷积层和全连接层 model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2, 2), tf.keras.layers.Conv2D(32, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), #添加卷积层,以上共5层 tf.keras.layers.Flatten(), # 将最终结果扁平化,以输送到全连接的层去 tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dense(1, activation='sigmoid') # 添加全连接层,注意这里的激励函数变成sigmoid。二分类用sigmoid,多分类用softmax。解释见下文引用1 ]) # 3 配置模型训练的参数 from tensorflow.keras.optimizers import RMSprop model.compile(loss='binary_crossentropy', optimizer=RMSprop(lr=0.001), metrics=['acc']) # loss:用 "binary_crossentropy(二元交叉熵)"衡量损失 # 二元分类问题,激活函数是一个sigmoid # 使用rmsprop作为优化器,学习率为0.001,见下文引用2 # 4 训练 history = model.fit( train_generator, steps_per_epoch=8, epochs=15, verbose=1)
引用1:需要注意的是,由于我们面对的是一个两类分类问题,即二类分类问题,所以我们会用sigmoid激活函数作为模型的最后一层,这样我们网络的输出将是一个介于0和1之间的有理数,即当前图像是1类(而不是0类)的概率。
引用2:我们将使用学习率为
0.001
的rmsprop
优化器。在这种情况下,使用RMSprop优化算法比随机梯度下降更可取,因为RMSprop可以为我们自动调整学习率。(其他优化器,如Adam和Adagrad,也会在训练过程中自动调整学习率,在这里也同样有效。)
构造神经元网络模型时,一定会考虑需要几个卷积层?过滤器应该几个?全连接层需要几个神经元?
最先想到的肯定是手动修改那些参数,然后观察训练的效果(损失和准确度),从而判断参数的设置是否合理。但是那样很繁琐,因为参数组合会有很多,训练时间很长。再进一步,可以手动编写一些循环,通过遍历来搜索合适的参数。但是最好利用专门的框架来搜索参数,不太容易出错,效果也比前两种方法更好。
Kerastuner就是一个可以自动搜索模型训练参数的库。它的基本思路是在需要调整参数的地方插入一个特殊的对象(可指定参数范围),然后调用类似训练那样的search方法即可。
即:使用Kerastuner找到最适合的模型参数,将这些设置好的参数用类传入训练函数,建立最优模型开始训练。
# 1 首先准备训练数据和需要加载的库。
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import RMSprop
train_datagen = ImageDataGenerator(rescale=1/255)
validation_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory('/tmp/horse-or-human/',
target_size=(150, 150),batch_size=32,class_mode='binary')
validation_generator = validation_datagen.flow_from_directory('/tmp/validation-horse-or-human/',
target_size=(150, 150), batch_size=32,class_mode='binary')
from kerastuner.tuners import Hyperband
from kerastuner.engine.hyperparameters import HyperParameters
import tensorflow as tf
# 2 创建HyperParameters对象,然后在模型中插入Choice、Int等调参用的对象。
hp=HyperParameters()
def build_model(hp):
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(hp.Choice('num_filters_top_layer',values=[16,64],default=16), (3,3), activation='relu', input_shape=(150, 150, 3)))
model.add(tf.keras.layers.MaxPooling2D(2, 2))
for i in range(hp.Int("num_conv_layers",1,3)):
model.add(tf.keras.layers.Conv2D(hp.Choice(f'num_filters_layer{i}',values=[16,64],default=16), (3,3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))
# 一个循环,几个卷积层
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(hp.Int("hidden_units",128,512,step=32), activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer=RMSprop(lr=0.001),metrics=['acc'])
return model
# 3 调用search方法
tuner=Hyperband(
build_model,
objective='val_acc',
max_epochs=10,
directory='horse_human_params',
hyperparameters=hp,
project_name='my_horse_human_project'
)
tuner.search(train_generator,epochs=10,validation_data=validation_generator)
# 搜索到最优参数
# 4 用tuner对象提取最优参数,构建神经元网络模型。并调用summary方法观察优化后的网络结构。
best_hps=tuner.get_best_hyperparameters(1)[0]
print(best_hps.values)
model=tuner.hypermodel.build(best_hps)
model.summary()
感觉今天没太学明白…但是wl老师说了!先跳过去没关系QuQ
噩耗:接下来的教程没有中文翻译了,小乌龟的英语水平即将面临前所未有的挑战!!!(此处应该有BGM,噔噔噔噔噔噔噔噔噔噔)但是还是要加油!