实现单层神经网络

2023-11-13

在前面,我们分别使用逻辑回归和 softmax 回归实现了对鸢尾花数据集的分类,逻辑回归能够实现线性二分类的任务,他其实就是最简单的神经网络——感知机。
在这里插入图片描述
而softmax回归则实现的是多分类任务,它也可以看做是输出层有多个神经元的单层神经网络。
在这里插入图片描述
下面,使用神经网络的思想来实现对鸢尾花数据集的分类,这个程序的实现过程和 softmax 回归几乎是完全一样的。

在使用神经网络来解决分类问题时,

首先,要设计神经网络的结构(也就是说确定神经网络有几层,每一层中有几个结点,结点之间又是如何连接的,使用什么激活函数,以及什么损失函数)。
在这里插入图片描述
这里,使用没有隐含层的单层前馈型神经网络来实现对鸢尾花的分类。
在这里插入图片描述
其次,编程来实现,

神经网络是一种数学模型,这些结点和结点之间的关系描述的是数学运算,因此实现神经网络实际就是通过多维数组实现这些数学运算。

在鸢尾花数据集的训练集中,一共有120个样本,如果我们一次输入所有样本,那么输入数据 X 就是一个形状为(120,4)的二维数组(为训练样本的属性值),输出层外是一个形状为(120,3)的二维数组(为对训练样本分类后的标签值)。
在这里插入图片描述
在前面的分类实现中,为了简化编程,我们将偏置项B看做是w0,将权值向量构造为m+1维的 W 矩阵,并且令 x0 为全一数组。将 X 向量构造为 m+1 列。
在这里插入图片描述
将这两个矩阵直接运算,
在这里插入图片描述
可以得到同样的结果。
在这里插入图片描述
在这个实验中,我们将 B 从 W 中分离出来,单独表示,这是考虑到后面实现多层神经网络时,编程更加方便直观。

下面,来介绍下实现神经网络的几个函数:

# 1、softmax
tf.nn.softmax(tf.matmul(X_train, W)+b)  # Y = XW+B

# 2、独热编码 one_hot
tf.one_hot(indices, depth)
# 参数 indices 要求是一个整数, 是一个输入项
# 参数 depth 是独热编码的深度

# 将鸢尾花数据集中的标签值转化为用独热编码表示
# 鸢尾花数据集中的标签值是一个浮点数,所以首先要转换为整数
tf.one_hot(tf.constant(y_test, dtype=tf.int32), 3)

# 3、交叉熵损失函数 tf.keras.losses.categorical_crossentropy
tf.keras.losses.categorical_crossentropy(y_true, y_pred)
# 第一个参数表示为独热编码的标签值
# 第二个参数是softmax函数的输出
# 返回值是一个一维张量
# 其中的每一个元素是每个样本的交叉熵损失值
# 因此, 还需要使用平均值函数得到平均交叉熵损失值
tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_train, y_pred=Y_PRED_train))
# 或使用求和函数得到总的交叉熵损失值
tf.reduce_sum(tf.keras.losses.categorical_crossentropy(y_true=Y_train, y_pred=Y_PRED_train))

完整的程序实现

目标:利用单层神经网络实现对鸢尾花数据集的分类

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

plt.rcParams['font.sans-serif'] = "SimHei"
plt.rcParams['axes.unicode_minus'] = False

# 目标:使用花萼长度、花萼宽度、花瓣长度、花瓣宽度四种属性将三种鸢尾花区分开

# 第一步:加载数据集
TRAIN_URL = "http://download.tensorflow.org/data/iris_training.csv"
train_path = tf.keras.utils.get_file(TRAIN_URL.split('/')[-1], TRAIN_URL)
df_iris_train = pd.read_csv(train_path, header=0)  # 表示第一行数据作为列标题

TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"
test_path = tf.keras.utils.get_file(TEST_URL.split('/')[-1], TEST_URL)
df_iris_test = pd.read_csv(test_path, header=0)

# 第二步:数据处理
# 2.1 转化为NumPy数组
iris_train = np.array(df_iris_train)  # 将二维数据表转换为 Numpy 数组, (120, 5), iris的训练集中有120条样本,
iris_test = np.array(df_iris_test)  # 将二维数据表转换为 Numpy 数组, (30, 5), iris的测试集中有30条样本,

# 2.2 提取属性和标签
train_x = iris_train[:, 0:4]  # 取出鸢尾花训练数据集中属性列
train_y = iris_train[:, 4]  # 取出最后一列作为标签值, (120,)

test_x = iris_test[:, 0:4]  # 取出鸢尾花训练数据集中属性列
test_y = iris_test[:, 4]  # 取出最后一列作为标签值, (30, )

# 2.3 数据归一化
# 可以看出这两个属性的尺寸相同,因此不需要进行归一化,可以直接对其进行中心化处理
# 对每个属性进行中心化, 也就是按列中心化, 所以使用下面这种方式
train_x = train_x - np.mean(train_x, axis=0)
test_x = test_x - np.mean(test_x, axis=0)
# 此时样本点的横坐标和纵坐标的均值都是0

# 鸢尾花数据集中的属性值和标签值都是64位的浮点数
print(train_x.dtype)  # float64
print(train_y.dtype)  # float64

# 2.4 生成多元模型的属性矩阵和标签列向量
X_train = tf.cast(train_x, tf.float32)
# 创建张量函数tf.constant()
Y_train = tf.one_hot(tf.constant(train_y, dtype=tf.int32), 3)  # 将标签值转换为独热编码的形式
print(X_train.shape)  # (120, 4)
print(Y_train.shape)  # (120, 3)

X_test = tf.cast(test_x, tf.float32)
# 创建张量函数tf.constant()
Y_test = tf.one_hot(tf.constant(test_y, dtype=tf.int32), 3)  # 将标签值转换为独热编码的形式
print(X_test.shape)  # (30, 4)
print(Y_test.shape)  # (30, 3)

# 第三步:设置超参数和显示间隔
learn_rate = 0.2
itar = 500

display_step = 100

# 第四步:设置模型参数初始值
np.random.seed(612)
# 这里的W是一个(4, 3) 的矩阵
W = tf.Variable(np.random.randn(4, 3), dtype=tf.float32)
# 这里的B是一个(3, ) 的一维张量, 初始化为0
B = tf.Variable(np.zeros([3]), dtype=tf.float32)

# 第五步:训练模型
cross_train = []  # 列表cross_train用来保存每一次迭代的交叉熵损失
acc_train = []  # 用来存放训练集的分类准确率

cross_test = []  # 列表cross_test用来保存每一次迭代的交叉熵损失
acc_test = []  # 用来存放测试集的分类准确率

for i in range(0, itar + 1):

    with tf.GradientTape() as tape:

        # softmax 函数
        # X - (120, 4), W - (4, 3) , 所以 Pred_train - (120, 3), 是每个样本的预测概率
        Pred_train = tf.nn.softmax(tf.matmul(X_train, W) + B)
        # 计算训练集的平均交叉熵损失函数
        Loss_train = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_train, y_pred=Pred_train))

    Pred_test = tf.nn.softmax(tf.matmul(X_test, W) + B)
    # 计算测试集的平均交叉熵损失函数
    Loss_test = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_test, y_pred=Pred_test))

    # 计算准确率函数 -- 因为不需要对其进行求导运算, 因此也可以把这条语句写在 with 语句的外面
    Accuarcy_train = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(Pred_train.numpy(), axis=1), train_y), tf.float32))
    Accuarcy_test = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(Pred_test.numpy(), axis=1), test_y), tf.float32))

    # 记录每一次迭代的交叉熵损失和准确率
    cross_train.append(Loss_train)
    cross_test.append(Loss_test)
    acc_train.append(Accuarcy_train)
    acc_test.append(Accuarcy_test)

    # 对交叉熵损失函数 WB 求偏导
    grads = tape.gradient(Loss_train, [W, B])
    # 函数assign_sub的作用是实现 Variable 变量的减法赋值
    # 更新模型参数 W
    W.assign_sub(learn_rate * grads[0])  # grads[0] 是 dL_dw, 形状为(4,3)
    # 更新模型偏置项参数 B
    B.assign_sub(learn_rate * grads[1])  # grads[1] 是 dL_db, 形状为(3, )

    if i % display_step == 0:
        print("i: %i, TrainLoss: %f, TrainAccuracy: %f, TestLoss: %f, TestAccuracy: %f"
              % (i, Loss_train, Accuarcy_train, Loss_test, Accuarcy_test))

"""
i: 0, TrainLoss: 2.066978, TrainAccuracy: 0.333333, TestLoss: 1.880855, TestAccuracy: 0.266667
i: 100, TrainLoss: 0.223813, TrainAccuracy: 0.933333, TestLoss: 0.280151, TestAccuracy: 0.933333
i: 200, TrainLoss: 0.171492, TrainAccuracy: 0.950000, TestLoss: 0.200843, TestAccuracy: 0.966667
i: 300, TrainLoss: 0.144387, TrainAccuracy: 0.958333, TestLoss: 0.161774, TestAccuracy: 0.966667
i: 400, TrainLoss: 0.127350, TrainAccuracy: 0.966667, TestLoss: 0.137980, TestAccuracy: 0.966667
i: 500, TrainLoss: 0.115541, TrainAccuracy: 0.966667, TestLoss: 0.121931, TestAccuracy: 0.966667
"""
# 第六步:数据可视化
plt.figure(figsize=(12, 5))
plt.subplot(121)
plt.plot(acc_train, color="blue", label="train")
plt.plot(acc_test, color="red", label="test")
plt.title("迭代次数和损失值曲线图", fontsize=22)
plt.xlabel('迭代次数', color='r', fontsize=16)
plt.ylabel('损失值', color='r', fontsize=16)
plt.legend()

plt.subplot(122)
plt.plot(cross_train, color="blue", label="train")
plt.plot(cross_test, color="red", label="test")
plt.title("迭代次数和准确率曲线图", fontsize=22)
plt.xlabel('迭代次数', color='r', fontsize=16)
plt.ylabel('准确率', color='r', fontsize=16)
plt.legend()

plt.show()

运行结果如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现单层神经网络 的相关文章

随机推荐

  • R语言之方差分析篇

    当包含的因子是解释变量时 通常会从预测转向 级别差异的分析 即称作方差分析 ANOVA 组间因子 因变量 自变量 均衡设计 balanced design 组内因子 单因素组间方差分析 单因素组内方差分析 重复测量方差分析 主效应 交叉效应
  • JVM Mutex Monitor::lock

    void Monitor lock Thread Self ifdef CHECK UNHANDLED OOPS Clear unhandled oops so we get a crash right away Only clear fo
  • Windows 下PBC库的安装和配置

    背景 PBC库是一个基于双线性对的密码学库 这库在公钥密码学中使用非常广泛 这个库在Linux下的安装非常的简单 有些只会纸上谈兵的人需要在WIN下做 呵呵 但是没办法 需求到了 硬着头皮也要写完 对于一些只会谈兵的人 呵呵 现在主要介绍下
  • jar反编译的.java文件如何可以编辑_修改及反编译可运行Jar包实现过程详解

    将可运行Jar包 反编译成项目 修改代码 再次编译 打包 需要工具 jd gui myeclipse 具体步骤 1 使用jd gui打开原始的Jar包 选择File gt Save All Sources 会生成一个zip压缩包 2 解压这
  • 元素垂直居中的几种方式

    第一种 div div div div boxOne width 200px height 200px background pink display flex justify content center align items cent
  • ps -aux

    查看某个程序的进程号并删除 1 ps aux grep 进程 2 kill 9 进程号 删除该进程
  • visual studio使用教程

    linux疑难问题排查实战 分享了作为公司专家 在项目开发过程中内存优化 堆 栈 代码段 数据段 性能优化 死机 栈越界 堆越界 死锁等疑难问题排查的案例 使用的工具 perf asan strace memleak等 工作经验 大家可以点
  • blender界面基础认识

    blender界面基础认识 自定义功能 Edit gt Preference 界面 主题 视图 灯光 编辑 动画 插件 输入 视图切换 键位映射 系统 保存 加载 文件路径 Blender界面分为以下三个部分 上侧的顶栏 中间的工作区 底部
  • Sklearn专题二 随机森林

    专题二 随机森林 概述 1 集成算法 1 集成算法考虑多个评估器的结果 汇总获取更好的分类 回归表现 2 三种集成算法 装袋法bagging 模型独立 提升法boosting 模型相关 stacking 3 随机森林是一种bagging集成
  • .NET平台常用的开发组件

    工欲善其事 必先利其器 其优雅的编程风格 高效率的开发速度 极度简单的可扩展性 足够强大开发类库 较小的学习曲线 让我对这个平台产生了浓厚的兴趣 在工作和学习中也积累了一些开源的组件 虽然跟Java比Net还是要少 但也足够使用了 其中有一
  • 【C#实现文字转语音功能】

    本文实例为大家分享了C 实现文字转语音的具体代码 供大家参考 具体内容如下 客户提出要求 将文字内容转为语音 因为内网环境 没办法采用联网 在线这种方式 灵机一动 能否写一个简单的例子呢 搜索相关资料还真行 话不多说 有图有真相 关键是 c
  • 网传Spring爆出更大漏洞?别再炒作了…

    之前刚刚过去的log4j2漏洞还历历在目 这次来了个更大的 云舒老大在29日发微博称 出了个超级大漏洞 有吃瓜群众就问 这个瓜有 log4j2 那么好吃吗 云舒大佬的回复是 更大 之后 又有安全大佬sunwear给了一些更细节的信息 所以漏
  • java中类可以包含哪些元素,Java类中包含的元素及作用

    Java类是面试中常考的知识点 是组成Java应用的基本成分 小型和大型的应用都是由类组建而成的 作为合格的Java工程师 一定要清晰了解Java类及其包含的元素及作用 今天学码思Java培训老师就Java类中包含的元素及作用做一个大致讲解
  • springSecurity跨域CORS处理

    续言 之前 知识追寻者写过关于springboot 的跨域处理 并且介绍了跨域相关的概念 具体的可以查看这篇知识追寻者springboot教程系列文章 https zszxz com category springboot article
  • iOS“断点”(Break Point)你不知道多强大

    iOS 断点 Break Point 你不知道多强大 转载自http mp weixin qq com s biz MzA4ODk0NjY4NA mid 230272985 idx 1 sn 045c98bfb2d8dd1ecf7a7321
  • ssh配置config文件,实现vscode免密登陆

    在使用ssh连接服务器时 每一次用vscode连接服务器进行开发 都需要输入密码 相当鸡肋 对config的配置能够实现解决这个问题 step1 生成ssh密钥 如果已经有了就不需要了 使用以下命令 一路回车即可 ssh keygen t
  • 触发connect超时事件

    触发connect超时事件 有关于如何触发connect超时事件 之前相当然的认为在服务器程序accpet函数前阻塞一段事件就好了 这个思路是完全错误的 这是我犯了的一个错误 没有严格的验证自己的程序就将其发布了出来 被小组的小伙伴提问时才
  • shell编程基础: menu drvien script template(菜单脚本模板)

    前言 菜单类脚本 其实就是我们经常使用的交互脚本 在我们安装一个app的时候最常见 我们需要使用交互脚本进行一些配置 在工作中 写一个交互性脚本也同样重要 比如我现在需要写一个数据库授权的脚本 上下文是这样的 我们在开发中都是使用docke
  • LCD和LED屏幕的工作原理总结

    1 点阵取模原理之横向取模与纵向取模 1 1 针式打印机 针式打印机16针是纵向排列 每次打印垂直的16bit 然后右移一bit 继续下列打印 字节的MSB表示最上面的点 字节LSB表示最下面的点 由于汉字字模的点阵是横向排列的 而提供给打
  • 实现单层神经网络

    在前面 我们分别使用逻辑回归和 softmax 回归实现了对鸢尾花数据集的分类 逻辑回归能够实现线性二分类的任务 他其实就是最简单的神经网络 感知机 而softmax回归则实现的是多分类任务 它也可以看做是输出层有多个神经元的单层神经网络