pytorch 60分钟入门

numpy中的ndarray方法和属性

1 NumPy数组的维数称为秩(rank),一维数组的秩为1,二维数组的秩为2,以此类推。这个跟线性代数的秩不太一样。
2 在NumPy中,每一个线性的数组称为是一个轴(axes),秩其实是描述轴的数量。比如说,二维数组相当于是一个一维数组,而这个一维数组中每个元素又是一个一维数组。所以这个一维数组就是NumPy中的轴(axes),而轴的数量——秩,就是数组的维数。
3 Numpy库中的矩阵模块为ndarray对象,有很多属性:T data, dtype, flags, flat, imag, real, size,itemsize,nbytes,ndim,shape,strides,ctypes,base等等。

数组部分

import numpy as np
x=np.array([[1,2,3],[9,8,7],[6,5,4]])
# 打印信息
print(x)
print x.flags  #返回数组内部的信息
x.flat[2:6]   #将数组变为1维数组,并获取其中的一部分数据
x.flat = 4; x   #将值赋给1维数组,再转化成有原有数组的大小形式
# 数组拼接一
# 首先将数组转成列表,然后利用列表的拼接函数append()、extend()等进行拼接处理,最后将列表转成数组。
# 通过list函数来强行转换一下
a_list.extend(b_list)
# 数组拼接二
# numpy提供了numpy.append(arr, values, axis=None)函数。对于参数规定,要么一个数组和一个数值;要么两个数组,不能三个及以上数组直接append拼接。
a=np.arange(5)
np.append(a,10)
b=np.array([11,22,33])

# 要进行赋值,否则将不进行更改
# numpy的数组没有动态改变大小的功能,numpy.append()函数每次都会重新分配整个数组,并把原来的数组复制到新数组中。
np.append(a,b)
# 数组拼接三
# 思路:numpy提供了numpy.concatenate((a1,a2,...), axis=0)函数。能够一次完成多个数组的拼接。其中a1,a2,...是数组类型的参数
a=np.array([1,2,3])
b=np.array([11,22,33])
c=np.array([44,55,66])
np.concatenate((a,b,c),axis=0) ## 默认情况下,axis=0可以不写
np.concatenate((a,b),axis=1)  #axis=1表示对应行的数组进行拼接
# concatenate()效率更高,适合大规模的数据拼接

flags的信息
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False

ndarray部分

x=np.arange(10)  #随机生成一个数组,并重新命名一个空间的数组
x.reshape(2,5)	#改变维度
x.size   #获得数组中元素的个数
x.shape  #获得数组的(行数,列数)
x.reshape(5,2) #重新改变维度
x.base   #获得该数组基于另外一个对象数组而来,如下,y是根据x而来
x.ndim  #获得数组的维数

Ndarray对象的方法

# numpy生成的就是ndarray
ndarray.ptp(axis=None, out=None) : 返回数组的最大值—最小值或者某轴的最大值—最小值
ndarray.clip(a_min, a_max, out=None) : 小于最小值的元素赋值为最小值,大于最大值的元素变为最大值。
ndarray.all():如果所有元素都为真,那么返回真;否则返回假
ndarray.any():只要有一个元素为真则返回真
ndarray.swapaxes(axis1, axis2) : 交换两个轴的元素,如下

array([ [0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])

#这个可以用一下
10
(10,)
y
array([ [0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

torch

# 插入代码块
x = torch.empty(5, 3) #初始化5*3的矩阵
x = torch.rand(5, 3) #随机初始化矩阵
x = torch.zeros(5, 3,) #dtype=torch.long) #创建一个0填充的矩阵,数据类型为long:
x = torch.tensor([5.5, 3]) #创建tensor并使用现有数据初始化:
x = x.new_ones(5, 3, dtype=torch.double)      # new_* 方法来创建对象
x = torch.randn_like(x, dtype=torch.float)    # 覆盖 dtype!
print(x.size())
torch.Size([5, 3])
torch.Size# `` 返回值是 tuple类型, 所以它支持tuple类型的所有操作.
# 任何 以``_`` 结尾的操作都会用结果替换原变量. 例如: ``x.copy_(y)``, ``x.t_()``, 都会改变 ``x``.
# 你可以使用与NumPy索引方式相同的操作来进行对张量的操作
print(x[:, 1])
torch.view#: 可以改变张量的维度和大小
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  #  size -1 从其他维度推断
# 译者注:torch.view 与Numpy的reshape类似
# 如果你有只有一个元素的张量,使用.item()来得到Python数据类型的数值

NumPy 转换

1 将一个Torch Tensor转换为NumPy数组是一件轻松的事,反之亦然。Torch Tensor与NumPy数组共享底层内存地址,修改一个会导致另一个的变化。
将一个Torch Tensor转换为NumPy数组
a = torch.ones(5)
b = a.numpy()
a.add_(1)
输出都是2
2 NumPy Array 转化成 Torch Tensor

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

CUDA 张量

1 使用.to 方法 可以将Tensor移动到任何设备中

# is_available 函数判断是否有cuda可以使用
# ``torch.device``将张量移动到指定的设备中
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA 设备对象
    y = torch.ones_like(x, device=device)  # 直接从GPU创建张量
    x = x.to(device)                       # 或者直接使用``.to("cuda")``将张量移动到cuda中
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # ``.to`` 也会对变量的类型做更改

Autograd: 自动求导机制

1 autograd包为张量上的所有操作提供了自动求导。 它是一个在运行时定义的框架,这意味着反向传播是根据你的代码来确定如何运行,并且每次迭代可以是不同的。
2 torch.Tensor是这个包的核心类。如果设置 .requires_grad 为 True,那么将会追踪所有对于该张量的操作。 当完成计算后通过调用 .backward(),自动计算所有的梯度, 这个张量的所有梯度将会自动积累到 .grad 属性。
3 要阻止张量跟踪历史记录,可以调用**.detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。
4 Tensor 和 Function互相连接并生成一个非循环图,它表示和存储了完整的计算历史。 每个张量都有一个
.grad_fn属性,这个属性引用了一个创建了Tensor的Function(除非这个张量是用户手动创建的,即,这个张量的 grad_fn 是 None)。
5 如果需要计算导数,你可以在Tensor上调用
.backward()**。 如果Tensor是一个标量(即它包含一个元素数据)则不需要为backward()指定任何参数, 但是如果它有更多的元素,你需要指定一个gradient 参数来匹配张量的形状
.requires_grad_( … ) 可以改变现有张量的 requires_grad属性。 如果没 有指定的话,默认输入的flag是 False。

梯度

1 反向传播 因为 out是一个纯量(scalar),out.backward() 等于out.backward(torch.tensor(1))。

np.mean(x==y)#返回条件成立的占比
Out[5]: 0.59999999999999998
np.mean(x)#均值
Out[6]: 3.0

x = torch.randn(3, requires_grad=True)
print(x)
y = x * 2
print(y.data)   #求值
while y.data.norm() < 1000:   # p的范数  括号未写内容默认为求2范数,关于范数的解释见下面代码
    y = y * 2 
print(y)

范数(norm)是数学中的一种基本概念。在泛函分析中,它定义在赋范线性空间中,并满足一定的条件,即①非负性;②齐次性;③三角不等式。
#它常常被用来度量某个向量空间(或矩阵)中的每个向量的长度或大小。
#常用的三种p-范数推导出的矩阵范数:
#1-范数:║A║1 = max{ ∑|ai1|,∑|ai2|,……,∑|ain| } (列和范数,A每一列元素绝对值之和的最大值)
#(其中∑|ai1|第一列元素绝对值的和∑|ai1|=|a11|+|a21|+…+|an1|,其余类似);
#2-范数:║A║2 = A的最大奇异值 = (max{ λi(AHA) }) 1/2 (谱范数,即A^HA特征值λi中最大者λ1的平方根,其中AH为A的转置共轭矩阵);
#∞-范数:║A║∞ = max{ ∑|a1j|,∑|a2j|,…,∑|amj| } (行和范数,A每一行元素绝对值之和的最大值)(其中∑|a1j| 为第一行元素绝对值的和,其余类似);

2 如果.requires_grad=True但是你又不希望进行autograd的计算, 那么可以将变量包裹在 with torch.no_grad()中:
grad 计算导数
backward 计算导数

3 autograd function
backward

Neural Networks

神经网络的典型训练过程如下:

定义包含一些可学习的参数(或者叫权重)神经网络模型;
在数据集上迭代;
通过神经网络处理输入;
计算损失(输出结果和正确值的差值大小);
将梯度反向传播回网络的参数;
更新网络的参数,主要使用如下简单的更新原则: weight = weight - learning_rate * gradient
在这里插入图片描述

import torch
import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features


net = Net()
print(net)

代码解释

conv2d的功能是:对由多个输入平面组成的输入信号进行二维卷积

1
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’)
利用二维卷积,1是batch_size的大小,
Cin 是通道数量也就是6
channel的分类:
最初图片的样本是channels,取决于图片的类型:RGB三通道
卷积完成之后输出的out_channels 取决于卷积核的数量
卷积核中in_channels,或者是上边的out_channels,或者是最初的channels
kernel就是卷积核的大小
stride 就是步长,我理解的应该是水平和竖直方向上的步长
通道数量:每个卷积层中卷积核的数量。
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
在这里插入图片描述

2 torch.nn.Linear()函数的理解
是用来建立一个单层的网络
源码解析:
Linear继承于nn.Module,内部函数主要有__init__,reset_parameters, forward和extra_repr函数
init(self, in_features, out_features, bias=True)
in_features:前一层网络神经元的个数
out_features: 该网络层神经元的个数
以上两者决定了weight的形状[out_features , in_features]
bias: 网络层是否有偏置,默认存在,且维度为[out_features ],若bias=False,则该网络层无偏置。
reset_parameters(self)
参数初始化函数
在__init__中调用此函数,权重采用Xvaier initialization 初始化方式初始参数。
forward(self, input)
在Module的__call__函数调用此函数,使得类对象具有函数调用的功能,同过此功能实现pytorch的网络结构堆叠。
torch.nn.models 是对某种蹭到额封装,包括网络结构以及网络参数和一些操作

3 网络之间怎么进行关联的需要再讨论一下

4 forward 函数
取决于 call函数和init函数
https://blog.csdn.net/xu380393916/article/details/97280035
这篇博主讲的非常清楚,用代码告诉你是怎么运行的
5 Max_pool,Avg_pool
池化函数,减少运算量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章