第三章 TensorFlow 神经网络的搭建

3.1 神经网络搭建八股

我觉得吧,搭建神经网络就像盖房子一样,该有的总要有!

因此为了思路流畅可以总结出需要的步骤,同时结合Tensor Flow为我们造好的API接口,省略掉很多第二章的代码,增加了易读性!

下面利用强大的Keras搭建!

3.1.1 步骤介绍

虽然叫八股但是其实有六步啊哈哈哈~

使用六步法

  1. import
  2. train,test
    (指定x_train,y_train和x_test,y_test)
  3. model = tf.keras.models.Sequential
    (逐层描述神经网络,相当于走了前向传播)
  4. model.compile
    (确定优化器,损失函数,评测指标)
  5. model.fit
    (告知训练集和测试集的输入特征和标签,每个betch是多少,需要多少次迭代)
  6. model.summary

(打印网络的结构和参数统计)

3.1.2 函数参数介绍

第一步和第二步很容易写出,没有什么封装的函数!

从第三步的model = tf.keras.models.Sequential开始需要选择填入的参数~

3.1.2.1 Sequential

看成神经网络的容器,我们需要描述每一层的输入输出结构!方便的是不用自己写了,有API接口可以直接以字符串的形式传入。

网络结构举例:

拉直层:

(不含计算只是形状转换,拉直成数组)

tf.keras.layers.Flatten()

全连接层:

tf.keras.layers.Dense(神经元个数,activation = '激活函数',kernel_regularizer = 正则化)
标签可选择的参数
activation (字符串形式)relu
softmax
sigmoid
tanh
kernel_regularizertf.keras.regularizers.l1()
tf.keras.regularizers.l2()

卷积层:

tf.keras.layers.Conv2D(filters = 卷积核个数,kernel_size = 卷积核尺寸,strides = 卷积核步长, padding = "valid" or "same")

LSTM层:

tf.keras.layers.LSTM()

3.1.2.2 Compile

model.compile(optimizer = 优化器,loss = 损失函数,metrics = ["准确率"])

这些选项在选择时,可以直接用字符串形式,也可以用函数形式!这里的函数形式可以改动超参数!

选项字符串形式函数形式 / 描述
Optimizer
(优化器)
'sgd'
'adagrad'
'adadelta'
'adam'
.SGD(lr=学习率,momentum=动量参数)
.Adagrad(lr=学习率)
.Adadelta(lr=学习率)
.Adam(lr=学习率,beta_1=0.9,beta_2=0.999)
Loss
(损失函数)
'mse'
'sparse_categorical_crossentropy'
.MeanSquaredError()
.SparseCategoricalCrossentropy(from_logits = False)
经过概率分布就要写False!!
Metrics
(评测指标)
'accuracy'
'categorical_accuracy'
'sparse_categorical_accuracy'
y_ 和 y都是用数值型表示的
y_ 和 y都是独热码或概率分布给出的
y_ 是数值,y是独热码

3.1.2.3 fit

这个后面带了好多参数!

model.fit(训练集的输入特征,训练集的标签,batch_size=,epochs=,validation_data=(测试集的输入特征,测试集的标签),validation_split=从训练集划分多少比例给测试集,validation_freq=多少次epoch测试一次)

3.1.2.4 summary

可以打印网络结构和参数统计!

3.2 案例代码

通过上述的接口简化之后,利用字符串或函数为选项,就可以轻松地调用第二章学习的激活函数,损失函数等~代码也简洁很多!

同样是鸢尾花的例子!

# 第一步import
import tensorflow as tf
from sklearn import datasets
import numpy as np

# 第二步train,test
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target

# 乱序
np.random.seed(6)
np.random.shuffle(x_train)
np.random.seed(6)
np.random.shuffle(y_train)

# 第三步 models.Sequential
model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(3,activation = 'softmax',kernel_regularizer = tf.keras.regularizers.l2())
])

# 第四步 model.compile
# 这里的softmax使得输出是概率分布而不是原始输出--》选择False
# 概率和数值输出所以用sparse_categorical_accuracy
model.compile(optimizer = tf.keras.optimizers.SGD(lr = 0.1),
              loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = False),
              metrics = ['sparse_categorical_accuracy'])

# 第五步 model.fir
# 选择20%的数据为测试集
model.fit(x_train,y_train,batch_size = 32,epochs = 500,validation_split = 0.2,validation_freq = 20)

# 第六步 model.summary()
model.summary()

结果很直观!同时summary还打印出了神经网络的形状(红色框框里~)

Keras搭建结果

!!!但是我还有一个疑问没有解决,很奇怪,是在乱序哪里!

我一直认为np.random.seed(6)这句是设置随机种子使得大家在不同电脑上的随机数据相同,其他没什么影响。然而,我删除这句随机种子代码后,

只写:

# 乱序
np.random.shuffle(x_train)
np.random.shuffle(y_train)

准确率只有0.4左右!?为什么呢,奇怪,明天想想问问大佬们....

解释:
大佬的分析从0.4的准确率说起,一共三种花,瞎蒙也是0.4...同时因为只留一句seed(6)准确率仍然和瞎蒙一样。
因此得出:如上面两句话都不写或者只写一句造成了x和y不匹配,也就是说喂的训练集就是个没规律的。

他给了我可以不用seed的解决方法:把x和y合成一个表,用tensorflow的shuffle,再将他们分开后就一定是配对的了~

3.3 数据集举例介绍

3.3.1 MNIST数据集

3.3.1.1 介绍

这个数据集共7万张图片,都是28 * 28像素的手写数字图片 !

其中6万张用来训练,我们用x_train,y_train接收

其余1万用来测试,我们用x_test,y_test接收!

我们先查看一下数据集的内容:

# 导入MNIST数据集
mnist = tf.keras.datasets.mnist
(x_train,y_train),(x_test,y_test) = mnist.load_data()

# 一共28 * 28个像素点的灰度值作为输入特征传入神经网络
tf.keras.layers.Flatten()

# 绘制灰度值,将第一个训练样本可视化出来
plt.imshow(x_train[0],cmap = 'gray')
plt.show()

这样可以看到第一张图用灰度值显示的效果:

手写字灰度图

这样可以看看第一个样本没灰度值的输入数据和格式

print("x_train[0] :\n ",x_train[0] )

结果是28行28列的数值,每个数值在1-256之间~

下面再看看整个输入数据集的样子!

print("x_test.shape:",x_test.shape)

输出:x_test.shape: (10000, 28, 28)

也就是:测试集的形状,一共10000个,每个28行28列

3.3.1.2 手写识别系统

这里用class封装实现训练手写识别系统~

注意:由于输入数据都是1-256之间的数据,可以除以255变为0-1的数,使得神经网络更好吸收~

也就是这句:

x_train,x_test = x_train/255.0,x_test/255.0

而且,这里用了两层神经网络,

分别用了 relu 和 softmax 激活函数,这也使得后面的输入为概率分布,需要False~

这里的优化器用了adam~

# 用Class封装实现数字识别训练
import matplotlib.pyplot as plt
import tensorflow as tf
from sklearn import datasets
import numpy as np
from tensorflow.keras.layers import Dense,Flatten
from tensorflow.keras import Model


# 导入MNIST数据集
mnist = tf.keras.datasets.mnist
(x_train,y_train),(x_test,y_test) = mnist.load_data()
x_train,x_test = x_train/255.0,x_test/255.0
# 归一化
# 将输入变为0,1之间的数,变小适合神经网络的吸收

class MnistModel(Model):
  def __init__(self):
    super(MnistModel,self).__init__()
    self.flatten = Flatten()
    self.d1 = Dense(128,activation='relu')
    self.d2 = Dense(10,activation='softmax')
  def call(self,x):
    x = self.flatten(x)
    x = self.d1(x)
    y = self.d2(x)
    return y

model = MnistModel()

model.compile(optimizer='adam',
       loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
       metrics = ['sparse_categorical_accuracy'])

model.fit(x_train,y_train,batch_size=32,epochs = 5,validation_data=(x_test,y_test),validation_freq=1)
model.summary()

最终的准确率还蛮高的~

3.3.2 Fashion 数据集

3.3.2.1 介绍

与MNIST很像,Fashion数据集也由7万张图片组成,且每张都为28 * 28像素的图片~

并且用6:1分出训练集和测试集。

特别在10个输出特征对应的不同的标签内容~

同样先看一下可视化的效果来了解数据:

# 导入Fashion数据集
fashion = tf.keras.datasets.fashion_mnist
(x_train,y_train),(x_test,y_test) = fashion.load_data()

# 一共28 * 28个像素点的灰度值作为输入特征传入神经网络
tf.keras.layers.Flatten()

# 绘制灰度值,将第一个训练样本可视化出来
plt.imshow(x_train[1],cmap = 'gray')
plt.show()

Fashion灰度图

3.3.2.2 实现衣服类别识别

这里同样用class封装神经网络模块

运用相同的神经网络,只需要将输入的数据集改一下即可~

# 用Sequential实现数字识别训练
import tensorflow as tf

# 导入MNIST数据集
fashion = tf.keras.datasets.mnist
(x_train,y_train),(x_test,y_test) = fashion.load_data()
x_train,x_test = x_train/255.0,x_test/255.0
# 归一化
# 将输入变为0,1之间的数,变小适合神经网络的吸收

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  # 定义两层神经网络的神经元和激活函数
  tf.keras.layers.Dense(128,activation='relu'),
  tf.keras.layers.Dense(10,activation='softmax'),        
])

# 输入概率分布-》false,输出概率-》s_c_a
model.compile(optimizer='adam',
       loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
       metrics = ['sparse_categorical_accuracy'])

model.fit(x_train,y_train,batch_size=32,epochs = 5,validation_data=(x_test,y_test),validation_freq=1)
model.summary()
Last modification:July 29th, 2020 at 12:03 pm
请赏我杯奶茶,让我快乐长肉