目录
与使用GPU有关的函数
检查GPU是否可用
torch.cuda.is_available()
若输出为True
,则表明GPU
可用。
输出可用GPU的个数
torch.cuda.device_count()
输出GPU的信息
torch.cuda.get_device_name(0) #序号从0开始
输出当前GPU序号
torch.cuda.current_device()
指定使用GPU
#device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
device = torch.device('cuda:0')
#还需要将模型(神经网络)与数据转移到相应的设备上
model = model.to(device)
data = data.to(device)
#如后面要用到data,可能要使用data.cpu()
#TypeError: can't convert cuda:0 device type tensor to numpy.
#Use Tensor.cpu() to copy the tensor to host memory first.
Pytorch中与矩阵等有关的数学运算函数
Pytorch
中包含了Numpy
中的大多数函数,具体可以参考其官网.
torch.unsqueeze()
这里介绍一个函数torch.unsqueeze(input, dim)
,该函数的功能是在指定的dim
上加上一个冗余维度。
如当我们使用torch.linspace(start, end, num)
或是torch.ones(n)
等产生数据时产生的Tensor
是一维的,而后续的运算都需要基于一个二维(或更高维)的Tensor
,所以需要进行维度的扩展。举例如下:
x = data.ones(5)
x = torch.unsqueeze(x, dim=0) #作为2维张量的首行
x = torch.unsqueeze(x, dim=-1) #作为2维张量的首列
特别的,当在我们想自己搭建一个简单的神经网络时,假若生成data
只有一个feature
时,需要将其变为一个二维张量的一列。举例如下:
x = torch.linspace(-1, 1, 10)
print(x)
print(x.size())
x = torch.unsqueeze(x, dim=1)
print(x)
print(x.size())
输出为
tensor([-1.0000, -0.7778, -0.5556, -0.3333, -0.1111, 0.1111, 0.3333, 0.5556,
0.7778, 1.0000])
torch.Size([10])
tensor([[-1.0000],
[-0.7778],
[-0.5556],
[-0.3333],
[-0.1111],
[ 0.1111],
[ 0.3333],
[ 0.5556],
[ 0.7778],
[ 1.0000]])
torch.Size([10, 1])
还有一种极端情况是只有一个样本数据,此时则需要将其转化为二维张量的一行,即上面的dim
应设为0
。
关于这个函数的更多信息,可以参考下面几个链接:
《torch.squeeze()和torch.unsqueeze()》
《PyTorch中为什么需要使用squeeze()和unsqueeze()操作?》
《torch.unsqueeze() 和 torch.squeeze()》
神经网络类的定义
class NeuralNet(torch.nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(NeuralNet, self).__init__()
self.net = torch.nn.Sequential(
torch.nn.Linear(input_size, hidden_size),
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, hidden_size),
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, output_size)
)
def forward(self, x):
out = self.net(x)
return out
上面的代码定义了一个3层的前馈神经网络。其中两个隐藏层的神经元个数相同,且采用了相同的激活函数。若不同隐藏层采用不同数量的神经元,只需要在__init__()
函数的参数列表中给出,然后在其内进行相关定义即可。上述代码等价于下面的代码:
class NeuralNet(torch.nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(NeuralNet, self).__init__()
self.hidden1 = torch.nn.Linear(input_size, hidden_size)
self.hidden2 = torch.nn.Linear(hidden_size, hidden_size)
self.output= torch.nn.Linear(hidden_size, output_size)
self.act_fun = torch.nn.ReLU()
def forward(self, x):
out = self.hidden1(x)
out = self.act_fun(out)
out = self.hidden2(out)
out = self.act_fun(out)
out = self.output(out)
return out
torch.nn.Linear(input_size, output_size)
定义一个线性全连接层torch.nn.ReLU()
函数表示使用ReLU
激活函数。
实例化一个神经网络类
# to(device)选择在'cpu'或'cuda'上运行
model = NeuralNet(input_size, hidden_size, output_size).to(device)
定义损失函数
loss_fun = torch.nn.MSELoss()
损失函数的选择取决于相应的任务,如回归常用MSE
,而分类常用Cross Entropy
。下面的链接给出了比较全面的torch
中的损失函数及其用法:
PyTorch 学习笔记(六):PyTorch的十八个损失函数
一个需要注意的是多分类采用
CrossEntropyLoss
时,不需要再输出层添加Softmax
激活函数,在调用CrossEntropyLoss
时会自动计算,即此时输出层设为线性全连接层。
BCELoss
是二分类下的交叉熵损失,此时需要显式的在输出层(一个神经元)添加一个Sigmoid
激活函数。
选择并设置优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
一轮迭代的实现
y_hat = model(x) #前向运算
loss = loss_fun(y_hat, y) #计算误差
optimizer.zero_grad() #所有参数的梯度清零,防止累加
loss.backward() #误差反向传播,所有参数的梯度都会被计算
optimizer.step() #进行一次参数更新