Pearson相关系数通常用于衡量两个变量之间的线性相关性。
之前介绍了如何用python模拟Pearson相关系数损失。
https://blog.csdn.net/liliang199/article/details/155751622
pytorch是最流行的模型训练工具,这里尝试用pytorch实现Pearson loss训练模型的过程。
所用代码和示例参考和修改自网络资料。
1 模型定义
这里参考pytorch开发模型的力促,先通过torch的nn.Module定义模型,然后定义Pearson损失。
1.1 模型定义
这里使用torch的Linear模块直接模拟weights和bias。
input_dim为输入维度,需要与输入X的维度一致,输出为1。
代码示例如下所示。
# 创建简单的线性模型 class LinearModel(nn.Module): def __init__(self, input_dim): super(LinearModel, self).__init__() self.linear = nn.Linear(input_dim, 1) def forward(self, x): return self.linear(x).squeeze()1.2 损失定义
参考pytorch损失函数的定义流程,定义Pearson损失函数。
Pearson相关系数有两种常用的损失函数形式:1 - |r| 或 1 - r^2。
基于绝对值的损失:1 - |r|,取值范围 [0, 1]
基于平方的损失:1 - r^2,取值范围 [0, 1],对弱相关更敏感。
这里为简化分析采用第一种
# 使用PyTorch实现Pearson损失函数的版本 class PearsonLossTorch(nn.Module): def __init__(self): super(PearsonLossTorch, self).__init__() def forward(self, y_pred, y_true): # 计算Pearson相关系数 v_pred = y_pred - torch.mean(y_pred) v_true = y_true - torch.mean(y_true) numerator = torch.sum(v_pred * v_true) denominator = torch.sqrt(torch.sum(v_pred ** 2)) * torch.sqrt(torch.sum(v_true ** 2)) # 防止除以零 if denominator == 0: denominator = 1e-10 pearson_r = numerator / denominator # 返回1 - r作为损失 return 1 - pearson_r1.3 梯度定义
Pearson损失相对weight和bias的梯度定义如下所示
具体过程参考
https://blog.csdn.net/liliang199/article/details/155751622
由于torch版本实现可以自动根据loss函数计算梯度,所以这里不需要单独计算梯度。
具体过程参考模型训练过程,示例如下
loss.backward()
2 模型训练
这里分别准备训练数据和使用pytorch训练模型。
2.1 训练数据
对于输入X,目标值y的生成核心逻辑如下
X是一个三维向量,true_weights是权重,true_bias是固定偏移,为保证随机性加随机偏移。
y = np.dot(X, true_weights) + true_bias + np.random.randn(n_samples) * noise
训练数据生成代码如下所示,具体过程参考
https://blog.csdn.net/liliang199/article/details/155751622
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_regression from sklearn.preprocessing import StandardScaler # 创建模拟数据 def generate_synthetic_data(n_samples=200, noise=10.0, seed=42): """生成合成数据""" np.random.seed(seed) # 生成特征 dim_size = 3 X = np.random.randn(n_samples, dim_size) # 生成真实权重 true_weights = np.array([2.5, -1.5, 0.8, 1.8, 3.2, 6.9, 7.8][:dim_size]) true_bias = 1.0 # 生成目标值 y = np.dot(X, true_weights) + true_bias + np.random.randn(n_samples) * noise # 标准化特征(有助于训练) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 标准化目标值 y_mean, y_std = y.mean(), y.std() y_scaled = (y - y_mean) / y_std return X_scaled, y_scaled, y_mean, y_std2.2 模型训练
参考pytorch训练模型流程,在每次迭代过程中:
1)先计算预测值predictions
2)然后根据预测值predictions和实际值y_tensor,计算Pearson损失loss
3)再然后通过loss.backward() optimizer.step()计算梯度,更新模型
torch版Pearson损失训练模型的伪码如下所示。
X_tensor = torch.FloatTensor(X_np)
y_tensor = torch.FloatTensor(y_np)
model = LinearModel(X_np.shape[1])
criterion = PearsonLossTorch()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练
losses = []
for epoch in range(1000):
optimizer.zero_grad()
predictions = model(X_tensor)
loss = criterion(predictions, y_tensor)
loss.backward()
optimizer.step()
losses.append(loss.item())
以下是torch版本的Pearson损失训练模型的代码。
def pytorch_version(): """ 使用PyTorch实现Pearson损失函数的版本 需要安装: pip install torch """ try: import torch import torch.nn as nn import torch.optim as optim class PearsonLossTorch(nn.Module): def __init__(self): super(PearsonLossTorch, self).__init__() def forward(self, y_pred, y_true): # 计算Pearson相关系数 v_pred = y_pred - torch.mean(y_pred) v_true = y_true - torch.mean(y_true) numerator = torch.sum(v_pred * v_true) denominator = torch.sqrt(torch.sum(v_pred ** 2)) * torch.sqrt(torch.sum(v_true ** 2)) # 防止除以零 if denominator == 0: denominator = 1e-10 pearson_r = numerator / denominator # 返回1 - r作为损失 return 1 - pearson_r # 创建简单的线性模型 class LinearModel(nn.Module): def __init__(self, input_dim): super(LinearModel, self).__init__() self.linear = nn.Linear(input_dim, 1) def forward(self, x): return self.linear(x).squeeze() # 示例用法 print("\nPyTorch版本:") X_np, y_np, _, _ = generate_synthetic_data() X_tensor = torch.FloatTensor(X_np) y_tensor = torch.FloatTensor(y_np) model = LinearModel(X_np.shape[1]) criterion = PearsonLossTorch() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练 losses = [] for epoch in range(1000): optimizer.zero_grad() predictions = model(X_tensor) loss = criterion(predictions, y_tensor) loss.backward() optimizer.step() losses.append(loss.item()) if epoch % 200 == 0: print(f"Epoch {epoch}: Loss = {loss.item():.4f}") print("PyTorch训练完成!") except ImportError: print("PyTorch未安装,跳过PyTorch示例。") print("安装命令: pip install torch") pytorch_version()训练输出如下,可见随着训练进行,模型越来越收敛,说明Pearson loss生效了。
PyTorch版本:
Epoch 0: Loss = 0.8733
Epoch 200: Loss = 0.7504
Epoch 400: Loss = 0.7321
Epoch 600: Loss = 0.7300
Epoch 800: Loss = 0.7298
PyTorch训练完成!
reference
---
如何使用python模拟Pearson loss训练模型
https://blog.csdn.net/liliang199/article/details/155751622