我的第一个神经网络学习代码
较为通用的前置知识
- 矩阵叉乘,n行m列只能与m行z列叉乘,也就是说第一个矩阵的列数等于第二个矩阵的行数
- 当前神经网络均满足:y=xw+b这个公式,其中我们训练神经网络就是在寻找w的值和b的值,只有损失函数无限趋近于0或者直接等于0,则该神经网络训练完成
- 关于学习率取值,如果取值过大,则会在正确值反复横跳,如果过小,则会训练速度过慢或者直接循环次数不足
- 关于学习次数,根据上一次学习后,通过损失值判断循环次数的数量
环境
pip install tensorflow
pip install numpy
pip install scikit-learn
代码
# 使用鸢尾花数据集
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
# batch中的参数值为每次从总数据中拿到的未使用的前32个,比如当前的120个,那么这次拿到的就是0-31个,下一次拿到的就是32-63,后面的以此类推,如果最后不足,则直接取完
# train_db中的batch中的参数和训练总数量会影响训练速度,比如总数量为5000,而batch中的参数为10和为50的区别就是50的速度谁10的5倍,毕竟每次喂入10个,要喂入500次,而每次喂入50个,只需要喂入100次即可
# test_db中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))
b1 = 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:
y = tf.matmul(x_train, w1) + b1 # 神经网络模型
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, b1]) # 让loss分别对w1和b1求偏导
w1.assign_sub(lr * grads[0]) # 更新w1(w1 = w1 - lr * w1_grad)
b1.assign_sub((lr * grads[1])) # 更新b1(b1 = b1 - lr * b1_grad)
print(f"轮数:{epoch}, loss值:{loss}")
print("-------------------------------------结果--------------------------------------------")
print("=======================================w1结果===============================================")
print(w1)
print("=======================================b1结果===============================================")
print(b1)
"""
=======================================w1结果===============================================
<tf.Variable 'Variable:0' shape=(4, 3) dtype=float32, numpy=
array([[ 1.0305176 , 0.39273214, -1.4889249 ],
[ 2.0761151 , 0.6026204 , -2.6595616 ],
[-2.8738952 , 0.06930634, 2.7183275 ],
[-1.3748647 , -1.905027 , 3.2918143 ]], dtype=float32)>
=======================================b1结果===============================================
<tf.Variable 'Variable:0' shape=(3,) dtype=float32, numpy=array([ 0.48070136, 0.67418057, -0.99409455], dtype=float32)>
"""
# 这部分注释的是之前训练好后的w和b,可以直接使用,也可以上面的神经网络训练完成后直接使用上面的w1和b1
# w1 = [[ 1.0305176 , 0.39273214, -1.4889249 ],
# [ 2.0761151 , 0.6026204 , -2.6595616 ],
# [-2.8738952 , 0.06930634, 2.7183275 ],
# [-1.3748647 , -1.905027 , 3.2918143 ]]
#
# b1 = [ 0.48070136, 0.67418057, -0.99409455]
#
for x_test, y_test in test_db: # 一次性未入30ge数据集的特征到神经网络,共喂入1次
y = tf.matmul(x_test, w1) + b1 # 用求出的w1和b1根据测试集中的特征预测结果
y = tf.nn.softmax(y) # 让y符合概率分布
pred = tf.argmax(y, axis=1) # 返回y中最大值的索引, 既预测的分类
print("============================结果=================================")
print(pred) # 每个特征值预测的结果,本案例中,我们的神经网络根据30个特征预测的结果
print(y_test) # 测试集中的每个特征对应的标签, 测试集中的30个标签