dl学习笔记:(4)简单神经网络

(1)单层正向回归网络

bx1x2z
100-0.2
110-0.05
101-0.05
1110.1

接下来我们用代码实现这组线性回归数据

import torch
x = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32)
z = torch.tensor([-0.2, -0.05, -0.05, 0.1])
w = torch.tensor([-0.2,0.15,0.15])
def LinearR(x,w):
    zhat = torch.mv(x,w)
    return zhat
zhat = LinearR(x,w)
zhat

下面对这段代码做一个详细说明:

(1)tensor的定义

这里我们需要定义成浮点数的原因,是因为torch中有很多函数不接受两个类型不同的参数传入,例如这里的mv函数,如果我们省略浮点的定义,就会出现报错如下:

这种静态的编程可以说既是pytorch的优点也是缺点,优点在于如果省略了对传入参数的检查处理,就会在运行速度上快很多,尤其是传入数据量大的时候,对每一个数据进行检查是一个很慢的过程。缺点在于你需要人为记住哪些函数是可以不同类型哪些不可以,pytorch没有一个统一的标准,唯一的办法就只有自己多试几次,所以建议大家在定义tensor的时候就默认定义成为float32

另外由于很多pytorch函数不接受一维张量,所以这里我们在定义的时候也养成两个[[的二维张量的习惯

(2)精度问题

如果我们想要查看运行结果是否和答案一致的时候,我们运行下面代码会发现奇怪的现象:

那就是为什么后面三个会是false,这其实就是精度的问题了。

所以当我们人为把精度调高到30位的时候就可以发现问题了:

当数据量大的时候,会因为精度问题产生较大的误差,如果想要控制误差大小,可以使用64位浮点数,唯一的缺点就是会比较占用内存。如果我们想要忽略较小的误差可以使用下面这个函数:

通过shift+tab快捷键来查看函数参数使用,我们也可以通过调整rtol和atol控制误差大小,可以看到这里的默认参数已经挺小的了

(2)torch.nn.Linear

在使用之前,我们先给出pytorch的架构图,包含了常用的类和库

我们先给出代码再进行解释:

import torch
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,1)
zhat = output(X)
zhat

首先nn.Linear是一个类,在这里代表了输出层,所以使用output作为变量名,output的这一行相当于是类的实例化过程。里面输入的参数2和1分别指上一层的神经元个数和这一层的神经元个数。

由于nn.Module的子类会在实例化的同时自动生成随机的w和b,所以这里我们上一层就只有两个x,又由于这是回归类模型所以输出层只有一个。我们也可以调用查看随机生成的数:

如果我们不想要bias可以设置成false:output = torch.nn.Linear(2,1,bias = False)

如果我们不想都每次都随机生成不同的权重,可以设置随机数种子:torch.random.manual_seed(250)

(3)逻辑回归

我们学习过线性回归之后,都知道线性回归能够拟合直线的线性关系,但是现实生活中的数据关系往往不是线性的,所以为了更好的拟合曲线关系,统计学家就在线性回归的方程两边加上了联系函数,这种回归也被叫做广义线性回归。而在探索联系函数的过程中,就发现了sigmoid函数。

\sigma = sigmoid(z) = \frac{1}{1+e^{-z}}

我们可以运行下面代码来画出sigmoid图像:

import numpy as np
import matplotlib.pyplot as plt

# 定义Sigmoid函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 生成x轴数据
x = np.linspace(-10, 10, 400)

# 计算y轴数据
y = sigmoid(x)

# 绘图
plt.figure(figsize=(8, 6))
plt.plot(x, y, label="Sigmoid Function", color='b')
plt.title("Sigmoid Function")
plt.xlabel("x")
plt.ylabel("sigmoid(x)")
plt.grid(True)
plt.axhline(0, color='black',linewidth=0.5)
plt.axvline(0, color='black',linewidth=0.5)
plt.legend()
plt.show()

首先,我们可以观察函数图像,这是一个将所有数映射到(0,1)之间的函数,x趋于负无穷时,函数值趋近于0,x趋近于正无穷时,函数值趋近于1。

运行下面代码,我们可以画出sigmoid的导数图像:

import numpy as np
import matplotlib.pyplot as plt

# 定义Sigmoid函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 定义Sigmoid函数的导数
def sigmoid_derivative(x):
    s = sigmoid(x)
    return s * (1 - s)

# 生成x轴数据
x = np.linspace(-10, 10, 400)

# 计算Sigmoid函数的导数
y_derivative = sigmoid_derivative(x)

# 绘图
plt.figure(figsize=(8, 6))
plt.plot(x, y_derivative, label="Sigmoid Derivative", color='r')
plt.title("Derivative of Sigmoid Function")
plt.xlabel("x")
plt.ylabel("sigmoid'(x)")
plt.grid(True)
plt.axhline(0, color='black',linewidth=0.5)
plt.axvline(0, color='black',linewidth=0.5)
plt.legend()
plt.show()

可以发现在0处取到的导数值最大,往边上走迅速减小,所以它可以快速将数据从0的附近排开。这样的性质,让sigmoid函数拥有将连续型变量转化为离散型变量的力量,这也让它拥有了化回归类问题为分类问题的能力。

当我们将该函数以对数几率的形式表达出来的时候,会发现另一个有趣的地方。

\ln \frac{\sigma }{1-\sigma } =\ln \frac{\frac{1}{1+e^{-xw}}}{1-\frac{1}{1+e^{-xw}}} = \ln \frac{\frac{1}{1+e^{-xw}}}{\frac{e^{-xw}}{1+e^{-xw}}} = \ln\frac{1}{e^{-xw}} = \ln e^{xw} = xw

我们神奇地发现,让取对数几率后所得到的值就是我们线性回归的z,因为这个性质,在等号两边加sigmoid 的算法被称为“对数几率回归”,在英文中就是Logistic Regression,就是逻辑回归。

此时 \sigma1-\sigma之和为1,因此它们可以被我们看作是一对正反例发生的概率,即\sigma是某样本i的标签被预测为1的概率,而1-\sigma是i的标签被预测为0的概率,相比的结果就是样本i的标签被预测为1的相对概率。基于这种理解,虽然可能不严谨,逻辑回归、即单层二分类神经网络返回的结果一般被当成是概率来看待和使用。

(1)与门的实现:

x0x1x2andgate
1000
1100
1010
1111
import torch
X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32)
andgate = torch.tensor([[0],[0],[0],[1]], dtype = torch.float32)
w = torch.tensor([-0.2,0.15,0.15], dtype = torch.float32)
def LogisticR(X,w):
    zhat = torch.mv(X,w)
    sigma = torch.sigmoid(zhat)
    #sigma = 1/(1+torch.exp(-zhat))
    andhat = torch.tensor([int(x) for x in sigma >= 0.5], dtype = torch.float32)
    return sigma, andhat
sigma, andhat = LogisticR(X,w)
andhat

这里我们求sigma的时候用的是库里面的函数,注释的是手动写的。

唯一需要额外解释的是andhat的列表推导式:

sigma >= 0.5 会对 sigma 中的每个元素进行比较,返回一个布尔型张量,并且形状与 sigma 相同举个例子,假设 sigma = torch.tensor([0.2, 0.7, 0.5, 0.3]),那么 sigma >= 0.5 的结果会是:tensor([False,  True,  True, False])
接下来是列表推导式部分,它会遍历 sigma >= 0.5 中的每个布尔值,并将每个布尔值转化为整数(True 转化为 1False 转化为 0)。也就是说,这个列表推导式的功能是将布尔值转换为二分类的预测值(0 或 1)。

上面的例子通过列表推导式 [int(x) for x in sigma >= 0.5],会得到:[0, 1, 1, 0]

当然除了sigmoid还有很多经典的函数,例如sign,ReLU,Tanh等函数,这里我们就不再一一列出来了,用到的时候再说。

(2)torch版本实现

import torch
from torch.nn import functional as F
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
torch.random.manual_seed(250) #人为设置随机数种子
dense = torch.nn.Linear(2,1)
zhat = dense(X)
sigma = F.sigmoid(zhat)
y = [int(x) for x in sigma > 0.5]
y

(4)softmax

当我们遇到多分类问题的时候,往往使用softmax来解决

Softmax 是一种常用于多分类问题的激活函数,特别是在神经网络的输出层,它将一组实数转换为一个概率分布。Softmax 是“归一化指数函数”的一种形式,其主要功能是将任意实数向量转换成一个概率分布,使得每个元素的值介于0和1之间,且所有元素的和为1。这对于多分类问题来说非常重要,因为它可以帮助我们得到不同类别的概率,从而进行分类决策。

可是由于指数的缘故,经常会发生溢出的情况,如下:

所以一般我们不手动自己写softmax,一般会调用pytorch内置的函数

你可能会疑惑为什么这个函数不会出现溢出的问题,这是因为使用了一点小技巧。

为了避免溢出,我们可以将每个输入值z_{i}减去输入向量的最大值max(z),这样可以确保计算中的指数值不会太大,仍然可以保留同样结果的相对比例。通过以下变换,我们可以得到数值稳定的 Softmax:

另外还需要解释一点的是这里的0是什么,我们可以通过快捷键查看函数的参数发现,第二个参数是维度,也就是说该函数需要你指定沿着哪一个维度进行softmax操作。

这里由于是只有一行,所以就是沿着这一行做softmax,所以维度的索引值为0,下面举几个例子:

如果是二维张量dim=1就是对两个小的张量进行softmax

这意味着 Softmax 没有对每个样本独立处理,而是计算了每个类别在所有样本中的相对比例。

我们再举一个大一点的三维张量的例子:

import torch
import torch.nn.functional as F

# 输入一个 3D 张量 (batch_size, channels, height)
z = torch.tensor([[[1.0, 2.0, 3.0, 4.0],   # 第一个样本的 4 个特征值
                  [1.0, 2.0, 3.0, 4.0],   # 第二个样本的 4 个特征值
                  [1.0, 2.0, 3.0, 4.0]],  # 第三个样本的 4 个特征值
                 
                 [[5.0, 6.0, 7.0, 8.0],   # 第一个样本的 4 个特征值
                  [5.0, 6.0, 7.0, 8.0],   # 第二个样本的 4 个特征值
                  [5.0, 6.0, 7.0, 8.0]]]  # 第三个样本的 4 个特征值

# 打印输入张量
print("输入张量:")
print(z)
print("\n")

# 沿着 dim=2 计算 Softmax(计算每个特征维度的概率)
softmax_dim2 = F.softmax(z, dim=2)
print("沿着 dim=2 计算 Softmax:")
print(softmax_dim2)
print("\n")

# 沿着 dim=1 计算 Softmax(计算每个类别的概率)
softmax_dim1 = F.softmax(z, dim=1)
print("沿着 dim=1 计算 Softmax:")
print(softmax_dim1)
print("\n")

# 沿着 dim=0 计算 Softmax(计算每个样本的概率)
softmax_dim0 = F.softmax(z, dim=0)
print("沿着 dim=0 计算 Softmax:")
print(softmax_dim0)

由于这是一个shape为(2,3,4)的张量,所以dim=2也就是最后一个维度4的求和,所以是四个元素加起来等于1;dim=1也就是中间维度3,按照列加起来等于1;dim=0第一个维度2,所以是第一个小张量里面的加第二个小张量里面的等于1.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony-7.IDL工具

IDL 工具 1.openharmony IDL工具 在OpenHarmony中,当应用/系统服务的客户端和服务端进行IPC(Inter-Process Communication)跨线程通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony ID…

openssl s_server源码剥离

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

前端小案例——网页井字棋

前言:我们在学习完了HTML、CSS和JavaScript之后,就会想着使用这三个东西去做一些小案例,不过又没有什么好的案例让我们去练手,本篇文章就提供里一个案例——网页井字棋。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可…

Leetcode 983. 最低票价 动态规划

原题链接&#xff1a;Leetcode 983. 最低票价 class Solution { public:int mincostTickets(vector<int>& days, vector<int>& costs) {int n days.size();int last days[n - 1];int dp[last 1];map<int, int> mp;for (auto x : days)mp[x] 1;dp…

Java中的 锁现象演示和原理解释 多线程操作资源类 八种案例 同步方法 静态方法 对象锁 类锁

目录 面试题 案例 1 标准访问有 ab 两个线程 案例 2 其中一个同步方法暂停 3 秒 案例 3 新增普通方法 案例 4 创建两个对象 案例 5 两个静态同步方法 一个对象 案例 6 两个静态同步方法 两个对象 案例 7 一个静态同步方法 一个普通同步方法 一个对象 案例 8 一个静态同…

HTML应用指南:利用GET请求获取全国特斯拉充电桩位置

随着电动汽车的普及&#xff0c;充电基础设施的建设变得至关重要。作为电动汽车领域的先驱&#xff0c;特斯拉不仅在车辆技术创新上持续领先&#xff0c;还积极构建广泛的充电网络&#xff0c;以支持其不断增长的用户群体。为了提升用户体验和服务质量&#xff0c;开发人员和数…

cuda + cudnn安装

1.安装CUDA Toolkit 在设备管理器&#xff08;此电脑–右键–属性&#xff09;的显示适配器中可以查看自己的显卡型号&#xff0c;去下载对应的CUDA Toolkit 。或者输入以下命令查看Driver Version &#xff0c;cuda Version&#xff1a;12.2代表12.2版本以下兼容可以进行安装 …

【k8s面试题2025】1、练气期

主要通过呼吸吐纳等方法&#xff0c;将外界的天地灵气吸入体内&#xff0c;初步改造身体&#xff0c;使身体素质远超常人。 文章目录 docker 和虚拟机的不同Kubernetes 和 docker 的关系Kube-proxy IPVS 和 iptables 的异同蓝绿发布Kubernetes中常见的数据持久化方式关于 Docke…

vue | 插值表达式

Vue 是一个用于 构建用户界面 的 渐进式 框架 1. 构建用户界面&#xff1a;基于 数据 动态 渲染 页面 2. 渐进式&#xff1a;循序渐进的学习 3. 框架&#xff1a;一套完整的项目解决方案&#xff0c;提升开发效率↑ (理解记忆规则) 插值表达式&#xff1a; 插值表达式是一种 Vu…

【蜂巢——方向,数学】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; int dx[6] {-1, -1, 0, 1, 1, 0}; int dy[6] {0, 1, 1, 0, -1, -1}; void cal(int d, int p, int q, int& x, int& y) {x p * dx[d];y p * dy[d];d (d 2) % 6;x q * dx[d];…

C语言进阶习题【1】指针和数组(1)——一维数组

1. 数组名的意义&#xff1a; sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小。&数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址。除此之外所有的数组名都表示首元素的地址。&#xff08;一维数…

禁用输入法的方案

车间运行的SF系统&#xff0c;扫描产品条码。WB输入法等工具流氓软件&#xff0c;文本框获得焦点之后&#xff0c;自动打开输入状态&#xff0c;美其名日&#xff0c;智能化。输入法open状态下&#xff0c;扫描条码是乱码的&#xff0c;或是不全&#xff0c;缺字符。分析是输入…

Linux提权-02 sudo提权

文章目录 1. sudo 提权原理1.1 原理1.2 sudo文件配置 2. 提权利用方式2.1 sudo权限分配不当2.2 sudo脚本篡改2.3 sudo脚本参数利用2.4 sudo绕过路径执行2.5 sudo LD_PRELOAD环境变量2.6 sudo caching2.7 sudo令牌进程注入 3. 参考 1. sudo 提权原理 1.1 原理 sudo是一个用于在…

3. 后端验证前端Token

书接上回&#xff0c;后端将token返回给前端&#xff0c;前端存入cookie&#xff0c;每次前端给后端发送请求&#xff0c;后端是如何验证的。 若依是用过滤器来实现对请求的验证&#xff0c;过滤器的简单理解是每次发送请求的时候先发送给过滤器执行逻辑判断以及处理&#xff0…

【转】厚植根基,同启新程!一文回顾 2024 OpenHarmony 社区年度工作会议精彩瞬间

在数字化浪潮奔腾不息的今天&#xff0c;开源技术已成为推动科技创新与产业发展的强大引擎。2025年1月10日-11日&#xff0c;OpenAtom OpenHarmony&#xff08;开放原子开源鸿蒙&#xff0c;以下简称“OpenHarmony”或“开源鸿蒙”&#xff09;社区2024年度工作会议于深圳盛大启…

数据结构(Java版)第九期:LinkedList与链表(四)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、LinkedList的模拟实现 1.1. 头插法 1.2. 尾插法 1.3. 插入中间节点 1.4. 删除某个节点 1.5. 删除所有为key的元素 二、LinkedList的使用 2.1. 什么是LinkedList 2.2. LinkedList的使⽤ 三、…

第22篇 基于ARM A9处理器用汇编语言实现中断<四>

Q&#xff1a;怎样编写ARM A9处理器汇编语言代码配置使用按键和定时器中断&#xff1f; A&#xff1a;本次实验同样为中断模式和监督模式都设置ARM A9堆栈指针&#xff0c;并使能中断&#xff0c;此外在主程序中调用子程序CONFIG_HPS_TIMER和CONFIG_KEYS分别对HPS Timer 0&…

Python学习(十三)什么是模块、模块的引入、自定义模块、常见的内置模块(math、random、os、sys、uuid、时间模块、加密模块)

目录 一、什么是模块&#xff1f;1.1 定义1.2 分类1.3 五种模块引入的方法1&#xff09;import 模块名&#xff08;全部引入&#xff09;2&#xff09;from 模块名 import 功能名&#xff08;部分引入&#xff09;3&#xff09;from 模块名 import *&#xff08;引入公共功能&a…

宝塔php7.4安装报错,无法安装,php8以上可以安装,以下的不行,gd库什么的都正常

宝塔的依赖问题导致的问题&#xff0c;最后手动挂载后才解决。。。废了三天三夜终于搞好了。。。。无语&#xff5e; 建议&#xff1a;不要一直升级宝塔版本&#xff0c;升级前备份或者开服务商的实例镜像&#xff0c;方便恢复&#xff0c;不然&#xff0c;可就GG了&#xff5…

C语言:-三子棋游戏代码:分支-循环-数组-函数集合

思路分析&#xff1a; 1、写菜单 2、菜单之后进入游戏的操作 3、写函数 实现游戏 3.1、初始化棋盘函数&#xff0c;使数组元素都为空格 3.2、打印棋盘 棋盘的大概样子 3.3、玩家出棋 3.3.1、限制玩家要下的坐标位置 3.3.2、判断玩家要下的位置是否由棋子 3.4、电脑出棋 3.4.1、…