TensorFlow入门实操笔记 3-4

前言碎碎念

fine…世界鸽王立flag第一天就咕咕咕了,今天马上立刻学习以抚慰自己的良心(bushi
起床自我暗示:我真的很喜欢机器学习!就会中计真的一开电脑就学习


大纲

    • 前言碎碎念
    • 第三章:卷积介绍
      • 3.1 卷积神经网络
      • 3.2 卷积神经程序
      • 3.3 卷积网络结构
      • 3.4 卷积神经网络 训练代码
    • 第四章 图像应用
      • 4.1 准备训练数据
      • 4.2 数据预处理
      • 4.3 创建并训练模型
      • 4.4 优化模型参数
    • 总结

第三章:卷积介绍

3.1 卷积神经网络

概念:CNN(Convolutional Neural Network,卷积神经网络)

用途:对待训练图片中所含冗余信息进行过滤(如:图片不在中央;图片角度倾斜;图片颜色等多余信息)

思想:用卷积提取图片特征,保留轮廓线

  1. 卷积

    像素和过滤器中对应位置的数值相乘,得到的结果累积。(这一步可以突出中心像素,并且对于n*n的过滤器,对图片进行卷积处理后,最后竖直水平方向上都会少掉(n-1)个像素。

    卷积保留水平和竖直方向的数据。
    TensorFlow入门实操笔记 3-4_第1张图片

  2. Max Pooling

    目的:增强特征,减少数据

    对于2*2图像,选取四个格子中最大值保留,相当于选择图像中最明显的一点保留下来。可以突出图像特征,同时把数据减少为原来的1/4。
    TensorFlow入门实操笔记 3-4_第2张图片

3.2 卷积神经程序

第一步是收集数据。你会注意到,这里和之前有一点变化,训练数据需要改变维度(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

接下来是定义模型。首先要添加一个卷积层。参数是

  1. 你想要生成的卷积数(过滤器数量)。这个数值是任意的,但最好是从32开始的倍数。
  2. 卷积的大小(过滤器的大小),在本例中为3x3网格。这是最常用的尺寸。
  3. 要使用的激活函数 – 在本例中,我们将使用relu,你可能还记得它相当于当x>0时返回x,否则返回0。
  4. 在第一层,设定输入数据的形状。

在卷积层之后加上一个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小。

3.3 卷积网络结构

通过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同上。

3.4 卷积神经网络 训练代码

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方法做训练,接着用测试集评估损失和准确率。

第四章 图像应用

4.1 准备训练数据

  1. 下载训练数据,存入硬盘。解压后得到两个文件夹horse、human。

    !wget --no-check-certificate \
        https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip \
        -O /tmp/horse-or-human.zip
    

TensorFlow入门实操笔记 3-4_第3张图片

  1. 测试集和训练集的数据目录结构。把不同标签的图片放入不同的文件夹,这样就可以直接用文件夹名标标签。
    TensorFlow入门实操笔记 3-4_第4张图片

4.2 数据预处理

让我们设置训练数据生成器(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')

4.3 创建并训练模型

# 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.001rmsprop优化器。在这种情况下,使用RMSprop优化算法随机梯度下降更可取,因为RMSprop可以为我们自动调整学习率。(其他优化器,如AdamAdagrad,也会在训练过程中自动调整学习率,在这里也同样有效。)

4.4 优化模型参数

构造神经元网络模型时,一定会考虑需要几个卷积层?过滤器应该几个?全连接层需要几个神经元?

最先想到的肯定是手动修改那些参数,然后观察训练的效果(损失和准确度),从而判断参数的设置是否合理。但是那样很繁琐,因为参数组合会有很多,训练时间很长。再进一步,可以手动编写一些循环,通过遍历来搜索合适的参数。但是最好利用专门的框架来搜索参数,不太容易出错,效果也比前两种方法更好。

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,噔噔噔噔噔噔噔噔噔噔)但是还是要加油!

你可能感兴趣的:(TensorFlow入门笔记,tensorflow,机器学习,python)