知识核心
- 多层神经网络构成是多个w的问题,如果有n个w,一个b的情况下,则有2^(n-1)个构成方式,比如有两个w的时候,函数公式可以是以下两种:y = xw1w2+b或者y = (xw1 + b)w2
- 多层神经网络会把训练速度降低
- 多层神经网络并不会对最终结果有过多影响,因为最终公式其实就是y = xw + b,只不过其中w被拆分成了多个条件而已
- 多层神经网络计算公式推导:如果y是三行四列的矩阵(3, 4),x是三行九列的举证(3,9)则,y = xw + b中w为九行四列(9,4),b为三行四列(3,4),这时候,把w拆为w1叉乘w2,那么可以为(9,N)叉乘(N,4)
代码
# 使用鸢尾花数据集
import tensorflow as tf
import numpy as np
from sklearn.datasets import load_iris
x_data = load_iris().data # 返回iris数据集所有输入特征值
y_data = load_iris().target # 返回iris数据集所有标签
# 因为x_data和y_data使用同样的随机种子,打乱顺序的算法是一样的,所以打乱后的特征和标签对应关系保持不变
np.random.seed(1024) # 设置随机种子
np.random.shuffle(x_data) # 按随机种子打乱数据顺序
np.random.seed(1024) # 设置随机种子
np.random.shuffle(y_data) # 按随机种子打乱数据顺序
tf.random.set_seed(1024)
# 取钱120条数据集作为训练集
x_train = x_data[:-30]
y_train = y_data[:-30]
# 取后30条数据集作为测试集
x_test = x_data[-30:]
y_test = y_data[-30:]
# 转变特征的数据类型(把numpy类型的数据转为Tensor类型的数据),否则后面矩阵叉乘时会因为数据类型不一致报语法错误
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)
# 配对特征和标签,每次未入神经网络一个batch
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
# 定义神经网络中所有可训练参数
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
w2 = tf.Variable(tf.random.truncated_normal([3, 3], stddev=0.1, seed=1))
b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
b2 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
epoch = 5000 # 循环学习5000次,看实际情况,如果学习的知识太复杂可以增加学习轮数
lr = 0.2 # 定义学习率,也可以根据实际情况调整
"""
这个for迭代了5000次,每次学习一个batch组数据集(第一组batch:32个数据集;第二组batch:32个数据集;第三组batch:32个数据集;第四组batch:24个数据集)
"""
for epoch in range(epoch):
# 下面的for迭代4次(train_db有4个元素,每个元素是一个batch)
for step, (x_train, y_train) in enumerate(train_db):
with tf.GradientTape() as tape:
a = tf.matmul(x_train, w1) + b1 # 计算第一层神经网络
y = tf.matmul(a, w2) + b2 # 计算第二层神经网络
y = tf.nn.softmax(y) # 使y符合概率分布并可以和独热码对比
y_ = tf.one_hot(y_train, depth=3) # 将标签转换为独热码(3分类)
loss = tf.reduce_mean((tf.square(y_ - y))) # 损失函数
grads = tape.gradient(loss, [w1, w2, b1]) # 让loss分别对w1,w2和b1求偏导
w1.assign_sub(lr * grads[0]) # 更新w1(w1 = w1 - lr * w1_grad)
w2.assign_sub(lr * grads[1]) # 更新w2(w1 = w2 - lr * w2_grad)
b1.assign_sub((lr * grads[2])) # 更新b1(b1 = b1 - lr * b1_grad)
b2.assign_sub((lr * grads[2])) # 更新b1(b2 = b2 - lr * b2_grad)
print(f"轮数:{epoch}, loss值:{loss}")
print("-------------------------------------结果--------------------------------------------")
print("=======================================w1结果===============================================")
print(w1)
print("=======================================w2结果===============================================")
print(w2)
print("=======================================b1结果===============================================")
print(b1)
print("=======================================b2结果===============================================")
print(b2)
for x_test, y_test in test_db: # 一次性未入30ge数据集的特征到神经网络,共喂入1次
a = tf.matmul(x_test, w1) # 用求出的w1和b1根据测试集中的特征预测结果
y = tf.matmul(a, w2) + b1 # 用求出的w1和b1根据测试集中的特征预测结果
y = tf.nn.softmax(y) # 让y符合概率分布
pred = tf.argmax(y, axis=1) # 返回y中最大值的索引, 既预测的分类
print("============================结果=================================")
print(pred) # 每个特征值预测的结果,本案例中,我们的神经网络根据30个特征预测的结果
print(y_test) # 测试集中的每个特征对应的标签, 测试集中的30个标签