基于TensorFlow2搭建神经网络实现鸢尾花iris.txt分类

news2024/12/23 1:49:09

分三步:

  1. 本地读取鸢尾花数据集

  1. 搭建神经网络

  1. 优化


本地读取鸢尾花数据集

读取本地数据集的两种方法

读取本地数据集有两种方法:

(1)利用pandas中的函数读取,并处理成神经网络需要的数据结构

pd.read_csv('文件名', header=第几行作为表头, sep='分割符号')

(2)利用open函数打开txt文件,并处理成神经网络需要的数据结构

open('文件名', 'r')

数据集 iris.txt 下载地址: https://cloud.tencent.com/developer/article/1869024

利用pandas函数

'''
利用pandas中的函数读取本地数据集
读取本地文件 —> 取特征输入 —> 取标签 —> 将标签转换为规定格式
'''
import numpy as np
import pandas as pd

# 本地读取鸢尾花数据集  150 rows x 5 columns
df = pd.read_csv(r'E:\学完了学完了\TensorFlow2.0\class1_expand\iris.txt', header=0, sep=' ')   # 读取本地文件,第0行作为表头,空格作为分隔符
data = df.values  # 去掉索引并取值

x_data = [lines[0:4] for lines in data]  # 取输入特征,dtype=object
x_data = np.array(x_data, float)  # 转换为numpy格式
y_data = [lines[4] for lines in data]  # 取标签

for i in range(len(y_data)):
    if y_data[i] == 'setosa':
        y_data[i] = 0
    elif y_data[i] == 'versicolor':
        y_data[i] = 1
    elif y_data[i] == 'virginica':
        y_data[i] = 2
y_data = np.array(y_data)

搭建神经网络

数据集较简单,故利用简单网络结构进行拟合 —— 仅考虑输入层和输出层,构建单层神经网络

参数定义如下:

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、batch、iteration的区别

名词

定义

epoch

使用训练集的全部数据对模型进行一次完整训练,被称之为“一代训练”

batch

使用训练集中的一小部分样本对模型权重进行一次反向传播的参数更新,这一小部分样本被称为“一批数据”

batch_size一般设置为2的指数次幂(默认为32)

iteration

使用一个batch数据对模型进行一次参数更新的过程,被称之为“一次训练”

= epoch / batch_size

梯度下降几种方式的根本区别就在于batch_size不同:

梯度下降方式

Training Set Size

Batch Size

Number of batches

批量梯度下降算法 BGD

N

N

1

随机梯度下降算法 SGD

N

1

N

小批量梯度下降算法 mini-batch

N

B

未整除:N/B(向下取整)+1

整除:N/B

假设数据集有50000个训练样本,现在选择batch size=256对模型进行训练:

  • 每个epoch要训练的图片数量:50000

  • 训练集具有的batch个数:50000/256 + 1 = 196

  • 每个epoch具有的iteration个数:196

  • 10个epoch具有的iteration个数:1960

梯度爆炸

若训练过程中出现如下样子的loss曲线:

说明出现了梯度爆炸,网络不能有效收敛

https://zhuanlan.zhihu.com/p/72589432

(一)产生原因

本质:链式法则的乘法特性所致

梯度下降的计算公式为:

参数更新量为学习率lr与损失函数偏导数相乘,若两者乘积过大,则会导致梯度爆炸

(二)解决方法

可针对学习率lr进行调整,也可对数据进行调整

  1. 逐步减小学习率,0.1/0.01等

  1. 对数据进行预处理后再输入神经网络,减小偏差值的大小,抑制梯度爆炸,即数据归一化与标准化

  1. 线性归一化:将数据映射到 [0,1] 区间

# 线性归一化:x - min / max - min
def normalize(data):
    x_data = data.T    # 每一列为同一属性,转置到每一行
    for i in range(4):
        x_data[i] = (x_data[i] - tf.reduce_min(x_data[i])) / (tf.reduce_max(x_data[i]) - tf.reduce_min(x_data[i]))
    return x_data.T   # 转置回原格式
  1. 非线性归一化(log函数转换):使数据映射到 [0,1] 区间上

  1. Z-Score标准化:使每个特征中的数值平均值变为0,标准差变为1


优化

对网络进行部分优化 —— 增加指数衰减学习率

指数衰减学习率

定义:在训练初期赋予网络较大的学习率,并在训练过程中逐步减小

作用:有效增加网络收敛速度

TensorFlow2中的函数:

tf.compat.v1.train.exponential_decay
tf.compat.v1.train.Optimizer
tf.compat.v1.train.GradientDescentOptimizer
tf.compat.v1.train.exponential_decay(learning_rate_base, global_step, decay_step, decay_rate, staircase=True/False, name)

# learning_rate_base:基础学习率,为事先设定的初始学习率
# global_step:当前训练的轮数/全局步数,系统会自动更新这个参数的值,从1开始,每迭代一次加1
# decay_step:衰减速度(每多少步缩减一次),通常代表了完整的使用一遍训练数据所需要的迭代轮数,这个迭代轮数也就是总训练样本数除以每一个batch中的训练样本数,比如训练数据集的大小为128,每一个batch中样例的个数为8,那么decay_step就为16
# decay_rate:衰减系数,取值0-1
# staircase=True,学习率呈现阶梯状递减,默认为False,即连续衰减

完整代码

下面的代码没加学习率指数衰减,加了的版本一直报错,还没解决...

import numpy as np
import pandas as pd
import tensorflow as tf
from matplotlib import pyplot as plt

# 本地读取鸢尾花数据集  150 rows x 5 columns
df = pd.read_csv('iris.txt', header=0, sep=' ')   # 读取本地文件,第0行作为表头,空格作为分隔符
data = df.values  # 去掉索引并取值

x_data = [lines[0:4] for lines in data]  # 取输入特征,dtype=object
x_data = np.array(x_data, float)  # 转换为numpy格式

y_data = [lines[4] for lines in data]  # 取标签
for i in range(len(y_data)):
    if y_data[i] == 'setosa':
        y_data[i] = 0
    elif y_data[i] == 'versicolor':
        y_data[i] = 1
    elif y_data[i] == 'virginica':
        y_data[i] = 2
y_data = np.array(y_data)

# 数据预处理
# Z-score标准化:x - mean / std
def normalize(data):
    x_data = data.T    # 每一列为同一属性,转置到每一行
    for i in range(4):
        x_data[i] = (x_data[i] - np.mean(x_data[i])) / np.std(x_data[i])
    return x_data.T   # 转置回原格式
normalize(x_data)

# 搭建神经网络
# 随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
# seed: 随机数种子,是一个整数,当设置之后,每次生成的随机数都一样(为方便教学,以保每位同学结果一致)
np.random.seed(116)  # 使用相同的seed,保证打乱顺序后输入特征和标签仍然一一对应
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
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的数据类型,否则后面矩阵相乘时会因数据类型不一致报错
# tf.cast(张量名,dtype=数据类型) 强制将Tensor转换为该数据类型
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)

# 使输入特征和标签值一一对应(把数据集分批次,每个批次batch组数据)
# tf.data.Dataset.from_tensor_slices((输入特征,标签))  配成[输入特征,标签]对,每次喂入一小撮(batch)
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)  # 每32组数据打包为一个batch
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

# 定义神经网络中的所有可训练参数
# 4个输入特征,故输入层为4个输入节点;因为3分类,故输出层为3个神经元(只用一层网络,输出节点数就等于分类数)
# tf.random.truncated_normal(维度,mean=均值,stddev=标准差)   默认均值为0、标准差为1。数据一定在两倍标准差内,数据更向均值集中
# 用tf.Variable()标记参数可训练
# 使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在现实使用时不写seed)
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))

lr = 0.1  # 学习率为0.1
train_loss_results = []  # 将每轮的loss记录在此列表中,为后续画loss曲线提供数据
test_acc = []  # 将每轮的acc记录在此列表中,为后续画acc曲线提供数据
epoch = 500  # 循环500轮
loss_all = 0  # 每轮分4个step,loss_all记录4个step生成的4个loss的和

# 训练部分(嵌套循环迭代,with结构更新参数,显示当前loss)
for epoch in range(epoch):  # 数据集级别的循环,每个epoch循环一次数据集
    # enumerate(列表名)  枚举出每一个元素,并在元素前配上对应的索引号,组合为:索引 元素。常在for循环中使用
    for step, (x_train, y_train) in enumerate(train_db):  # batch级别的循环,每个step循环一个batch
        '''
        在with结构中计算前向传播的预测结果y,计算损失函数loss;
        loss分别对参数w1和b1计算偏导数,更新参数w1和b1的值,打印出这一轮epoch后的损失函数值
        '''
        with tf.GradientTape() as tape:  # with结构记录梯度信息
            y = tf.matmul(x_train, w1) + b1  # 神经网络乘加运算
            y = tf.nn.softmax(y)  # 使输出y符合概率分布(此操作后与独热码同量级,可相减求loss)
            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])  # 嵌套循环loss对w1和b1求偏导

        # 实现梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
        # 每个step更新参数w1和b1
        w1.assign_sub(lr * grads[0])  # 参数w1自更新
        b1.assign_sub(lr * grads[1])  # 参数b自更新

    # 每个epoch,打印loss信息
    '''
    因为训练集有120组数据,batch=32,每个step只能喂入32组数据,
    需要batch级别循环4次,所以loss/4,求得每次step迭代的平均loss
    '''
    print("Epoch {}, loss: {}".format(epoch, loss_all / 4))
    train_loss_results.append(loss_all / 4)  # 将4个step的loss求平均,记录在此变量中
    loss_all = 0  # loss_all归零,为记录下一个epoch的loss做准备

    # 测试部分(计算当前参数前向传播后的准确率,显示当前准确率acc)
    '''
    希望每个epoch循环后可以显示当前模型的效果,即识别准确率,
    故在epoch循环中又嵌套了一个batch级别的循环
    '''
    # 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
        y = tf.nn.softmax(y)  # 变为概率分布
        pred = tf.argmax(y, axis=1)  # 返回y中最大值的索引,即预测的分类(axis=1为横向)
        pred = tf.cast(pred, dtype=y_test.dtype)  # 将pred转换为y_test即标签的数据类型
        correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)  # 若分类正确,则correct=1,否则为0,将bool型的结果转换为int型
        correct = tf.reduce_sum(correct)  # 将每个batch的correct数加起来
        total_correct += int(correct)  # 将所有batch中的correct数加起来
        total_number += x_test.shape[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.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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用码云Gitee创建代码仓库并提交代码

目录 1. 登录Gitee官网 2. 创建代码仓库 3. 克隆仓库到本地 4. 提交代码到Gitee仓库 官方文档:创建你的第一个仓库 - Gitee.com 1. 登录Gitee官网 官网地址:Gitee - 基于 Git 的代码托管和研发协作平台 2. 创建代码仓库 点击图中加号创建仓库&am…

String的不可变性

1.什么是不可变对象 如果一个对象在创建之后就不能再改变它的状态,那么这个对象是不可变的(Immutable)。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型变量的值不能改变,引用类型的变量…

数据库面试题

数据库基础知识 什么是MySQL? MySQL是一个数据库管理系统。 数据库是数据的结构化集合。 MySQL数据库是关系型的。 关系数据库将数据存储在单独的表中,而不是将所有数据放在一个大仓库中。数据库结构被组织成针对速度进行了优化的物理文件。具有对象&a…

第五届字节跳动青训营 前端进阶学习笔记(一)前端和HTML

文章目录1.前言2.什么是前端3.前端需要关注哪些问题4.HTML语法5.HTML标签6.HTML中的内容划分7.总结这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天 1.前言 本次课程主要介绍了: 前端要解决的基本问题HTML的基本定义和语法为什么要语义化和怎么做的语义化 …

深度学习——梯度

一、初识梯度 import torch x torch.arange(4.0) print(x) x.requires_grad_(True) y 2 * torch.dot(x, x) #torch.matmul(x, x) print(y) y.backward() print(x.grad) print(x.grad 4*x)输出&#xff1a; tensor([0., 1., 2., 3.]) tensor(28., grad_fn<MulBackward0&g…

批次标准化Batch Normalization

批次标准化Batch Normalization 目录 批次标准化Batch Normalization 为什么需要批次标准化 产生上述变化趋势不匹配的原因 处理方法 处理方法的优化 Batch Normalization的引出Testing时的相应处理 批次标准化Batch Normalization 第五节 2021 - 类神经网络训练不起来怎么…

从【卡内基梅隆大学机器人概论课】认识机器人学科需要哪些技能栈

闲来无事&#xff0c;找到了卡内基梅隆大学机器人研究所&#xff0c;看了下他们机器人的教育&#xff0c;不得不感慨相比我们学校先进了不知多少&#xff0c;是真真切切让同学们去了解机器人的方方面面&#xff0c;下面摘自它们的概论作业。 作业0 作业1 作业2 作业3 作业4 作…

LeetCode 79 单词搜索 | 解题思路分享

原题链接&#xff1a;79. 单词搜索 题目难度&#xff1a;中等 题目描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的…

css03笔记

目录 css三大特性 优先级 权重叠加计算 chrome调试工具 盒子模型 1.1 盒子模型的介绍 2.1内容的宽度和高度 3.1边框&#xff08;border&#xff09; 3.2边框-单方向设置 3.3边框-单个属性 综合案例一&#xff08;新浪导航&#xff09; 4.1 内边距&#xff08;paddi…

5.11回溯法--电路板排列问题--排列树

问题描述 将n块电路板以最佳排列插入带有n个插槽的机箱中&#xff0c;要求对于给定的电路板连接块&#xff0c;确定最佳排列&#xff0c;使其具有最小的密度。设x[ ] 表示n块电路板的一个排列&#xff0c;x[ i ]表示在机箱的第 i 个插槽中插入电路板x[ i ]&#xff0c;x确定的电…

尚硅谷ES6李强笔记

1.课程介绍 1.es是什么 2.新特性的优点 3.学习课程必备知识背景 2.相关名词介绍 3. let变量声明以及声明特性 3.1变量声明方式 //普通声明 let a;//一次性声明多个变量 let a,b,c;//声明并且初始化 let a 100;//一次性声明多个并且初始化 let a2,b1,ci love you;3.2不允许重…

打工人必学的法律知识(一)——《中华人民共和国劳动合同法》必知必会

目录 一、劳动合同无效或者部分无效 二、竞业限制 三、劳动合同的履行和变更 四、劳动合同的解除和终止 一、劳动合同无效或者部分无效 第二十六条 下列劳动合同无效或者部分无效&#xff1a;&#xff08;一&#xff09;以欺诈、胁迫的手段或者乘人之危&#xff0c;使对方…

使用FFmpeg命令处理音视频

文章目录前言一、ffprobe相关命令1.使用ffprobe查看音频文件的信息2.使用ffprobe查看视频文件的信息二、ffplay相关命令1.基本的ffplay命令2.音视频同步命令三、ffmpeg相关命令1.ffmpeg通用参数2.ffmpeg视频参数3.ffmpeg音频参数4.ffmpeg示例总结前言 FFmpeg是一套可以用来记录…

【C语言】字符函数,字符串函数,内存函数及其模拟实现

文章目录求字符串长度strlen长度不受限制的字符串函数strcpystrcatstrcmp长度受限制的字符串函数strncpystrncatstrncmp字符串查找函数strstrstrtokstrerror字符函数字符分类函数字符转换函数内存操作函数memcpymemmovememsetmemcmp求字符串长度 strlen 函数功能 求字符串长…

【机器学习之模型融合】Voting投票法简单实践

目录 前言&#x1f49c; 1、使用sklearn实现投票法&#x1f494; 1.1、导入工具库&#xff0c;准备数据&#x1f495; 1.2、定义交叉验证评估函数&#x1f496; 1.3、建立基于交叉验证的benchmark、做模型选择&#x1f31f; 1.4、构建多组分类器、进行融合&#x1f4a5;…

单线程的Node.js能开发高并发服务器程序吗?

文章目录前言Nodejs的事件驱动机制EventLoop vs NSRunLoopNSRunLoopios next runloop异步/事件循坏机制的那些坑批量迁移数据原子性参考文献前言 这篇文章还是从一个在写Node.js程序中遇到的问题说起。本周在做数据库迁移的时候&#xff0c;写了下面一段代码&#xff0c;目的是…

代数与逻辑:作业四 神经网络

代数与逻辑&#xff1a;作业四 神经网络 文章目录代数与逻辑&#xff1a;作业四 神经网络一、作业要求二、简述神经网络模型三、编程实现感知机模型与二隐层神经网络1、感知机模型2、二隐层神经网络四、选择公开数据集&#xff0c;测试感知机模型与二隐层神经网络性能一、作业要…

如何高效学习?一年学完麻省理工4年计算机课程

斯科特.杨用用10天拿下线性代数&#xff0c;用1年时间学完麻省理工大学4年的计算机课程&#xff0c;他是如何做到的&#xff1f;他在这本书《如何高效学习》中做了具体阐述。 斯科特.杨很早就发现&#xff0c;在美国有一半的学生在死记硬背&#xff0c;这些学生并不知道使用整体…

动手学区块链学习笔记(二):区块链以及工作量证明算法

引言 紧接上文&#xff0c;在介绍完区块链中的加密解密以及公钥私钥等算法后&#xff0c;本篇开始正式进入区块链概念与一个简单区块链系统的实现过程介绍。 区块链技术介绍 什么是区块链&#xff1f; 区块链&#xff0c;就是一个又一个区块组成的链条。每一个区块中保存了一…

制造企业数据/经营分析框架

背景 随着大数据技术发展以及数字化转型概念的普及&#xff0c;传统企业特别是制造业&#xff0c;也开始投入人力、资金&#xff0c;建立自己的数据分析团队&#xff0c;期望通过数据分析赋能企业的发展/转型。尽管&#xff0c;国内华为、美的、海尔、三一、徐工等制造业龙头企…