tensorflow2.x第三篇

容器或自定义层实现全连接网络,自定义数据集,断点续训,模型的保存,图片数据增强,应用

  • 神经网络的搭建八股,用“六步法”。
#第一步:import 相关模块
import tensorflow as tf
from sklearn import datasets
import numpy as np
#第二步:指定输入网络的训练集和测试集
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target

np.random.seed(16)
np.random.shuffle(x_train)
np.random.seed(16)
np.random.shuffle(y_train)
tf.random.set_seed(16)

#第三步:逐层搭建网络结构,model = tf.keras.models.Sequential()
'''
tf.keras.models.Sequential() 
    Sequential 函数是一个容器,描述了神经网络的网络结构,在 Sequential
函数的输入参数中描述从输入层到输出层的网络结构。
如:
    拉直层:tf.keras.layers.Flatten()
        拉直层可以变换张量的尺寸,把输入特征拉直为一维数组,是不含计算参数的层。
        
    全连接层:tf.keras.layers.Dense( 
                神经元个数,
                activation=”激活函数”,
                kernel_regularizer=”正则化方式”)
    其中:
        activation(字符串给出)可选 relu、softmax、sigmoid、tanh 等
        kernel_regularizer 可选 tf.keras.regularizers.l1()、tf.keras.regularizers.l2()
        
    卷积层:tf.keras.layers.Conv2D( 
            filter = 卷积核个数,
            kernel_size = 卷积核尺寸,
            strides = 卷积步长,
            padding = “valid” or “same”)
            
    LSTM 层:tf.keras.layers.LSTM()。
'''
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(3,activation='softmax',kernel_regularizer=tf.keras.regularizers.l2())
])

#第四步:在 model.compile()中配置训练方法,选择训练时使用的优化器、损失函数和最终评价指标
'''
Compile 用于配置神经网络的训练方法,告知训练时使用的优化器、损失函数和准确率评测标准。
Model.compile( 
            optimizer = 优化器, 
            loss = 损失函数, 
            metrics = [“准确率”]) 
其中: 
optimizer 可以是字符串形式给出的优化器名字,也可以是函数形式,使用函数形式可以设置学习率、动量和超参数。 
可选项包括:
        ‘sgd’or tf.optimizers.SGD( lr=学习率,decay=学习率衰减率,momentum=动量参数) 
        ‘adagrad’or tf.keras.optimizers.Adagrad(lr=学习率,decay=学习率衰减率) 
        ‘adadelta’or tf.keras.optimizers.Adadelta(lr=学习率,decay=学习率衰减率) 
        ‘adam’or tf.keras.optimizers.Adam (lr=学习率,decay=学习率衰减率)
        
Loss 可以是字符串形式给出的损失函数的名字,也可以是函数形式。 
可选项包括:
        ‘mse’or tf.keras.losses.MeanSquaredError()
        ‘sparse_categorical_crossentropy or tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
损失函数常需要经过 softmax 等函数将输出转化为概率分布的形式。
from_logits 则用来标注该损失函数是否需要转换为概率的形式,取 False 时表示转化为概率分布,取 True 时表示没有转化为概率分布,直接输出。

Metrics 标注网络评测指标。 
可选项包括:
        ‘accuracy’:y_和 y 都是数值,如 y_=[1] y=[1]。
        ‘categorical_accuracy’:y_和 y 都是以独热码和概率分布表示。如 y_=[0, 1, 0], y=[0.256, 0.695, 0.048]。
        ‘sparse_ categorical_accuracy’:y_是以数值形式给出,y 是以独热码形式给出。 如 y_=[1],y=[0.256, 0.695, 0.048]。
'''
model.compile(optimize=tf.keras.optimizers.SGD(lr=0.1),
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

#第五步:在 model.fit()中执行训练过程,告知训练集和测试集的输入值和标签、每个 batch 的大小(batchsize)和数据集的迭代次数(epoch)
'''
model.fit(
        训练集的输入特征, 
        训练集的标签, 
        batch_size, 
        epochs, 
        validation_data = (测试集的输入特征,测试集的标签), 
        validataion_split = 从测试集划分多少比例给训练集, 
        validation_freq = 测试的 epoch 间隔次数) 

fit 函数用于执行训练过程
'''
model.fit(x_train,y_train,batch_size=32,epochs=500,validation_split=0.2,validation_freq=20)

#第六步:使用 model.summary()打印网络结构,统计参数数目。summary 函数用于打印网络结构和参数统计
model.summary()
  • 将TensorFlow的容器替换成自定义的。
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np

x_train = datasets.load_iris().data
y_train = datasets.load_iris().target

np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)

class IrisModel(Model):
    def __init__(self):
        super(IrisModel, self).__init__()
        self.d1 = Dense(3,activation='softmax')
    def call(self, inputs, training=None, mask=None):
        y = self.d1(inputs)
        return y
model = IrisModel()

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

model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
model.summary()
  • 自制数据集
import tensorflow as tf
from PIL import Image
import numpy as np
import os

train_path = './mnist_image_label/mnist_train_jpg_60000/'
train_txt = './mnist_image_label/mnist_train_jpg_60000.txt'
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_test_jpg_10000/'
test_txt = './mnist_image_label/mnist_test_jpg_10000.txt'
x_test_savepath = './mnist_image_label/mnist_x_test.npy'
y_test_savepath = './mnist_image_label/mnist_y_test.npy'


def generateds(path, txt):
    f = open(txt, 'r')  # 以只读形式打开txt文件
    contents = f.readlines()  # 读取文件中所有行
    f.close()  # 关闭txt文件
    x, y_ = [], []  # 建立空列表
    for content in contents:  # 逐行取出
        value = content.split()  # 以空格分开,图片路径为value[0] , 标签为value[1] , 存入列表
        img_path = path + value[0]  # 拼出图片路径和文件名
        img = Image.open(img_path)  # 读入图片
        img = np.array(img.convert('L'))  # 图片变为8位宽灰度值的np.array格式
        img = img / 255.  # 数据归一化 (实现预处理)
        x.append(img)  # 归一化后的数据,贴到列表x
        y_.append(value[1])  # 标签贴到列表y_
        print('loading : ' + content)  # 打印状态提示

    x = np.array(x)  # 变为np.array格式
    y_ = np.array(y_)  # 变为np.array格式
    y_ = y_.astype(np.int64)  # 变为64位整型
    return x, y_  # 返回输入特征x,返回标签y_


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):
    print('-------------Load Datasets-----------------')
    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:
    print('-------------Generate Datasets-----------------')
    x_train, y_train = generateds(train_path, train_txt)
    x_test, y_test = generateds(test_path, test_txt)

    print('-------------Save 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()
  • 数据增强
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

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
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)  # 给数据增加一个维度,从(60000, 28, 28)reshape为(60000, 28, 28, 1)
'''
image_gen_train=tf.keras.preprocessing.image.ImageDataGenerator(增强方法)
image_gen_train.fit(x_train)

常用增强方法:
        缩放系数:rescale=所有数据将乘以提供的值
        随机旋转:rotation_range=随机旋转角度数范围
        宽度偏移:width_shift_range=随机宽度偏移量
        高度偏移:height_shift_range=随机高度偏移量
        水平翻转:horizontal_flip=是否水平随机翻转
        随机缩放:zoom_range=随机缩放的范围 [1-n,1+n]
例:image_gen_train = ImageDataGenerator(
        rescale=1./255, #原像素值 0~255 归至 0~1
        rotation_range=45, #随机 45 度旋转
        width_shift_range=.15, #随机宽度偏移 [-0.15,0.15)
        height_shift_range=.15, #随机高度偏移 [-0.15,0.15)
        horizontal_flip=True, #随机水平翻转
        zoom_range=0.5 #随机缩放到 [1-50%,1+50%]
'''
image_gen_train = ImageDataGenerator(
    rescale=1. / 1.,  # 如为图像,分母为255时,可归至0~1
    rotation_range=45,  # 随机45度旋转
    width_shift_range=.15,  # 宽度偏移
    height_shift_range=.15,  # 高度偏移
    horizontal_flip=False,  # 水平翻转
    zoom_range=0.5  # 将图像随机缩放阈量50%
)
image_gen_train.fit(x_train)

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()
  • 保存模型,读取模型,查看模型参数,画出loss曲线
import tensorflow as tf
import os
import numpy as np
from matplotlib import pyplot as plt
'''
np.set_printoptions(
        precision=小数点后按四舍五入保留几位,
        threshold=数组元素数量少于或等于门槛值,打印全部元素;否则打印门槛值+1 个元素,中间用省略号补充)
precision=np.inf 打印完整小数位
threshold=np.nan 打印全部数组元
素
'''
np.set_printoptions(threshold=np.inf)

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

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)
'''
借助 tensorflow 给出的回调函数,直接保存参数和网络
tf.keras.callbacks.ModelCheckpoint(
        filepath=路径文件名, 
        save_weights_only=True, 
        monitor='val_loss', # val_loss or loss 
        save_best_only=True)
monitor 配合 save_best_only 可以保存最优模型,包括:训练损失最小模型、
测试损失最小模型、训练准确率最高模型、测试准确率最高模型等
'''
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()

print(model.trainable_variables)
file = open('./weights.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()

###############################################    show   ###############################################
'''
history=model.fit(
            训练集数据, 
            训练集标签, 
            batch_size=, 
            epochs=, 
            validation_split=用作测试数据的比例,
            validation_data=测试集, 
            validation_freq=测试频率)
history:
        loss:训练集 loss
        val_loss:测试集 loss
        sparse_categorical_accuracy:训练集准确率
        val_sparse_categorical_accuracy:测试集准确率
'''
# 显示训练集和验证集的acc和loss曲线
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.title('Training and Validation Accuracy')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()

在这里插入图片描述

  • 应用
from PIL import Image
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

model_save_path = './checkpoint/mnist.ckpt'
model = tf.keras.models.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)


for i in range(10):
    #预测图片路径
    image_path = str(i)+'.png'
    #打开图片
    img = Image.open(image_path)

    image = plt.imread(image_path)
    plt.set_cmap('gray')
    plt.imshow(image)
    #调整尺寸,像素少的图像用这种现实方法
    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)

    print('\n')
    tf.print(pred)

    plt.pause(1)
    plt.close()
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值