PyTorch学习笔记|单层神经网络

单层回归网络

其实神经网络并不复杂,我们经过前面的铺垫,如果只看单层的网络(输入层不算),其实就是下面这张图片,好像其实也就是一个线性回归的方程,当然神经网络只所以好用,是因为有多层网络和非线性的激活函数,这个我们后面再来说。

那我们先用tensor来实现一下神经网络的正向传播。

go 复制代码
import torch

X = torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype = torch.float32)
w = torch.tensor([-0.2, 0.15, 0.15])
z = torch.tensor([-0.2, -0.05, -0.05, 0.1])

def Linear(X, w):
    zhat = torch.mv(X, w)
    return zhat

zhat = Linear(X,w)
print(zhat)

#tensor([-0.2000, -0.0500, -0.0500,  0.1000])
x0 x1 x2 z
1 0 0 -0.2
1 1 0 -0.05
1 0 1 -0.05
1 1 1 0.1

nn.Linear实现单层回归网络

当然,我们在pytorch中有专门的类用来创建单层回归网络,我们来看一下代码。

go 复制代码
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,1)
zhat = output(X)
print(zhat)

#result
tensor([[ 0.4556],
        [-0.2170],
        [ 1.0687],
        [ 0.3961]], grad_fn=<AddmmBackward0>)

通过上面代码,我们需要注意几个点: 一是我们看下LInear中的2和1是什么含义,2是in_features,也就是输入数据的特征数量(两个特征,也就是X数据的2列),1是out_features,也就是输出是一个神经元。 二是有没有发现输入的X和我们之前写的少了全是1的一列,因为LInear会自动帮我们生成b偏置数据。 三是我们没有定义w和b,这些是自动生成的随机数,我们可以打印出来看看。

go 复制代码
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,1)
zhat = output(X)
print(output.weight, output.bias)
print(output.weight.shape, output.bias.shape)
print(zhat.shape)

# result
Parameter containing:
tensor([[0.1488, 0.0206]], requires_grad=True) Parameter containing:
tensor([0.4631], requires_grad=True)
torch.Size([1, 2]) torch.Size([1])
torch.Size([4, 1])

当然我们也可以不要偏置。

go 复制代码
output = torch.nn.Linear(2,1,bias=False)

进一步讨论nn.Linear

看完上面的内容,我还是想要了解w和b生成后是怎么计算的,为什么我会有这样的疑问了,因为各种教程在讲解这部分内容写矩阵表达式的时候各不同,用wX,有wTX,还有返回来的Xw和X wT,当然这些都对,只要我们设置好数据的形状格式,那我就想知道pytorch到底是怎么计算的,那我们就来研究下。

我们还是先看上面案例的返回结果,w的形状是(1,2),其实是(out_features,in_features),我们的X形状是(4,2),所以我初步想的是X*wT。然后bias是[1],所以是在加上bias,然后利用广播运算,这样就能得到最后结果。

go 复制代码
# result
Parameter containing:
tensor([[0.1488, 0.0206]], requires_grad=True) Parameter containing:
tensor([0.4631], requires_grad=True)
torch.Size([1, 2]) torch.Size([1])
torch.Size([4, 1]

我们进一步看看源码来验证一下我的想法,确实是这样的。

go 复制代码
self.in_features = in_features
        self.out_features = out_features
        self.weight = Parameter(
            torch.empty((out_features, in_features), **factory_kwargs)
        )
        if bias:
            self.bias = Parameter(torch.empty(out_features, **factory_kwargs))
        else:
            self.register_parameter("bias", None)
        self.reset_parameters()



def linear(input: Tensor, weight: Tensor, bias: Optional[Tensor] = None) -> Tensor:
    # input:  [batch, in_features]
    # weight: [out_features, in_features]
    # bias:   [out_features]

    自动对 weight 做转置 .T,然后矩阵乘法
    output = input @ weight.T

    if bias is not None:
        output += bias #广播运算
    return output

我们把输出改成三个神经元,我们再来加深一下印象。

go 复制代码
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,3)
zhat = output(X)
print(zhat)
print(zhat.shape)
print(output.weight, output.bias)
print(output.weight.shape, output.bias.shape)

# result
tensor([[-0.6868,  0.7037,  0.2460],
        [ 0.0118,  1.1411,  0.8687],
        [-0.1429,  0.2609,  0.0204],
        [ 0.5557,  0.6983,  0.6431]], grad_fn=<AddmmBackward0>)
torch.Size([4, 3])
Parameter containing:
tensor([[ 0.6986,  0.5439],
        [ 0.4374, -0.4428],
        [ 0.6227, -0.2256]], requires_grad=True) Parameter containing:
tensor([-0.6868,  0.7037,  0.2460], requires_grad=True)
torch.Size([3, 2]) torch.Size([3])

二分类:逻辑回归

当然,现实中我们除了要做回归外,还要做一些分类任务,那就有一个大名鼎鼎的函数sigmoid,这样规定大于0.5时,预测结果为1类, 小于0.5时,预测结果为0类,则可以顺利将回归算法转化为分类算法。

go 复制代码
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,1)
zhat = output(X)
sigma = torch.sigmoid(zhat)
result  = torch.where(sigma >= 0.5, torch.tensor(1.0), torch.tensor(0.0))
print(sigma)
print(result)

#result
tensor([[0.6020],
        [0.4350],
        [0.5257],
        [0.3607]], grad_fn=<SigmoidBackward0>)
tensor([[1.],
        [0.],
        [1.],
        [0.]])

还有其他的函数,我们也来一一介绍一下。

  • 阶跃函数sign

  • ReLU函数

  • tanh函数

go 复制代码
torch.sign(zhat)
torch.relu(zhat)
torch.tanh(zhat)

需要注意的是,还可以用nn中的functional来调用,有的会报提醒,说是方法弃用了。

go 复制代码
import torch
import torch.nn.functional as F

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

多分类:Softmax回归

对于多分类来说,我们就要用到Softmax回归。

需要注意的是,由于softmax的分子和分母中都带有为底的指数函数,所以在计算中非常容易出现极大的数值,用torch来计算就不会出现这样的问题,帮我们处理好了。

go 复制代码
X = torch.tensor([[0,0],[1,0],[0,1],[1,1]], dtype = torch.float32)
output = torch.nn.Linear(2,3)
zhat = output(X)
sigma = torch.softmax(zhat,dim=1) #一定要加dim参数,此时需要进行加和的维度是1
print(sigma.shape,sigma)

#result
torch.Size([4, 3]) tensor([[0.3028, 0.2799, 0.4173],
        [0.2970, 0.1531, 0.5500],
        [0.3278, 0.2946, 0.3776],
        [0.3279, 0.1644, 0.5077]], grad_fn=<SoftmaxBackward0>)
相关推荐
AI周红伟5 小时前
All in Token, 移动,电信,联通,阿里,百度,华为,字节,Token石油战争,Token经济,百度要“重写”AI价值度量
大数据·人工智能·机器学习·百度·copilot·openclaw
AI周红伟5 小时前
Token经济学:AI时代的新货币战争,All in Token, 新时代的石油战争,华为,阿里,百度,字节的石油战争
大数据·人工智能·机器学习·百度·华为·copilot·openclaw
XM_jhxx8 小时前
±0.03mm的精度怎么保证?翌东塑胶用AI赋能质量管控升级
人工智能
阿正的梦工坊9 小时前
深入理解 PyTorch 中的 unsqueeze 操作
人工智能·pytorch·python
秦歌66610 小时前
DeepAgents框架详解和文件后端
人工智能·langchain
测试员周周11 小时前
【Appium 系列】第06节-页面对象实现 — LoginPage 实战
开发语言·前端·人工智能·python·功能测试·appium·测试用例
霸道流氓气质11 小时前
基于 Milvus Lite 的 Spring AI RAG 向量库实践方案与示例
人工智能·spring·milvus
ar012311 小时前
AR巡检平台:构筑智能巡检新模式的数字化引擎
人工智能·ar
语音之家12 小时前
【预讲会征集】ACL 2026 论文预讲会
人工智能·论文·acl
碳基硅坊12 小时前
电商场景下的商品自动识别与辅助上架
人工智能