“”"
-------------------torch 函数详解----------------------------
“”"
import numpy as np
import torch
from torch.autograd import Variable
from torch import nn
import matplotlib.pyplot as plt
“”“1.torch.is_tensor(x):如果obj 是一个pytorch张量,则返回True”""
x = torch.Tensor(2,3,4) #新建一个pytorch张量
torch.is_tensor(x)
print('result:', torch.is_tensor(x))
输出结果:
result: True
“”“2.torch.is_storage(x):如何x 是一个pytorch storage对象,则返回True”""
print(torch.is_storage(x))
输出结果:
False
“”“3.torch.numel:返回x 张量中的元素个数”""
print(torch.numel(x))
输出结果:
24
“”“4.torch.eye(n, m=None, out=None):返回一个2维张量,对角线位置全1,其它位置全0"”"
y = torch.eye(3)
print(y)
输出结果:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
“”“5.torch.from_numpy(ndarray):Numpy桥,将numpy.ndarray 转换为pytorch的 Tensor。
返回的张量tensor和numpy的ndarray共享同一内存空间。修改一个会导致另外一个也被修改。返回的张量不能改变大小”""
a = np.array([1,2,3])
t = torch.from_numpy(a)
print(t)
输出结果:
tensor([1, 2, 3], dtype=torch.int32)
“”“6.torch.linspace:返回一个1维张量,包含在区间start 和 end 上均匀间隔的steps个点。 输出1维张量的长度为steps
start (float) – 序列的起始点
end (float) – 序列的最终值
steps (int) – 在start 和 end间生成的样本数
out (Tensor, optional) – 结果张量
“””
print(torch.linspace(3, 10, steps=5))
输出:
tensor([ 3.0000, 4.7500, 6.5000, 8.2500, 10.0000])
“”“7.torch.logspace(start, end, steps=100, out=None):返回一个1维张量,包含在区间 10^start和 10^end上以对数刻度均匀间隔的steps个点。
输出1维张量的长度为steps
start (float) – 序列的起始点
end (float) – 序列的最终值
steps (int) – 在start 和 end间生成的样本数
out (Tensor, optional) – 结果张量
“””
print(torch.logspace(start=-10, end=10, steps=5))
输出:
tensor([1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
“”“8.torch.ones(*sizes, out=None):返回一个全为1 的张量,形状由可变参数sizes定义。
sizes (int…) – 整数序列,定义了输出形状
out (Tensor, optional) – 结果张量 例子:
“””
print(torch.ones(2, 3))
输出结果:
tensor([[1., 1., 1.],
[1., 1., 1.]])
“”“9.torch.rand(*sizes, out=None):返回一个张量,包含了从区间[0,1)的均匀分布中抽取的一组随机数,形状由可变参数sizes 定义。
sizes (int…) – 整数序列,定义了输出形状
out (Tensor, optinal) - 结果张量 例子:
“””
print(torch.rand(3))
输出结果:
tensor([0.1480, 0.2517, 0.1265])
“”“10.torch.randn:返回一个张量,包含了从标准正态分布(均值为0,方差为 1,即高斯白噪声)中抽取一组随机数,形状由可变参数sizes定义”""
print("torch.randn: ", torch.randn(3))
输出结果:
torch.randn: tensor([1.2205, 0.2615, 0.4777])
“”“11.torch.randperm:给定参数n,返回一个从0 到 n - 1 的随机整数排列”""
print(torch.randperm(3))
输出结果:
tensor([2, 0, 1])
“”“12.torch.arange:返回一个1维张量,长度为 floor((end−start)/step)。包含从start到end,以step为步长的一组序列值(默认步长为1)。
参数:
start (float) – 序列的起始点
end (float) – 序列的终止点
step (float) – 相邻点的间隔大小
out (Tensor, optional) – 结果张量”""
print("torch.arange: ", torch.arange(1, 5, 1, out = x))
print("x: ", x)
输出结果:
torch.arange: tensor([1., 2., 3., 4.])
x: tensor([1., 2., 3., 4.])
“”"13.torch.range:返回一个1维张量,有 floor((end−start)/step)+1 个元素。包含在半开区间[start, end)
从start开始,以step为步长的一组值。 step 是两个值之间的间隔,即 xi+1=xi+stepxi+1=xi+step
警告:建议使用函数 torch.arange()
参数:
start (float) – 序列的起始点
end (float) – 序列的最终值
step (int) – 相邻点的间隔大小
out (Tensor, optional) – 结果张量"""
print("torch.range: ", torch.range(1.3, 5.6))
输出结果:
torch.range: tensor([1.3000, 2.3000, 3.3000, 4.3000, 5.3000])
“”"14.torch.zeros:返回一个全为标量 0 的张量,形状由可变参数sizes 定义。
参数:
sizes (int…) – 整数序列,定义了输出形状
out (Tensor, optional) – 结果张量"""
print("torch.zeros: ", torch.zeros(5))
输出结果:
torch.zeros: tensor([0., 0., 0., 0., 0.])
“”"15.torch.max:返回输入张量所有元素的最大值。
a.参数:input (Tensor) – 输入张量
b.参数:
input (Tensor) – 输入张量
dim (int) – 指定的维度
max (Tensor, optional) – 结果张量,包含给定维度上的最大值
max_indices (LongTensor, optional) – 结果张量,包含给定维度上每个最大值的位置索引
c.参数:
input (Tensor) – 输入张量
other (Tensor) – 输出张量
out (Tensor, optional) – 结果张量
“”"
aa = torch.randn(5)
print(aa)
print("torch.max111: ", torch.max(aa))
输出结果:
tensor([ 0.4969, -0.1609, -1.3744, -0.6532, 1.2244])
torch.max111: tensor(1.2244)
“”“dim=1 :取矩阵的每一行最大的值 组成一个1维矩阵。dim的值必须小于aa1的维度,比如:如果aa1是2维矩阵那么dim得小于2, aaa1为3为矩阵 dim的值得小于3
dim > 1 :取矩阵的每一列最大的值 组成一个矩阵
“””
aa2 = torch.randn(3, 4)
print(aa2)
print("torch.max222: ", torch.max(aa2, dim=1))
输出结果:
tensor([[ 1.4783, 1.5988, 0.6321, -0.8419],
[-1.6461, 1.4878, 0.9888, -0.2271],
[ 0.6326, 0.1875, 0.6437, -0.9330]])
torch.max222: torch.return_types.max(
values=tensor([1.5988, 1.4878, 0.6437]),
indices=tensor([1, 1, 2]))
aa1 = torch.randn(2, 5, 6)
print(aa1)
输出结果:
tensor([[[ 0.4342, 2.1148, -0.5727, -0.1438, -1.2496, 0.5915],
[-0.6340, -0.5718, 0.7919, -0.5353, 0.0998, -1.6941],
[-0.4791, -0.3789, 1.8555, 1.3287, 0.5841, -0.4429],
[-1.3211, 1.2741, -1.7600, 0.2985, -1.0295, 1.2520],
[ 0.9671, -0.5196, -0.7857, -0.0560, 0.2304, 0.2697]],
[[-1.0855, -0.6774, 0.5850, 0.2507, -0.4710, 1.1073],
[-0.2189, -0.2839, -1.2439, 1.2105, -0.6102, -0.3298],
[-0.4399, -0.3557, -0.7534, 0.4810, -1.2203, 0.7078],
[-0.6699, 2.0302, -1.3209, 0.0196, 1.5503, 0.5045],
[-0.7213, -0.0689, -0.4742, 2.1822, -1.0017, 1.5620]]])
ddww,dede = torch.max(aa1, dim=2)
print("torch.max333: ", ddww, "rfrfrf: ", dede)
输出结果:
torch.max333: tensor([[2.1148, 0.7919, 1.8555, 1.2741, 0.9671],
[1.1073, 1.2105, 0.7078, 2.0302, 2.1822]]) rfrfrf: tensor([[1, 2, 2, 1, 0],
[5, 3, 5, 1, 3]])
#aa2和bbb2个一维矩阵没一个元素对比 输出大的元素 一维矩阵
aa2 = torch.randn(5)
bbb = torch.randn(5)
print("aa2: ", aa2)
print("bbb: ", bbb)
print("torch.max2: ", torch.max(aa2, bbb))
输出结果:
aa2: tensor([ 1.5293, 0.8364, -0.0355, 1.4288, 0.6854])
bbb: tensor([-0.7501, 0.0315, 0.0835, -1.1763, 0.0222])
torch.max2: tensor([1.5293, 0.8364, 0.0835, 1.4288, 0.6854])
“”"16. torch.squeeze:将输入张量形状中的1 去除并返回。 如果输入是形如(A×1×B×1×C×1×D),那么输出形状就为: (A×B×C×D)
当给定dim时,那么挤压操作只在给定维度上。例如,输入形状为: (A×1×B), squeeze(input, 0) 将会保持张量不变,
只有用 squeeze(input, 1),形状会变成 (A×B)。
注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。
参数:
input (Tensor) – 输入张量
dim (int, optional) – 如果给定,则input只会在给定维度挤压
out (Tensor, optional) – 输出张量"""
x1 = torch.zeros(2, 1, 2, 1, 3)
print("squeeze: ", torch.squeeze(x1).size()) #去掉所有的1
print("squeeze1: ", torch.squeeze(x1, 1).size()) #去掉第一个1
输出结果:
squeeze: torch.Size([2, 2, 3])
squeeze1: torch.Size([2, 2, 1, 3])
“”"17.MSELoss(size_average=None, reduce=None, reduction=‘mean’):很多的 loss 函数都有 size_average 和 reduce 两个布尔类型的参数。因为一般损失函数都是直接计算 batch 的数据,因此返回的 loss 结果都是维度为 (batch_size, ) 的向量。
(1)如果 reduce = False,那么 size_average 参数失效,直接返回向量形式的 loss
(2)如果 reduce = True,那么 loss 返回的是标量:
a)如果 size_average = True,返回 loss.mean();
b)如果 size_average = False,返回 loss.sum();
注意:默认情况下, reduce = True,size_average = True
“”"
a=np.array([[1,2],[3,6]])
b=np.array([[2,3],[8,5]])
#返回向量
loss_fn = nn.MSELoss(size_average=False, reduce=False)#一般要求用nn.MSELoss(reduction='none')
input = Variable(torch.from_numpy(a))
target = Variable(torch.from_numpy(b))
loss = loss_fn(input.float(), target.float())
print("loss: ", loss)
输出结果:
loss: tensor([[ 1., 1.],
[25., 1.]])
结果怎么算的?(2-1)的平方,(3-2)的平方,(8-3)的平方,(5-6)的平方即对应位置的差的平方值。
print("---------------------------------------")
#返回平局值
loss_fn1 = nn.MSELoss(size_average=True, reduce=True)#一般要求nn.MSELoss(reduction='mean')这样写
input = Variable(torch.from_numpy(a))
target = Variable(torch.from_numpy(b))
loss = loss_fn1(input.float(), target.float())
print("loss: ", loss)
输出结果为:
loss: tensor(7.) 怎么来的?上面算的(1+1+25+1)/4得到的
“”“18. item(): 一个tensor如果想要转换为标准的python对象数值,需要调用tensor.item(),这个方法只对包含一个元素的tensor适用.
实际就是讲张量转为数字,如下:
如果超过1个元素 必报错。
“””
x_train = np.array([[3.3]])
z1 = torch.from_numpy(x_train)
print("21212: ", z1.item())
输出结果:21212: 3.3
“”"19. plot() :画图
plot函数的一般的调用形式:
#单条线:
plot([x], y, [fmt], data=None, **kwargs)
#多条线一起画
plot([x], y, [fmt], [x2], y2, [fmt2], …, **kwargs)
可选参数[fmt] 是一个字符串来定义图的基本属性如:颜色(color),点型(marker),线型(linestyle),
具体形式 fmt = ‘[color][marker][line]’
fmt接收的是每个属性的单个字母缩写,例如: plot(x, y, ‘bo-’) # 蓝色圆点实线
label :标记每条线或点的 一般是名字之类的
“”"
import matplotlib.pyplot as plt
x = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
[9.779], [6.182], [7.59], [2.167], [7.042],
[10.791], [5.313], [7.997], [3.1]], dtype=np.float32)
y = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
[3.366], [2.596], [2.53], [1.221], [2.827],
[3.465], [1.65], [2.904], [1.3]], dtype=np.float32)
plt.plot(x, y, 'ro', label='swswsw')
plt.legend()
plt.show()
“”“20.交叉熵损失函数: CrossEntropyLoss():公式 loss(x, class) = -x[class] + log(exp(x[0]) + …+ exp(x[j]))
“””
“”“单维度测试--------------------------------------------”""
import torch
import torch.nn as nn
import math
loss = nn.CrossEntropyLoss()
input = torch.randn(1, 5, requires_grad=True)
target = torch.empty(1, dtype=torch.long).random_(4)
output = loss(input, target)
print("输入为5类:")
print(input)
print("要计算loss的类别:")
print(target)
print("计算loss的结果:")
print(output)
first = 0
for i in range(1):
first -= input[i][target[i]] #************** -x[class]
second = 0
for i in range(1):
for j in range(5):
second += math.exp(input[i][j]) #************* exp(x[0]) + ...+ exp(x[j])
res = 0
res += first + math.log(second) #********* -x[class] + log(exp(x[0]) + ...+ exp(x[j]))
print("自己的计算结果:")
print(res)
输出结果:
输入为5类:
tensor([[-1.0431, -0.1981, 1.3219, -1.8172, -0.4636]], requires_grad=True)
要计算loss的类别:
tensor([0])
计算loss的结果:
tensor(2.7861, grad_fn=<NllLossBackward>)
自己的计算结果:
tensor(2.7861, grad_fn=<AddBackward0>)
“”"------------------------------------------------------"""
“”“多维度测试-------------------------------------------”""
import torch
import torch.nn as nn
import math
loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)
print("输入为3个5类:")
print(input)
print("要计算loss的类别:")
print(target)
print("计算loss的结果:")
print(output)
first = [0,0,0]
for i in range(3):
first[i] -= input[i][target[i]]
second = [0,0,0]
for i in range(3):
for j in range(5):
second[i] += math.exp(input[i][j])
res = 0
for i in range(3):
res += first[i] +math.log(second[i])
print("自己的计算结果:")
print(res/3)
输出结果:
输入为3个5类:
tensor([[ 0.9773, -0.8612, -0.7163, 0.6097, 0.0114],
[-0.2555, -1.4427, 1.9644, -0.7308, 2.1826],
[ 0.3451, -1.3543, 0.0665, 0.5910, 0.2061]], requires_grad=True)
要计算loss的类别:
tensor([1, 3, 2])
计算loss的结果:
tensor(2.6667, grad_fn=<NllLossBackward>)
自己的计算结果:
tensor(2.6667, grad_fn=<DivBackward0>)
3维测试:
import torch
import torch.nn as nn
import math
loss = nn.CrossEntropyLoss()#计算公式:loss(x, class) = -x[class] + log(exp(x[0]) + ...+ exp(x[j]))
input = torch.randn(3, 5, 2, requires_grad=True) #input就是x
target = torch.empty(3, 2, dtype=torch.long).random_(5) #target就是class
output = loss(input, target)
print("输入为3个5类:")
print(input)
print("要计算loss的类别:")
print(target)
print("计算loss的结果:")
print(output)
first = [[0,0],[0,0],[0,0]]
for i in range(3):
for j in range(2):
first[i][j] -= input[i][target[i][j]][j] #************** -x[class]
second = [[0,0],[0,0],[0,0]]
for i in range(3):
for j in range(5):
for k in range(2):
second[i][k] += math.exp(input[i][j][k])#************* exp(x[0]) + ...+ exp(x[j])
res = 0
for i in range(3):
for j in range(2):
res += first[i][j] +math.log(second[i][j]) #********* -x[class] + log(exp(x[0]) + ...+ exp(x[j]))
print("自己的计算结果:")
print(res/6)
输出结果:
输入为3个5类:
tensor([[[-0.8542, -0.2139],
[ 1.7634, 0.8149],
[-0.4763, -0.5300],
[-1.3903, -0.4187],
[ 1.4105, -0.3344]],
[[-0.8880, -0.4785],
[-2.3293, -1.0082],
[ 1.3367, 0.6445],
[-0.6875, 0.9052],
[-0.4579, -0.1773]],
[[-0.8935, 1.4309],
[ 0.9779, -0.4425],
[-0.0809, -1.0523],
[-0.3746, -0.2991],
[ 0.4313, -1.3516]]], requires_grad=True)
要计算loss的类别:
tensor([[2, 4],
[3, 4],
[1, 2]])
计算loss的结果:
tensor(2.1585, grad_fn=<NllLoss2DBackward>)
自己的计算结果:
tensor(2.1585, grad_fn=<DivBackward0>)
“”“21.torch.random_(from=0, to=None, *, generator=None)
将tensor用从在[from, to-1]上的正态分布或离散正态分布取样值进行填充。如果没有明确说明,则填充值仅由本tensor的数据类型限定。
random_(x):从[0, x-1]区间取任意一个数填充。
random_(x, y):从[x, y-1]区间取任意一个数填充。
“””
ss = torch.empty(1).random_(6)
print("212121: ", ss)
ss1 = torch.empty(1).random_(6, 9)
print("212121222: ", ss1)
“”"22. SGD:随机梯度下降法
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
随机梯度下降法,支持动量参数,支持学习衰减率,支持Nesterov动量
参数:
lr:大或等于0的浮点数,学习率
momentum:大或等于0的浮点数,动量参数
decay:大或等于0的浮点数,每次更新后的学习率衰减值
nesterov:布尔值,确定是否使用Nesterov动量
有3组数据:
x1 = [2, 3, 4, 5]
x2 = [5, 6, 7, 8]
y = [30, 40 ,50 ,60]
h(x) = ax1 + bx2
梯度算法就是要获取a和b的值 让h(x)的值更接近y的值,同时让随时函数l = loss(x, class)的值l 最小。这就是梯度算法的核心
最终公式是:Q := Q - ρ∑((Yi - H(xi))xi) Q从0到j每一个Q这么算
优点:
随机梯度下降在计算下降最快的方向时时随机选一个数据进行计算,而不是扫描全部训练数据集,这样就加快了迭代速度。
随机梯度下降并不是沿着J(θ)下降最快的方向收敛,而是震荡的方式趋向极小点。
“”"
# -*- coding: utf-8 -*-
import random
# 用y = Θ1*x1 + Θ2*x2来拟合下面的输入和输出
# input1 1 2 5 4
# input2 4 5 1 2
# output 19 26 19 20
input_x = [[1, 4], [2, 5], [5, 1], [4, 2]] # 输入
y = [19, 26, 19, 20] # 输出
theta = [1, 1] # θ参数初始化
loss = 10 # loss先定义一个数,为了进入循环迭代
step_size = 0.01 # 步长
eps = 0.0001 # 精度要求
max_iters = 10000 # 最大迭代次数
error = 0 # 损失值
iter_count = 0 # 当前迭代次数
while (loss > eps and iter_count < max_iters): # 迭代条件
loss = 0
i = random.randint(0, 3) # 每次迭代在input_x中随机选取一组样本进行权重的更新
pred_y = theta[0] * input_x[i][0] + theta[1] * input_x[i][1] # 预测值
theta[0] = theta[0] - step_size * (pred_y - y[i]) * input_x[i][0]
theta[1] = theta[1] - step_size * (pred_y - y[i]) * input_x[i][1]
for i in range(3):
pred_y = theta[0] * input_x[i][0] + theta[1] * input_x[i][1] # 预测值
error = 0.5 * (pred_y - y[i]) ** 2
loss = loss + error
iter_count += 1
print('iters_count', iter_count)
print('theta: ', theta)
print('final loss: ', loss)
print('iters: ', iter_count)
“”“23.torch.view():返回一个有相同数据但大小不同的tensor。 返回的tensor必须有与原tensor相同的数据和相同数目的元素,
但可以有不同的大小。一个tensor必须是连续的contiguous()才能被查看。
另外,参数不可为空。参数中的-1就代表这个位置由其他位置的数字来推断,只要在不致歧义的情况的下,view参数就可以推断出来,也就是人可以推断出形状的情况下
“””
x = torch.randn(4, 4)
print("x: ", x)
print("x.size(): ", x.size())
y = x.view(16)
print("yyy: ", y)
print("y.size(): ", y.size())
z = x.view(-1, 8) # the size -1 is inferred from other dimensions
print("zzzz: ", z)
print("z.size(): ", z.size())
“”“24.train_loader = DataLoader()”""
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision import transforms
train_dataset = datasets.MNIST(
root='F:/PycharmProjects/pytorch-beginner-master/02-Logistic Regression/data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(
root='F:/PycharmProjects/pytorch-beginner-master/02-Logistic Regression/data', train=False, transform=transforms.ToTensor())
batch_size = 32
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
print("训练集总长度: ", len(train_dataset))
print("每个mini_batch的size为32,一共有: ", len(train_loader), "个")
# for i, data in enumerate(train_loader, 1):
# img, label = data #j将数据从train_loader读出来 一次读取的样本数是32个
# img, label = Variable(img), Variable(label)
# print("img.data.size(): ", img.data.size(), "img.data.size(): ", label.data.size())
“”"25.torch.sum(): 返回输入张量input 所有元素的和。
输出形状与输入相同,除了给定维度上为1"""
a = torch.randn(2, 5)
print("cdcdcd: ", a)
print("sum: ", a.sum())
b = torch.randn(2, 5)
num_correct = (a == b).sum()
print("num_correct: ", num_correct)
“”“26.torch.nn.Linear():线形图存, 对传入数据应用线性变换:y = weight* x+ bias,PyTorch的nn.Linear()是用于设置网络中的全连接层的,需要注意的是全连接层的输入与输出都是二维张量,一般形状为[batch_size, size],不同于卷积层要求输入输出是四维张量。
参数:
in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size的值
out_features指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。
从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。
bias - 如果设置为False,则图层不会学习附加偏差。默认值:True”""
x = torch.randn(2, 3)#输入[batch_size=2, size=3]
m = torch.nn.Linear(3, 2)#这里的3就是size,2是要输出的output_size。所以输出是[batch_size,2]
output = m(x)
print('m.weight.shape:\n ', m.weight.shape)
print('m.bias.shape:\n', m.bias.shape)#m.bias由batch_size决定,batch_size的值来源于in_features
print('output.shape:\n', output.shape)
输出结果:
m.weight.shape:torch.Size([2, 3])
m.bias.shape: torch.Size([2])
output.shape:torch.Size([2, 2])
“”"27.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1,
padding=0, dilation=1, groups=1,
bias=True, padding_mode=‘zeros’):2d卷积。
参数:
Input Channels:这个很好理解,就是输入的四维张量[N, C, H, W]中的C了,即输入张量的channels数。也就是输入图像的通道数
(如灰度图像就是1通道,RGB图像忽略alpha通道后就是3通道)。
out_channels:也很好理解,即期望的四维输出张量的channels数,不再多说
Kernel_Size:filter(卷积核)的大小(F),一般我们会使用5x5、3x3这种左右两个数相同的卷积核,因此这种情况只需要写kernel_size = 5这样的就行了。
如果左右两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个tuple,而不能写一个列表(list)
Stride:步长(S),Stride指每次移动卷积核的步长,显然这个值会大幅影响输出的Feature Map的shape。
Padding:边界补充§,Padding指为输入图像外围补充的圈数,注意如28乘28的图像,补充Padding=1就变成30乘30的了(而不是29乘29)。这个值一般直接在卷积时候定义,
不必手动为输入图像加Padding。
计算公式:
输入的大小:W1 H1 D1
输出大小:W2 = ((W1-F+2P)/S) + 1
H2 = ((H1-F+2P)/S) + 1
D2 = K
“”"
"""2维的卷积层,用于图片的卷积"""
# 输入图像的通道数=1(灰度图像),卷积核的种类数=3(K)
# 卷积核的shape是3乘3的,扫描步长为1,不加padding
layer = nn.Conv2d(in_channels=1, out_channels=3, kernel_size=3, stride=1, padding=0)
"""要输入的原始图像"""
# 样本数=1,通道数=1,图像的shape是28乘28的 w=28,F=3 S=1,根据W2 = ((W1-F+2P)/S) + 1算得w2 = (28 - 3)/1 + 1 = 26
x = torch.rand(1, 1, 28, 28)#根据计算公式 输出为:26*26*3
"""使用上面定义的卷积层layer和输入x,完成一次卷积的前向运算"""
out = layer.forward(x)
# 得到的还是1张图片,因为用了3种kernel所以输出的通道数变成3了
# 因为没加padding,原来28乘28的图像在3乘3卷积下得到的边长是28-3+1=26
print("out.shape: ", out.shape) # torch.Size([1, 3, 26, 26])
"""添加padding看看"""
# 这次使用padding为1.所以原始图像上下左右都加了一层0
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=1)
print(layer.forward(x).shape) # torch.Size([1, 3, 28, 28])
"""步长设置为2看看"""
# stride设置为2,也就是每次移动2格子(向上或者向右)
layer = nn.Conv2d(1, 3, kernel_size=3, stride=2, padding=1)
# 相当于每次跳1个像素地扫描,输出的Feature Map直接小了一半
print(layer.forward(x).shape) # torch.Size([1, 3, 14, 14])
"""实际使用时,应该这样用!"""
out = layer(x)
print(out.shape) # torch.Size([1, 3, 14, 14])
“”"28. torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
如果padding不是0,会在输入的每一边添加相应数目0 比如padding=1,则在每一边分别补0 ,其实最后的结果补出来是bias
参数:
kernel_size(int or tuple) - max pooling的窗口大小,可以为tuple,在nlp中tuple用更多,(n,1)
stride(int or tuple, optional) - max pooling的窗口移动的步长。默认值是kernel_size
padding(int or tuple, optional) - 输入的每一条边补充0的层数
dilation(int or tuple, optional) – 一个控制窗口中元素步幅的参数
return_indices - 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助
ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作
“”"
aa = torch.randn(4, 4, 2)
print("aa: ", aa)
bb = nn.MaxPool2d(kernel_size=2, stride=2)
c = bb(aa)
print("c: ", c)
print("c.shape", c.shape)
“”"29. nn.LSTM(in_dim, hidden_dim, n_layer, batch_first=True):LSTM循环神经网络
参数:
input_size: 表示的是输入的矩阵特征数
hidden_size: 表示的是输出矩阵特征数
num_layers 表示堆叠几层的LSTM,默认是1
bias: True 或者 False,决定是否使用bias
batch_first: True 或者 False,因为nn.lstm()接受的数据输入是(序列长度,batch,输入维数),这和我们cnn输入的方式不太一致,所以使用batch_first,我们可以将输入变成(batch,序列长度,输入维数)
dropout: 表示除了最后一层之外都引入一个dropout
bidirectional: 表示双向LSTM,也就是序列从左往右算一次,从右往左又算一次,这样就可以两倍的输出
batch_first: 输入输出的第一维是否为 batch_size,默认值 False。因为 Torch 中,人们习惯使用Torch中带有的dataset,
dataloader向神经网络模型连续输入数据,这里面就有一个 batch_size 的参数,表示一次输入多少个数据。 在 LSTM 模型中,
输入数据必须是一批数据,为了区分LSTM中的批量数据和dataloader中的批量数据是否相同意义,LSTM 模型就通过这个参数的设定来区分。
如果是相同意义的,就设置为True,如果不同意义的,设置为False。 torch.LSTM 中 batch_size 维度默认是放在第二维度,故此参数设置
可以将 batch_size 放在第一维度。如:input 默认是(4,1,5),中间的 1 是 batch_size,指定batch_first=True后就是(1,4,5)。所以,
如果你的输入数据是二维数据的话,就应该将 batch_first 设置为True;
“”"
import torch
import torch.nn as nn
from torch.autograd import Variable
#构建网络模型---输入矩阵特征数input_size、输出矩阵特征数hidden_size、层数num_layers
inputs = torch.randn(5,3,10)# ->(seq_len,batch_size,input_size)
"""inputs = torch.randn(5,3,10) :bitch_size=5, seq_len=3,input_size=10
我的理解:有5个句子,每个句子3个单词,每个单词用10个实数向量表示;而句子的长度是不一样的,所以seq_len可长可短,这也是LSTM可以解决长短序列
的特殊之处。只有seq_len这一参数是可变的。
"""
rnn = nn.LSTM(10,20,2)# -> (input_size,hidden_size,num_layers)
h0 = torch.randn(2,3,20)# ->(num_layers* 1,batch_size,hidden_size)
c0 = torch.randn(2,3,20)# ->(num_layers*1,batch_size,hidden_size)
num_directions=1# 因为是单向LSTM
'''
Outputs: output, (h_n, c_n)
'''
output,(hn,cn) = rnn(inputs,(h0,c0))
#print("out:", out)
“”“30. x.size(num):获取维数”""
dede = torch.Tensor(3, 4, 5)
print("dedede: ", torch.Tensor(3, 4, 5).size(0)) #值是3
print("dedede2: ", torch.Tensor(3, 4, 5).size(1))#值是4
print("dedede3: ", torch.Tensor(3, 4, 5).size(2))#值是5
#print("dedede4: ", torch.Tensor(3, 4, 5).size(3))#报错
frfr = torch.cuda.get_device_name(0)
print("dedede: ", frfr)
31.torch.nn.ReLU(inplace=False):tensor所有的元素中如果小于零的就改为零
1.如果inplace为false,不改变输入,只改变输出
2.如果inplace为true,改变输入
如下例子:
import torch
input = torch.randn(8)
print('input: ', input)
input1 = torch.nn.ReLU(inplace=False)(input)
print('input: ', input)
print('input1: ', input1)
input2 = torch.nn.ReLU(inplace=True)(input)
print('input: ', input)
print('input2: ', input2)
输出结果:
input: tensor([-0.1985, -1.4657, 0.1393, -1.6685, 0.1855, -0.5001, -1.0144, 0.1143])
input: tensor([-0.1985, -1.4657, 0.1393, -1.6685, 0.1855, -0.5001, -1.0144, 0.1143])
input1: tensor([0.0000, 0.0000, 0.1393, 0.0000, 0.1855, 0.0000, 0.0000, 0.1143])
input: tensor([0.0000, 0.0000, 0.1393, 0.0000, 0.1855, 0.0000, 0.0000, 0.1143])
input2: tensor([0.0000, 0.0000, 0.1393, 0.0000, 0.1855, 0.0000, 0.0000, 0.1143])