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_r
1.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_std
2.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训练模型