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()