知识要点
- 导入数据: (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())