文章目录
log_softmax
F.log_softmax(x, dim=1)
是 PyTorch 中的一个函数,用于对输入张量 x
应用 log-softmax 操作。
解释
-
F.log_softmax
:这是 PyTorch 中的一个函数,位于torch.nn.functional
模块中。它首先对输入进行 softmax 操作,然后取对数。softmax 操作将输入的原始分数转换为概率分布,而取对数可以使后续的计算更稳定且数值范围更适合计算。 -
x
:这是输入张量。通常在神经网络中,它是来自最后一层的输出。 -
dim=1
:这是指定 softmax 操作应用的维度。对于二维张量(例如批处理的数据),dim=1
通常表示在每个样本的类别维度上应用 softmax 操作。
作用
log-softmax 操作的主要作用是在多分类问题中计算模型的输出概率分布,并且在使用负对数似然损失(negative log-likelihood loss,通常用于分类任务)时特别有用。通过先应用 log-softmax,再与目标标签计算负对数似然损失,可以确保计算的数值稳定性。
示例
假设你有一个二维张量 x
,表示模型的未归一化输出(logits),其形状为 [batch_size, num_classes]
。以下是如何使用 F.log_softmax
的示例:
python
import torch
import torch.nn.functional as F
# 模拟模型输出的logits
logits = torch.tensor([[2.0, 1.0, 0.1],
[1.0, 3.0, 0.2]])
# 应用log-softmax
log_probs = F.log_softmax(logits, dim=1)
print(log_probs)
输出可能类似于:
tensor([[-0.4076, -1.4076, -2.3076],
[-2.1269, -0.1269, -3.1269]])
解释输出
- 对于第一个样本
logits = [2.0, 1.0, 0.1]
,应用 log-softmax 后的输出为[-0.4076, -1.4076, -2.3076]
。这些值是输入经过 softmax 转换为概率后取对数的结果。 - 对于第二个样本
logits = [1.0, 3.0, 0.2]
,应用 log-softmax 后的输出为[-2.1269, -0.1269, -3.1269]
。
log-softmax 的输出可以直接用于计算损失函数,例如交叉熵损失,这在分类任务中特别有用。
nll_loss
F.nll_loss(out[data.train_mask], data.y[data.train_mask])
是 PyTorch 中用于计算负对数似然损失(Negative Log-Likelihood Loss, NLLLoss)的一种常见用法,通常用于多分类任务。以下是这个函数的详细解释:
解释
-
F.nll_loss
:这是 PyTorch 中的一个函数,用于计算负对数似然损失。它通常与F.log_softmax
结合使用,因为F.nll_loss
期望输入是对数概率(log-probabilities)。 -
out
:这是模型的输出,即经过F.log_softmax
处理后的对数概率张量。形状通常为[num_nodes, num_classes]
。 -
data.train_mask
:这是一个布尔张量,用于指示哪些节点属于训练集。其形状为[num_nodes]
,值为True
的位置表示对应的节点在训练集中。 -
data.y
:这是节点的标签张量,形状为[num_nodes]
。每个元素表示一个节点的类别标签。
具体操作
-
掩码选择 :使用
data.train_mask
选择训练集中的节点。out[data.train_mask]
:选择模型输出中属于训练集的节点。data.y[data.train_mask]
:选择标签中属于训练集的节点。
-
计算损失 :
F.nll_loss
接收两个参数:input
:对数概率张量,形状为[batch_size, num_classes]
。target
:目标标签张量,形状为[batch_size]
。
-
返回值:返回一个标量,表示训练集上的平均负对数似然损失。
示例代码
假设我们有一个简单的GNN模型,以下是如何使用 F.nll_loss
计算损失的示例代码:
python
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures
# 加载Cora数据集
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=NormalizeFeatures())
data = dataset[0]
# 定义GCN模型
class GCN(torch.nn.Module):
def __init__(self):
super(GCN, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return F.log_softmax(x, dim=1)
# 初始化模型和优化器
model = GCN()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
data = data.to('cuda')
model = model.to('cuda')
# 训练模型
def train():
model.train()
optimizer.zero_grad()
out = model(data)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss.item()
# 评估模型
def test():
model.eval()
out = model(data)
pred = out.argmax(dim=1)
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
acc = int(correct) / int(data.test_mask.sum())
return acc
for epoch in range(200):
loss = train()
acc = test()
print(f'Epoch {epoch+1}, Loss: {loss:.4f}, Accuracy: {acc:.4f}')
解释
- 数据加载:加载Cora数据集并归一化特征。
- 模型定义:定义一个简单的两层GCN模型。
- 训练和评估 :使用
F.nll_loss
计算训练集上的损失,并在每个epoch结束时评估模型在测试集上的准确性。
通过这种方式,F.nll_loss
帮助我们衡量模型在训练集上的表现,并为优化模型提供目标函数。
nll_loss+log_softmax=cross_entropy
为了更简洁地实现负对数似然损失(NLL Loss)和log-softmax的结合,我们可以使用 torch.nn.functional.cross_entropy
。cross_entropy
函数将 log_softmax
和 nll_loss
两个步骤合并在一起,简化了代码,并且在数值上更加稳定和高效。
解释
torch.nn.functional.cross_entropy
:这是 PyTorch 提供的一个函数,用于计算交叉熵损失。它内部会先对输入进行log_softmax
操作,然后计算nll_loss
。input
:未归一化的模型输出(logits),形状为[num_nodes, num_classes]
。target
:目标标签,形状为[num_nodes]
。
代码示例
以下是如何使用 torch.nn.functional.cross_entropy
替代 log_softmax
和 nll_loss
的代码示例:
python
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures
# 加载Cora数据集
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=NormalizeFeatures())
data = dataset[0]
# 定义GCN模型
class GCN(torch.nn.Module):
def __init__(self):
super(GCN, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return x # 返回未归一化的logits
# 初始化模型和优化器
model = GCN()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
data = data.to('cuda')
model = model.to('cuda')
# 训练模型
def train():
model.train()
optimizer.zero_grad()
out = model(data)
loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss.item()
# 评估模型
def test():
model.eval()
out = model(data)
pred = out.argmax(dim=1) # 提取预测类别
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
acc = int(correct) / int(data.test_mask.sum())
return acc
for epoch in range(200):
loss = train()
acc = test()
print(f'Epoch {epoch+1}, Loss: {loss:.4f}, Accuracy: {acc:.4f}')
解释
- 数据加载:加载Cora数据集并归一化特征。
- 模型定义:定义一个简单的两层GCN模型。在前向传播过程中返回未归一化的logits。
- 训练过程 :使用
F.cross_entropy
直接计算损失,它将自动对输入进行log_softmax
并计算nll_loss
。 - 评估过程 :使用
out.argmax(dim=1)
提取预测类别,并计算准确性。
通过这种方式,我们简化了代码,并且避免了在计算 log_softmax
和 nll_loss
时可能出现的数值问题。
argmax()
pred = out.argmax(dim=1)
是 PyTorch 中用于从模型的输出中提取预测类别标签的一个常用方法。以下是详细解释:
解释
-
out
:这是模型的输出,通常是一个形状为[num_nodes, num_classes]
的张量,其中每一行表示一个节点或样本的类别对数概率(log-probabilities)。 -
argmax(dim=1)
:这是一个张量操作,用于在指定维度上找到最大值的索引。dim=1
表示我们在类别维度上进行操作,因此对于每个节点或样本,argmax(dim=1)
将返回具有最大对数概率的类别索引。
作用
通过 argmax(dim=1)
,我们从模型的输出中提取每个节点或样本的预测类别。对于分类任务,这一步是必要的,因为模型的输出通常是每个类别的对数概率分布,我们需要从中选出概率最大的类别作为预测结果。
示例代码
假设我们有一个GNN模型的输出 out
,其形状为 [num_nodes, num_classes]
,以下是如何使用 argmax
提取预测类别的示例代码:
python
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures
# 加载Cora数据集
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=NormalizeFeatures())
data = dataset[0]
# 定义GCN模型
class GCN(torch.nn.Module):
def __init__(self):
super(GCN, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return F.log_softmax(x, dim=1)
# 初始化模型和优化器
model = GCN()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
data = data.to('cuda')
model = model.to('cuda')
# 训练模型
def train():
model.train()
optimizer.zero_grad()
out = model(data)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss.item()
# 评估模型
def test():
model.eval()
out = model(data)
pred = out.argmax(dim=1) # 提取预测类别
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
acc = int(correct) / int(data.test_mask.sum())
return acc
for epoch in range(200):
loss = train()
acc = test()
print(f'Epoch {epoch+1}, Loss: {loss:.4f}, Accuracy: {acc:.4f}')
解释
- 数据加载:加载Cora数据集并归一化特征。
- 模型定义:定义一个简单的两层GCN模型。
- 训练和评估 :在训练过程中使用
F.nll_loss
计算损失。在评估过程中使用out.argmax(dim=1)
提取预测类别,并计算准确性。
示例输出
假设 out
的输出如下:
python
out = torch.tensor([[0.1, 2.3, 0.4],
[1.2, 0.8, 3.5],
[0.6, 0.7, 0.2]])
使用 out.argmax(dim=1)
提取预测类别:
python
pred = out.argmax(dim=1)
print(pred)
输出将是:
tensor([1, 2, 1])
这表示模型预测第一个样本的类别为1,第二个样本的类别为2,第三个样本的类别为1。通过这种方式,我们可以从模型的输出中提取每个样本的预测类别,用于后续的评估或其他处理。