from __future__ import print_function
import torch
##1 基本操作
#构建tensor
x = torch.empty(5, 3)
x = torch.rand(5, 3)
x = torch.zero(5, 3, dtype=torch.long)
#Operation
y = torch.rand(5, 3)
torch.add(x, y)
result = torch.empty(5, 3)
torch.add(x, y, out=result) #x+y结果放到result里
y.add_(x)
x.copy_(y)
#Tensor变换
print(x[:, 1]) #打印第一列
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) #-1意思是让torch自己推断第一维大小
##torch几个维度查看和变换的函数
torch.size()
b = a.view(-1, 3, 2) #前后尺寸要一致
torch.squeeze() / torch.unsqueeze()
#torch.squeeze(n)函数表示压缩tensor中第n维为1的维数
>>> b.squeeze(2).size()
torch.Size([1, 3, 2])
>>> b.squeeze(0).size()
torch.Size([3, 2])
#torch.unsqueeze(n)则是在第n维增加一个维数=1
torch.permute() #按照自己期望的位置重新排序
permute(2, 0, 1) #注意数字是维度的index而不是数值
#numpy互转
#np和torch共享地址,修改一个会改变另一个
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
# [2. 2. 2. 2. 2.]
print(b)
# tensor([ 2., 2., 2., 2., 2.], dtype=torch.float64)
#CUDA tensor
if torch.cuda.is_available():
device = torch.device("cuda") # 一个CUDA device对象。
y = torch.ones_like(x, device=device) # 直接在GPU上创建tensor
x = x.to(device) # 也可以使用``.to("cuda")``把一个tensor从CPU移到GPU上
z = x + y
print(z)
print(z.to("cpu", torch.double)) # ``.to``也可以在移动的过程中修改dtype
##2 自动求导
# requires_grad是True,那么PyTorch就会追踪所有与之相关的operation。反向传播backward()
# 在测试时,with torch.no_grad() 不计算梯度
# Function类,与tensor相互连接从而形成一个有向无环图,记录历史。每个tensor有一个grad_fn属性来引用创建这个tensor的Function
x = torch.ones(2, 2, requires_grad=True)
#梯度
out.backward()
print(x.grad) #d(out)/dx
print((x ** 2).requires_grad)
with torch.no_grad(): #用来停止梯度计算
print((x ** 2).requires_grad)
##3 神经网络
#torch.nn来创建
#1)定义网络
import torch
import torch.nn as nn
# import torch.nn.function as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 输入是1个通道的灰度图,输出6个通道(feature map),使用5x5的卷积核
self.conv1 = nn.Conv2d(1, 6, 5)
# 第二个卷积层也是5x5,有16个通道
self.conv2 = nn.Conv2d(6, 16, 5)
#全连接
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), (2,2))
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
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:] # 除了batch维度之外的其它维度。
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
params = list(net.parameters()) #得到模型所有的参数
print(len(params))
print(params[0].size()) # conv1的weight
#2)测试网络
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
#清空梯度
net.zero_grad()
out.backward(torch.randn(1, 10))
#注意:torch.nn只支持mini-batches的输入。整个torch.nn包的输入都必须第一维是batch,即使只有一个样本也要弄成batch是1的输入。
#nn.Conv2d的输入是一个4D的Tensor,shape是nSamples x nChannels x Height x Width。
#如果你只有一个样本(nChannels x Height x Width),那么可以使用input.unsqueeze(0)来增加一个batch维。
#3)损失函数
output = net(input)
criterion = nn.MSELoss()
loss = criterion(output, target)
#4)计算梯度
net.zero_grad() # 清掉tensor里缓存的梯度值。
loss.backward()
#5)更新参数
import torch.optim as optim
# 创建optimizer,需要传入参数和learning rate
optimizer = optim.SGD(net.parameters(), lr=0.01)
#清除梯度,optimizer.zero_grad()一次清除所有。
optimizer.zero_grad()
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()