TensorFlow学习笔记(1)及鸢尾花识别代码注释

人工智能的主流:连接主义。

人工智能的三个学派:

1、行为主义:基于控制论,由感知到控制。

2、符号主义:基于表达式,先描述表达式,再求解表达式,是一种用公式描述的人工智能。

3、连接主义:仿生学,神经网络的感性控制。

搭建一个完整的神经网络,往往需要以下几个步骤:

1、准备数据:特征和标签对(数据集)

2、搭建网络:确定神经网络的结构

3、优化参数:(利用反向传播)获取最佳参数

4、应用网络:保存训练模型,应用(前向传播)

神经网络的表达式:y=w*x+b     y表示期望,w表示权重,b表示偏置,在最初的设计中,w和b都是随机设置的。

损失函数:预测期望值与实际值的差距,根据损失函数去判断参数w、b优化的好坏,是否还需要继续优化。常见的是均方误差(MSE),目的就是找到使损失函数最小的w和b。

梯度:损失函数对各参数求偏导后的向量,梯度下降的方向即损失函数变小的方向,沿着梯度的下降方向寻找损失函数的最小值。

迭代函数:wt=wt-lr*(loss对w的偏导)    wt表示参数,lr表示迭代速率

Tensor:张量,多维数组

拥有的数据类型:int、float(32,64)、bool、string

创建张量tensor:tf.constant(张量内容,形状,dtype=数据类型)

张量内容如果是一个数值,那么在张量内部都会填充为该数值。

tf.constant([1 5], shape=(2,), dtype=int64)    表示是一个两行,第一行为1第二行为5的整型张量。

对于numpy格式的数据,要用tf.convert_to_tensor(a,dtype=)转变为tensor。

创建全为0的张量:tf.zeros(维度)

创建全为1的张量:tf.ones(维度)

创建全为指定值的张量:tf.fill(维度,指定值)

生成正态分布的随机数,默认均值为0,标准差为1   tf.random.normal(维度,mean=均值,stddev=标准差)

生成截断式正态分布的随机数   tf.random.truncated_normal(维度,mean=均值,stddev=标准差)

生成均匀分布随机数   tf.random.uniform(维度,minval=最小值,maxval=最大值) 最小最大为前闭后开区间

常见函数:

强制转换类型函数:tf.cast(A张量名,dtype=数据类型)  表明要将张量A转变为dtype后的数据类型

计算张量维度元素上的最小值:tf.reduce_min(张量A)

计算张量维度元素上的最大值:tf.reduce_max(张量A)

axis:指定axis等于0或1,来控制被执行的行与列。

axis=0,表示沿着行垂直往下(列);axis=1,表示沿着列水平向右(行),如果不指定axis,则所有元素都参与计算。

tf.varuable(初始值):

将变量标记为“可训练”,被标记的变量会在反向传播中记录梯度信息。神经网络训练汇总,常用该函数标记带训练参数。

四则运算:

tf.add/subtract/multiply/divide(张量1,张量2),分别表示+-*/,只有相同维度的张量才可以进行四则运算。

平方:tf.square(张量)

次方:tf.pow(张量)

开方:tf.sqrt(张量)

矩阵乘:tf.matmul(a,b)   a,b必须符合矩阵的运算要求

# -*- coding: UTF-8 -*-
# UTF-8编码解码器,使计算机能正确识别中文
# 利用鸢尾花数据集,实现前向传播、反向传播,可视化loss曲线

# 导入所需模块
import tensorflow as tf  #引入tensorflow包,并重命名为tf,后续的tf即表示tensorflow(用于神经网络搭建)
from sklearn import datasets   #从sklearn包下载datasets数据集
from matplotlib import pyplot as plt   #从matplotlib包引入pyplot函数,并重命名为plt(用于记录数据绘图输出图形)
import numpy as np   #引入numpy包重命名为np(用于数值计算和数据扩展)
#一、准备数据
# ①数据集读入
# 导入数据,分别为输入特征和标签
x_data = datasets.load_iris().data  #表示从datasets加载iris的特征数据
y_data = datasets.load_iris().target  #表示从datasets加载iris的标签
#②数据集乱序
# 随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
# seed: 随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
# shuffle用来吧一个列表中的元素顺序随机打乱
np.random.seed(116)  # 使用相同的seed,保证输入特征和标签一一对应,先设置随机数,再执行乱序的shuffle操作
np.random.shuffle(x_data)
np.random.seed(116)   #设置操作级别的种子数
np.random.shuffle(y_data)
# 此时x与y被打乱,但二者的特征和标签仍旧一一对应
tf.random.set_seed(116)    #设置全局种子数
#③生成训练集及测试集
# 将打乱后的数据集分割为训练集和测试集,训练集为前120行,测试集为后30行
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]
y_test = y_data[-30:]

# 转换x的数据类型,否则后面矩阵相乘时会因数据类型不一致报错
# 矩阵相乘时要求数据类型是一致的
x_train = tf.cast(x_train, tf.float32)#转换类型
x_test = tf.cast(x_test, tf.float32)#同上
#④配成(输入特征与标签对),每次读入一小撮
# from_tensor_slices函数使输入特征和标签值一一对应。(把数据集分批次,每个批次batch组数据)
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
# 将训练组的x与y对应起来,后边加.batch表示将该数据组按照每32个一组组成一个batch
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
# 将测试组的x与y对应起来

# 二搭建神经网络
# 生成神经网络的参数,4个输入特征(鸢尾花有四个特征测量数据),输入层为4个输入节点;因为3分类,故输出层为3个神经元
# 用tf.Variable()标记参数可训练
# 使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在现实使用时不写seed)
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
#标记w1是可训练参数,然后随机生成一个截取正态范围内的一部分作为随机数生成的区间(表示生成了一个四行三列,标准差为0.1,随机种子为1的矩阵)
b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
# b1作为偏置项,衡量的是一个神经元激活的难易程度,越大越难以被激活,通过对b的优化,使各个神经元达到最合适的激活状态
lr = 0.1  # 学习率为0.1,即沿着梯度下降方向的步长
train_loss_results = []  # 定义了一个列表(()为元组不可变,[]为列表可变,{}为字典),将每轮的loss记录在此列表中,为后续画loss曲线提供数据
test_acc = []  # 定义了一个列表,将每轮的acc记录在此列表中,为后续画acc曲线提供数据
epoch = 500  # 循环500轮
loss_all = 0  # 每轮分4个step,loss_all记录四个step生成的4个loss的和

# 训练部分
# 120个数据分为每32个数据一组,进行训练。训练500epoch(轮)
for epoch in range(epoch):  #for循环进行迭代训练(for往往针对的是次数已知的循环,while针对的是次数未知的),数据集级别的循环,每个epoch循环一次数据集
    for step, (x_train, y_train) in enumerate(train_db):  #batch级别的循环 ,每个step循环一个batch
        # enumerate函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
        with tf.GradientTape() as tape:  # with,上下文管理器,该结构记录梯度信息
            y = tf.matmul(x_train, w1) + b1  # 神经网络矩阵乘法与加法运算,完成y=w*x+b的运算
            y = tf.nn.softmax(y)  # 使输出y(预测值)符合概率分布(此操作后与独热码同量级,可相减求loss)
            # softmax层的输入是全连接,输出是0-1之间的一个概率值,取最大的为输出结果
            y_ = tf.one_hot(y_train, depth=3)  # 将标签值(实际值)转换为独热码格式,方便计算loss和accuracy
            loss = tf.reduce_mean(tf.square(y_ - y))  # 损失函数采用均方误差mse = mean(sum(y-out)^2),可以消除正负值带来的影响
            loss_all += loss.numpy()  # 将每个step计算出的loss累加,为后续求loss平均值提供数据,这样计算的loss更准确
        # 计算loss对各个参数的梯度
        grads = tape.gradient(loss, [w1, b1])
        # gradient函数,求梯度
        # 实现梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
        w1.assign_sub(lr * grads[0])  # 参数w1自更新,assign_sub 自减
        b1.assign_sub(lr * grads[1])  # 参数b自更新

    # 对每个epoch,打印loss信息
    print("Epoch {}, loss: {}".format(epoch, loss_all/4))
    train_loss_results.append(loss_all / 4)  # 给train_loss_results追加内容,将4个step的loss求平均记录在此变量中
    loss_all = 0  # loss_all归零,为记录下一个epoch的loss做准备

    # 测试部分
    # total_correct为预测对的样本个数, total_number为测试的总样本数,将这两个变量都初始化为0
    total_correct, total_number = 0, 0
    for x_test, y_test in test_db:
        # 使用更新后的参数进行预测
        y = tf.matmul(x_test, w1) + b1
        y = tf.nn.softmax(y)
        pred = tf.argmax(y, axis=1)  # argmax 返回y中最大值的索引,即预测的分类
        # 将pred转换为y_test的数据类型
        pred = tf.cast(pred, dtype=y_test.dtype)  #cast 强制转换数据类型,后边跟某个变量,指的是转变成该变量的格式
        # 若分类正确,则correct=1,否则为0,将bool型的结果转换为int型
        correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)   #比较pred和y_test的数据类型,二者的形式要一致,否则不能进行比较
        # 相同输出true,不同输出false
        # 将每个batch的correct数加起来
        correct = tf.reduce_sum(correct)
        # 将所有batch中的correct数加起来
        total_correct += int(correct)
        # total_number为测试的总样本数,也就是x_test的行数,shape[0]返回变量的行数,0表示返回一个数
        total_number += x_test.shape[0]
    # 总的准确率等于total_correct/total_number
    acc = total_correct / total_number
    test_acc.append(acc)
    print("Test_acc:", acc)
    print("--------------------------")

# 绘制 loss 曲线,plt绘图函数
plt.title('Loss Function Curve')  # 图片标题
plt.xlabel('Epoch')  # x轴变量名称
plt.ylabel('Loss')  # y轴变量名称
plt.plot(train_loss_results, label="$Loss$")  # 逐点画出trian_loss_results值并连线,连线图标是Loss
plt.legend()  # 画出曲线图标
plt.show()  # 画出图像

# 绘制 Accuracy 曲线
plt.title('Acc Curve')  # 图片标题
plt.xlabel('Epoch')  # x轴变量名称
plt.ylabel('Acc')  # y轴变量名称
plt.plot(test_acc, label="$Accuracy$")  # 逐点画出test_acc值并连线,连线图标是Accuracy
plt.legend()
plt.show()

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值