文章目录
手把手教你使用Tensorflow2.0搭建入门级神经网络
实验代码:提取码-6666
前置知识
神经网络模型
初始化神经网络模型:model = tf.models.Sequential([网络结构])
-
拉直层:
tf.keras.layers.Flatten()
-
全连接层:
tf.keras.layers.Dense(神经元个数,activation='激活函数',kernel_regularizer=正则化方式)
acitivation(以字符串给出):‘relu’,‘softmax’,‘sigmoid’
kernel_regularize:tf.keras.regulizers.l1()
,tf.keras.regulizers.l2()
-
卷积层:
tf.keras.layers.Conv2D(filters=卷积核个数,kernel_size=卷积核尺寸,strides=卷积核步长,padding="valid"/"same")
-
LSTM:
tf.keras.layers.LSTM()
优化模型的基本配置
在初始化神经网络模型之后需要添加优化模型参数的基本配置如分类器,损失函数等:model.compile(optimizer=${优化器},losses=${损失函数},metrics=[‘准确率’])
- optimizer选择优化器:
SGD优化器:‘sgd’ 或者
tf.keras.optimizers.SGD(lr=${学习率},momentum=${动量参数})
Adagrad优化器:‘adagrad’ 或者tf.keras.optimizers.Adagrad(lr=${学习率})
Adadelta优化器:‘adadelta’ 或者tf.keras.optimizers.Adadelta(lr=${学习率})
SGD优化器:‘adam’ 或者tf.keras.optimizers.Adam(beta_1=0.9,beta_2=0.999)
- loss选择损失函数:
均方差损失函数(MSE):‘mse’ 或者
tf.keras.MeanSquareError()
交叉熵损失函数(CrossEntropy):‘sparse_categorical_crossentropy’ 或者tf.keras.SparseCategoricalCrossentropy(from_logits=False)
- metrics度量选择方式:
‘accuracy’: y _ y\_ y_与 y y y都是数值,如: y _ = [ 1 ] , y = [ 1 ] y\_=[1],y=[1] y_=[1],y=[1]
‘categorical_accuracy’: y _ y\_ y_与 y y y都是独热编码,如: y _ = [ 0 , 1 , 0 ] , y = [ 0.256 , 0.695 , 0.048 ] y\_=[0,1,0],y=[0.256,0.695,0.048] y_=[0,1,0],y=[0.256,0.695,0.048]
‘sparse_categorical_accuracy’: y _ y\_ y_是数值, y y y都是独热码,如: y _ = [ 1 ] , y = [ 0.256 , 0.695 , 0.048 ] y\_=[1],y=[0.256,0.695,0.048] y_=[1],y=[0.256,0.695,0.048]
打印模型信息与模型训练
- 打印模型信息:
model.summary()
- 训练模型:
model.fit(${训练集输入特征},${训练集标签},batch_size,epochs,validation_data=(${测试集输入特征},${测试集的标签}),validation_split=${从训练集划分多少比例给测试集},validation_freq=${多少次epoch测试一次})
将神经网络封装成一个类(建议背八股)
入门级神经网络搭建
由于Sequential型只适用于上层输出就是上层的顺序,无法写出一些带跳连的非顺序网络结构,因此用一个类进行封装一方面可以使模型更加简介明了,也增加了模型可执行性
采用类封装神经网络如下模板:
class MyModel(Model):
## 定义所需网络结构模块
def __init__(self):
super(MyModel,self).__init__()
# 定义网络模块
def call(self,x):
# 调用网络结构快,实现前向传播
out=""
return out;
【例1】:我们以 MNIST 手写数据集为例子来尝试搭建入门级神经网络
-
导入基本的第三方库
import tensorflow as tf from tensorflow.keras import Model import matplotlib.pyplot as plt import numpy as np
-
将神经网络封装成一个类,并将模型初始化
## 将神经网络模型封装成为一个类 class MnistModel(Model): def __init__(self): super(MnistModel,self).__init__() self.dl = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128,activation='relu'), tf.keras.layers.Dense(10,activation='softmax') ]) def call(self,x): out = self.dl(x) return out # 初始化模型 model = MnistModel()
-
加载MNIST数据集,并将训练集和测试集的特征进行归一化
# 加载MNIST手写数据集 mnist = tf.keras.datasets.mnist (x_train,y_train),(x_test,y_test) = mnist.load_data() # 将训练集数据进行随机打乱 np.random.seed(116) np.random.shuffle(x_train) np.random.seed(116) np.random.shuffle(y_train) tf.random.set_seed(116) # 训练集和测试集特征归一化 x_train,x_test = x_train/255.,x_test/255.
-
加载模型训练时的基本配置(如:优化器,损失函数等)
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()
扩展一:自制数据集,解决本领域应用
观察数据集数据结构,给x_train
,y_train
,x_test
,y_test
赋值,随后定义函数def generateDatasets(${图片路径},${标签文件})
def generateDatasets(path,txt):
f = open(txt,'r')
contents = f.readlines()
f.close()
## 存放数据集特X与标签Y
x,y_=[],[]
for content in contents:
# 以空格为分割依据分割为value[0]:数据集文件名 + value[1]:标签
value = content.split()
# 获取图片保存所在路径,并将图片读取出来
img_path = path + value[0]
img = Image.open(img_path)
# 将图片转换成灰度图像,并将数据归一化
img = np.array(img.convert('L'))
img = img/255.
x.append(img)
y_.append(value[1])
print('loading:'+content)
# 数据集制作成功
x = np.array(x)
y_ = np.array(y_)
y = y.astype(np.int64)
return x,y_
【例2】:将图片数据转换成需要的满足tensorflow训练的数据集
-
导入第三方库(不需要多说)
import tensorflow as tf from PIL import Image import numpy as np import os
-
设置数据集存放的位置
## 数据的路径名 # 训练集(原始数据)存放的文件夹 train_path = './mnist_image_label/mnist_train_jpg_60000/' # 训练集(原始数据文件名 + 标签)构成的txt文档 train_txt = './mnist_image_label/mnist_train_jpg_60000.txt' # 训练集特征X和标签y分别转成.npy数据格式,所存放的位置 x_train_savepath = './mnist_image_label/mnist_x_train.npy' y_train_savepath = './mnist_image_label/mnist_y_train.npy' # 训练集(原始数据)存放的文件夹 test_path = './mnist_image_label/mnist_train_jpg_60000/' # 训练集(原始数据文件名 + 标签)构成的txt文档 test_txt = './mnist_image_label/mnist_test_jpg_10000.txt' # 训练集特征X和标签y分别转成.npy数据格式,所存放的位置 x_test_savepath = './mnist_image_label/mnist_x_test.npy' y_test_savepath = './mnist_image_label/mnist_y_test.npy'
-
加载数据
if os.path.exists(x_train_savepath) and os.path.exists(y_train_savepath) and os.path.exists( x_test_savepath) and os.path.exists(y_test_savepath): ## 判断.npy文件是否存在,如果存在直接加载 print('--------------------- Load Datasets ---------------------') # 加载.npy文件 x_train_save = np.load(x_train_savepath) y_train = np.load(y_train_savepath) x_test_save = np.load(x_test_savepath) y_test = np.load(y_test_savepath) x_train = np.reshape(x_train_save,(len(x_train_save),28,28)) x_test = np.reshape(x_test_save,(len(x_test_save),28,28)) else: ## 反之调用generateDatasets函数,先把图片数据转成指定的格式,并将数据转换成.npy文件,以便下次使用 print('--------------------- Generate Datasets ---------------------') x_train,y_train = generateDatasets(train_path,train_txt) x_test,y_test = generateDatasets(test_path,test_txt) # 转成.npy文件 print('--------------------- Load Datasets ---------------------') x_train_save = np.reshape(x_train, (len(x_train), -1)) x_test_save = np.reshape(x_test, (len(x_test), -1)) np.save(x_train_savepath, x_train_save) np.save(y_train_savepath, y_train) np.save(x_test_savepath, x_test_save) np.save(y_test_savepath, y_test)
-
模型搭建 + 常规训练
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128,activation='relu'), tf.keras.layers.Dense(10,activation='softmax') ]) 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()
扩展二:数据增强
数据增强的目的是帮助扩展数据集,即对图像的简单形变,用来应对因拍照角度不同引起的图片变形,如下代码就是一个模板:
image_gen_train = tf.keras.preprocessing.image.ImageDataGenerator(
rescale='${所有数据将乘以该数值}',
rotation_range='${随机宽度偏移量}',
width_shift_range='${随机高度偏移量}',
horizontal_filp='${是否水平旋转}'
zoom_range=随机缩放的范围'${[1-n,1+n]}')
image_gen_train.fit(x_train)
【例3】:将图片增强后训练模型
- 导入第三方库
import tensorflow as tf # 数据预处理的包 from tensorflow.keras.preprocessing.image import ImageDataGenerator
- 加载数据集(以FASHION数据集为例子),并将数据进行增强
## 加载数据 fashion = tf.keras.datasets.fashion_mnist (x_train,y_train),(x_test,y_test) = fashion.load_data() x_train,x_test = x_train/255.,x_test/255. x_train=x_train.reshape(x_train.shape[0],28,28,1) ## 数据增强 image_gen_train = ImageDataGenerator( rescale=1./1., #如为图像,分母为255时,可归一化 rotation_range=45, #旋转角度为45度 width_shift_range=15,#位置偏移宽度 height_shift_range=15,#位置偏移高度 horizontal_flip=True,#水平旋转 zoom_range=0.5#将图像随机缩放阈量50% ) image_gen_train.fit(x_train)
- 常规模型搭建 + 训练(注意fit函数部分加载数据区别于其它训练方法)
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128,activation='relu'), tf.keras.layers.Dense(10,activation='softmax') ]) model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), metrics=['sparse_categorical_accuracy']) model.fit(image_gen_train.flow(x_train,y_train,batch_size=32),epochs=5,validation_data=(x_test,y_test),validation_freq=1) model.summary()
扩展三:断点续训,存取模型
读取模型:load_weights('${文件路径名}')
,代码样例
checkpoint_save_path = "./checkpoint/MnistModel.ckpt"
if os.path.exists(checkpoint_save_path + 'index'):
print("-------- load the model -----------")
model.load_weights(checkpoint_save_path)
保存模型:
tf.keras.callbacks.ModelCheckpoint(filepath='${路径文件名}',save_weights_only=True/False,save_best_only=True/False)
history=model.fit(...,...,callbacks=[cp_callback])
【例4】:跟踪训练模型参数,并保存模型参数
- 导入第三方库
→
\rightarrow
→ 初始化模型参数
→
\rightarrow
→ 模型训练相关配置加载
import tensorflow as tf import os mnist = tf.keras.datasets.mnist (x_train,y_train),(x_test,y_test) = mnist.load_data() x_train,x_test = x_train/255.,x_test/255. model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128,activation='relu'), tf.keras.layers.Dense(10,activation='softmax') ]) model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), metrics=['sparse_categorical_accuracy'])
- 加载模型,如果项目中有现成的模型就加载模型,反之无法加载模型
## 加载保存后的模型 checkpoint_save_path = "./checkpoint/mnist.ckpt" ## 如果存在现成的模型,则将模型加载出来 if os.path.exists(checkpoint_save_path + '.index'): print("---------------- load the model -----------------") model.load_weights(checkpoint_save_path) ## 选择保存的模型方式(如:仅保存模型参数/仅仅保存最好的模型) cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path, save_weights_only=True, save_best_only=True)
- 常规训练
history = model.fit(x_train,y_train,batch_size=32,epochs=5, validation_data=(x_test,y_test),validation_freq=1, callbacks=[cp_callback]) model.summary()
扩展四:参数提取,把参数存入文本
提取可训练参数:model.trainable_variables
(返回模型中可训练的参数)
设置print输出格式:np.set_printoptions(threshold='${超过多少省略提示}')
【例5】:基于【例4】保存的模型我们将模型参数打印下来
- 补充导入的包
import numpy as np np.set_printoptions(threshold=np.inf) # 打印全部内容
- 打印模型信息,并将模型信息写入txt文件当中
print(model.trainable_variables) file = open('./weight.txt','w') for v in model.trainable_variables: file.write(str(v.name)+'\n') file.write(str(v.shape)+'\n') file.write(str(v.numpy())+'\n') file.close()
扩展五:acc/loss可视化,查看训练效果
【例6】:将模型训练的过程(模型在训练集/测试集中的精度/损失函数)
- 基于【例1】,我们记录模型训练的过程,补充导入的第三方库
import matplotlib.pyplot as plt
- 基于【例1】训练模型model.fit,并用history借住
# 训练集的准确率 acc = history.history['sparse_categorical_accuracy'] # 测试集的准确率 val_acc = history.history['val_sparse_categorical_accuracy'] # 训练集的损失函数 loss = history.history['loss'] # 测试集的损失函数 val_loss = history.history['val_loss'] ## 画图程序 plt.subplot(1,2,1) plt.plot(acc,label='Training Accuracy') plt.plot(val_acc,label='Validation Accuracy') plt.legend() plt.subplot(1,2,2) plt.plot(loss,label='Training Loss') plt.plot(val_loss,label='Validation Loss') plt.legend() plt.show()
综合案例:给图识物
案例说明:给出了一组手写数据集,我们用基于MNIST手写数据集训练好的模型来预测这一组数据;
-
测试的图片(通常情况下与MNIST数据是不同分布的,这也是人工智能通常情况的场景):
-
基于以下程序,实现了预测手写数字的案例:
from PIL import Image import numpy as np import tensorflow as tf model_save_path = './checkpoint/mnist.ckpt' # 初始化模型 model = tf.keras.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128,activation='relu'), tf.keras.layers.Dense(10,activation='softmax') ]) # 初始化模型,并加载已经训练好的模型参数 model.load_weights(model_save_path) preNum = int(input("Input the number of test pictures:")) for i in range(preNum): image_path = input("the path of picture:") img = Image.open(image_path) img = img.resize((28,28),Image.ANTIALIAS) img_arr = np.array(img.convert('L')) # 将输入的图片进行灰度处理,下面的操作目的是减少图片噪声污染,提高模型预测的准确度 for i in range(28): for j in range(28): if img_arr[i][j]<200: img_arr[i][j] = 255 else: img_arr[i][j] = 0 img_arr = img_arr / 255.0 # 加载图片,并调用模型预测 x_predict = img_arr[tf.newaxis, ...] result = model.predict(x_predict) pred = tf.argmax(result,axis=1) tf.print(pred)