目录
- 与使用GPU有关的函数
- 检查GPU是否可用
- 输出可用GPU的个数
- 输出GPU的信息
- 输出当前GPU序号
- 指定使用GPU
- Pytorch中与矩阵等有关的数学运算函数
- torch.unsqueeze()
- 神经网络类的定义
- 实例化一个神经网络类
- 定义损失函数
- 选择并设置优化器
- 一轮迭代的实现
- 完整代码
与使用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() #进行一次参数更新
完整代码
colab在线