Bootstrap

18- TensorFlow模型中Keras进阶 (TensorFlow系列) (深度学习)

知识要点

  • 导入数据: (x_train, y_train), (x_test, y_test) = mnist.load_data()
  • 标准化处理:  x_train_scaled = scaler.fit_transform(x_train)          # scaler = StandardScaler()
  • one-hot编码: y_train = tf.keras.utils.to_categorical(y_train, 10) 
  • 定义神经网络: model = tf.keras.Sequential()
  • 第一层输入元组或数字: model.add(Dense(64, input_shape=(784)))
  • 添加selu 层: model.add(Dense(64, activation='selu'))
  • 添加激活层: model.add(Activation('relu'))
  • 添加BN层: model.add(BatchNormalization())        # 优化算法
  • 添加输出层: model.add(Dense(10, activation='softmax'))  输出层的激活, 二分类是sigmoid, 多分类的话是softmax .
    • softmax是个非常常用而且比较重要的函数,尤其在多分类的场景中使用广泛。他把一些输入映射为0-1之间的实数,并且归一化保证和为1,因此多分类的概率之和也刚好为1。
  • model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])   配置网络
  • 训练网络: model.fit(x_train_scaled, y_train, batch_size=64, epochs=5)
  • 查看网络参数量: model.summary()
  • 评估模型: model.evaluate(x_test_scaled, y_test)     # loss: 0.1095 - accuracy: 0.9761
  • 保存模型: model.save('./model.h5')        # 只保存模型, 不保存参数
  • 读取模型: model2 = tf.keras.models.load_model('./model.h5')
  • 模型预测: model.predict(x_test)
  • 随机丢弃神经网络: model.add(Dropout(0.2))
  • model.add(AlphaDropout(0.2))  是一种保持输入均值和方差不变的Dropout, 防止过拟合
    • AlphaDropout是一种保持 self-normalizing 属性的Dropout。对于一个0均值和单位标准差的输入,AphaDropout的输出保持输入的均值和标准差不变
    • AlphaDropout和SELU激活函数一起使用,保证了输出是0均值和单位标准差。
  • l1_l2正则化: model.add(Dense(64, activation='relu', kernel_regularizer='l1_l2'))
    •  对于网络层 𝑦=𝑊𝑥+𝑏 ,他们的作用机制是相似的,区别是作用的对象不同, kernel_regularizer作用于权重𝑊,bias_regularizer作用于𝑏,而activity_regularizer则作用于该层的输出𝑦 .
  • dataset: 通常用于训练数据和目标值的集合, 保存到一起. 可以直接传入model 中 .

正则化参考: Keras 中 L1正则化与L2正则化的用法


1 标准化处理原始数据

  • 导入手写数字
# 手写数字 mnist, cifar10
from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
  • 标准化处理
from sklearn.preprocessing import StandardScaler
# 对数据做处理
x_train = x_train.reshape(-1, 784) / 255.0
x_test = x_test.reshape(-1, 784) / 255.0

# 对x_train, x_test做标准化处理
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.transform(x_test)

y_train = y_train.astype(np.float32)
y_test = y_test.astype(np.float32)
  • one_hot编码
# tf.one_hot() 
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)

2 添加BN层

  • 定义模型
  • BN层可以在激活函数之前, 也可以在激活函数之后  # 通常为先激活, 再进行BN
from tensorflow.keras.layers import Dense, BatchNormalization, Activation
# 定义神经网络.
model = tf.keras.Sequential()
# 第一层要多写一个参数, 叫做输入数据的维度. 
# 输入维度有两种写法, 第一种是input_shape, 必须是一个元组, 不要写样本个数
# 只需要写特征的维度即可.
# input_dim, 不需要写元组, 直接指定具体的数字即可
model.add(Dense(64, input_shape=(784, )))
# 先BN再激活
# model.add(BatchNormalization())
# model.add(Activation('relu'))

# 先激活, 再BN
model.add(Activation('relu'))
model.add(BatchNormalization())

model.add(Dense(64))
# model.add(BatchNormalization())
# model.add(Activation('relu'))
model.add(Activation('relu'))
model.add(BatchNormalization())
# 输出层的激活, 二分类是sigmoid, 多分类的话是softmax
model.add(Dense(10, activation='softmax'))
  •  配置网络
# 配置网络
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
# 训练网络
model.fit(x_train_scaled, y_train, batch_size=64, epochs=5,
          validation_data=(x_test_scaled, y_test), )
# 查看网络参数量
model.summary()

 

  • 评估模型
model.evaluate(x_test_scaled, y_test)   # loss: 0.1095 - accuracy: 0.9761
  • 保存模型
# 保存模型 HDF5 分层的数据结构.
model.save('./model.h5')
  • 加载模型
# 加载模型
model2 = tf.keras.models.load_model('./model.h5')
model2.evaluate(x_test, y_test)   # loss: 8.4811 - accuracy: 0.1039
  • 提取预测值
# 预测
model.predict(x_test, ).shape    # (10000, 10)

3 selu 激活函数

深度学习在卷积神经网络(cnn)和循环神经网络(rnn)取得很大突破,但标准前馈网络(ann)的成功消息却很少。因此引入自归一化的神经网络,来尝试进行高级抽象表示。这种自归一化的神经网络的激活函数就是selu,它也是一种基于激活函数的正则化方案。它具有自归一化特点,即使加入噪声也能收敛到均值为0、方差为1或方差具有上下界。
优点:在全连接层效果好,可以避免梯度消失和爆炸
缺点:在卷积网络效果尚未证明。可能引起过拟合。

# 定义神经网络.
model = tf.keras.Sequential()
# selu : scaled, relu -> elu -> selu
model.add(Dense(64, activation='selu', input_shape=(784, )))
model.add(Dense(64, activation='selu'))
model.add(Dense(10, activation='softmax'))

  •  输入方式:  Flatten
  • 一层网络叫做一层Dense
# 定义神经网络.
model = tf.keras.Sequential()
# 第一层要多写一个参数, 叫做输入数据的维度. 
# 输入维度有两种写法, 第一种是input_shape, 必须是一个元组, 不要写样本个数
# 只需要写特征的维度即可.
# input_dim, 不需要写元组, 直接指定具体的数字即可
# Flatten 即reshape, 展平
model.add(Flatten(input_shape=(28, 28)))
model.add(Dense(64, activation='relu'))
# model.add(Dense(64, activation='relu', input_dim=784))
# 出了第一层需要传输入数据的维度, 其他层不需要, keras会自动的帮我们计算维度.
model.add(Dense(64, activation='relu'))
# 输出层的激活, 二分类是sigmoid, 多分类的话是softmax
model.add(Dense(10, activation='softmax'))

4 dropout 正则化

from tensorflow.keras.layers import Dense, Dropout, AlphaDropout
# 定义神经网络.
model = tf.keras.Sequential()
# 第一层要多写一个参数, 叫做输入数据的维度. 
# 输入维度有两种写法, 第一种是input_shape, 必须是一个元组, 不要写样本个数
# 只需要写特征的维度即可.
# input_dim, 不需要写元组, 直接指定具体的数字即可
model.add(Dense(512, activation='relu', input_shape=(784, )))
# model.add(Dropout(0.2))
# 1. 保持方差和均值不变, 2. 归一化性质不变.
model.add(AlphaDropout(0.2))
# model.add(Dense(64, activation='relu', input_dim=784))
# 出了第一层需要传输入数据的维度, 其他层不需要, keras会自动的帮我们计算维度.
model.add(Dense(512, activation='relu'))
# model.add(Dropout(0.2))
model.add(AlphaDropout(0.2))
# 输出层的激活, 二分类是sigmoid, 多分类的话是softmax
model.add(Dense(10, activation='softmax'))

5 L1 L2正则化

  • l1_l2正则化: model.add(Dense(64, activation='relu', kernel_regularizer='l1_l2'))
    •  对于网络层 𝑦=𝑊𝑥+𝑏 ,他们的作用机制是相似的,区别是作用的对象不同, kernel_regularizer作用于权重𝑊,bias_regularizer作用于偏置𝑏,而activity_regularizer则作用于该层的输出𝑦 .
  • 大多数情况下,使用 kernel_regularizer 就足够了;
  • 如果你希望输入和输出是接近的,你可以使用 bias_regularizer;
  • 如果你希望该层的输出尽量小,你应该使用 activity_regularizer。
# 定义神经网络.
model = tf.keras.Sequential()
# 第一层要多写一个参数, 叫做输入数据的维度. 
# input_dim, 不需要写元组, 直接指定具体的数字即可
model.add(Dense(64,activation='relu',kernel_regularizer='l1_l2',input_shape=(784)))
# model.add(Dense(64, activation='relu', input_dim=784))
# 出了第一层需要传输入数据的维度, 其他层不需要, keras会自动的帮我们计算维度.
model.add(Dense(64, activation='relu', kernel_regularizer='l1_l2'))
# 输出层的激活, 二分类是sigmoid, 多分类的话是softmax
model.add(Dense(10, activation='softmax'))

6 dataset 的使用

6.1 dataset 取值

  • form_tensor_slices, 可以从元组, 列表, 字典, ndarray中创建dataset
# 所有数据相关的内容在tf.data中
# form_tensor_slices,可以从元组, 列表, 字典, ndarray中创建dataset
dataset = tf.data.Dataset.from_tensor_slices(np.arange(10))
# 数据集最基础的用法就是取数据
for item in dataset:
    print(item.numpy())    # 0,1,2,3,4,5,6,7,8,9
  • 数据重复三次    # 结果为3次 1-9
# repeat 重复三次
dataset = dataset.repeat(3)
  • 每次取7个数值
# 重复三次, 每次取7个
dataset = dataset.repeat(3).batch(7)
for i in dataset:
    print(i)

 6.2 创建 dataset

  • 通过numpy数组创建
# 从元组创建dataset, (x, y)
x = np.array([[1, 2], [3, 4], [5, 6]])
y = np.array(['cat', 'dog', 'fox'])

dataset = tf.data.Dataset.from_tensor_slices((x, y))
for item_x, item_y in dataset:
    print(item_x.numpy(), item_y.numpy())

  •  使用字典创建 dataset
# 字典的做法
dataset = tf.data.Dataset.from_tensor_slices({
    'feature': x,
    'label' : y
})
for item in dataset:
    print(item['feature'].numpy(), item['label'].numpy())

6.3 dataset.interleave

  • 对现有datasets中的每个元素做处理,产生新的结果,interleave将新的结果合并,并产生新的数据集case:
# interleave
# 最常见用法: 文件名dataset --> 具体数据集
dataset = tf.data.Dataset.from_tensor_slices(np.arange(10))
dataset = dataset.repeat(3).batch(7)
# map_func, 执行操作, cycle_length,并行长度, block_length 
dataset = dataset.interleave(lambda v: tf.data.Dataset.from_tensor_slices(v),
                   cycle_length = 5, 
                   block_length = 5)

for i in dataset:
    print(i.numpy())

官网地址: tf.data.Dataset  |  TensorFlow v2.0.0

;