使用神经网络与5折交叉验证进行基因组预测:完整指南
在本篇博客中,我们将带您了解如何使用神经网络模型与5折交叉验证进行基因组预测。此方法通过基因组数据和环境因子预测表型(phenotype)。该实现使用了 Keras 库和 TensorFlow 后端,并且通过交叉验证评估模型表现,计算性能指标如相关性和均方根误差(RMSE)。此外,我们还将展示如何可视化训练过程和预测结果。
1. 引言
基因组预测旨在基于个体的基因数据预测其表型值。在本教程中,我们将使用 Keras 构建神经网络,通过 5折交叉验证 训练并评估该模型。数据包括基因型(SNP)、环境因子和表型数据。训练结束后,我们将计算模型的性能指标,并展示训练历史和预测结果的可视化图表。
2. 环境准备
在开始之前,请确保已安装以下软件和库:
- R:版本 4.0 或更高
- RStudio(推荐使用)
- Keras 和 TensorFlow:用于构建和训练神经网络
- 其他必备库 :
data.table
、ggplot2
、dplyr
、caret
可以通过以下命令安装所需的 R 包:
r
install.packages(c("keras", "tensorflow", "data.table", "ggplot2", "dplyr", "caret"))
安装 Keras 和 TensorFlow 后,运行以下命令进行配置:
r
library(keras)
install_keras() # 安装 Keras 和 TensorFlow
3. 数据加载与预处理
我们将从在线资源加载基因型(SNP)、环境协变量和表型数据。数据源已公开,脚本将直接从给定的 URL 下载数据。
加载数据
r
# 加载基因型(SNP)数据
myGD <- read.table(file = "http://zzlab.net/GAPIT/data/mdp_numeric.txt", head = TRUE)
# 加载环境协变量数据
myCV <- read.table(file = "http://zzlab.net/GAPIT/data/mdp_env.txt", head = TRUE)
# 加载表型数据
myY <- read.csv(file = "http://zzlab.net/StaGen/2025/Data/my_y.csv", head = TRUE)
数据预处理
- 基因型数据:去除 ID 列,并对基因型数据进行主成分分析(PCA),以捕捉种群结构。
- 协变量数据:去除 ID 列。
- 表型数据:对表型数据进行标准化。
r
# 准备基因型数据
genotypes <- myGD
genotypes <- genotypes[, -1] # 移除 ID 列
# 对基因型数据进行 PCA 处理
pcs <- prcomp(myGD[,-1]) # 排除 ID 列
pca <- as.data.frame(pcs$x[, 1:3]) # 取前3个主成分
# 准备环境协变量数据
covariates <- myCV
covariates <- covariates[, -1] # 移除 ID 列
# 将 PCA 组件与环境协变量数据合并
covariates <- cbind(pca, covariates)
# 将基因型数据和协变量数据合并为输入矩阵 X
X <- as.matrix(cbind(genotypes, covariates))
# 对输入数据进行标准化
X <- scale(X)
X[is.na(X)] <- 0 # 将缺失值替换为 0
# 加载并标准化表型数据
y <- myY$Sim
y <- scale(y)
4. 设置5折交叉验证
我们使用 5折交叉验证 来训练和评估模型。数据集被划分为5个子集,每个子集轮流作为验证集,其余4个子集作为训练集。
r
# 设置随机种子,保证结果可复现
set.seed(123)
# 创建5折交叉验证的折叠
folds <- createFolds(y, k = 5, returnTrain = TRUE)
# 初始化存储预测结果和性能指标的列表
predictions <- list()
correlations <- numeric(5)
rmse_values <- numeric(5)
5. 构建与训练神经网络模型
我们使用 Keras 库构建神经网络模型。模型包括:
- 输入层 :根据
X
的特征数量设置。 - 隐藏层:使用 ReLU 激活函数,并添加 Dropout 层进行正则化。
- 输出层:一个单节点输出预测值。
r
for (fold_idx in seq_along(folds)) {
cat("Training fold", fold_idx, "of 5\n")
# 分割训练集和验证集
train_idx <- folds[[fold_idx]]
val_idx <- setdiff(1:nrow(X), train_idx)
X_train <- X[train_idx, ]
y_train <- y[train_idx]
X_val <- X[val_idx, ]
y_val <- y[val_idx]
# 构建神经网络模型
model <- keras_model_sequential() %>%
layer_dense(units = 48, activation = "relu", input_shape = ncol(X),
kernel_regularizer = regularizer_l2(0.08)) %>%
layer_batch_normalization() %>%
layer_dropout(rate = 0.25) %>%
layer_dense(units = 24, activation = "relu",
kernel_regularizer = regularizer_l2(0.08)) %>%
layer_batch_normalization() %>%
layer_dropout(rate = 0.25) %>%
layer_dense(units = 1)
# 编译模型
model %>% compile(
optimizer = optimizer_adam(learning_rate = 0.0003),
loss = "mean_squared_error"
)
# 设置回调函数(学习率调整与提前停止)
lr_scheduler <- callback_reduce_lr_on_plateau(
monitor = "val_loss",
factor = 0.3,
patience = 5,
min_lr = 1e-6
)
early_stopping <- callback_early_stopping(
monitor = "val_loss",
patience = 5,
restore_best_weights = TRUE
)
# 训练模型
history <- model %>% fit(
X_train, y_train,
epochs = 500,
batch_size = 154,
validation_data = list(X_val, y_val),
callbacks = list(early_stopping, lr_scheduler),
verbose = 1
)
# 对验证集进行预测
y_pred <- model %>% predict(X_val, batch_size = 154)
# 存储预测结果
predictions[[fold_idx]] <- data.frame(
Fold = fold_idx,
True = y_val,
Predicted = as.vector(y_pred)
)
# 计算性能指标(相关性与RMSE)
correlations[fold_idx] <- cor(y_val, y_pred)^2
rmse_values[fold_idx] <- sqrt(mean((y_val - y_pred)^2))
# 可视化训练历史
library(ggplot2)
df_history <- as.data.frame(history)
p <- ggplot(df_history, aes(x = epoch, y = value, color = data)) +
geom_line(size = 1.2) +
facet_wrap(~metric, scales = "free_y") +
theme_minimal(base_size = 14) +
labs(
title = paste("Training History - Fold", fold_idx),
x = "Epoch",
y = "Metric"
)
ggsave(
filename = paste0("training_history_fold_", fold_idx, ".png"),
plot = p,
width = 6,
height = 5,
dpi = 150
)
}
6. 评估模型表现
完成所有 5 折训练后,结合所有折叠的预测结果,并计算模型的平均性能指标(相关性与 RMSE)。
r
# 合并所有折叠的预测结果
predictions_df <- do.call(rbind, predictions)
# 保存预测结果到 CSV 文件
write.csv(predictions_df, "genomic_predictions_epi.csv", row.names = FALSE)
# 打印预测表现摘要
cat("Prediction performance across folds:\n")
cat("Mean correlation:", mean(correlations), "\n")
cat("Correlation SD:", sd(correlations), "\n")
cat("Mean RMSE:", mean(rmse_values), "\n")
cat("RMSE SD:", sd(rmse_values), "\n")
7. 相关性可视化
我们为每个折叠生成一个散点图,显示预测与真实表型值之间的关系,并添加回归线进行拟合。
r
# 为每个折叠生成相关性散点图
corr <- numeric(5)
for (fold_idx in 1:5) {
fold_data <- predictions_df[predictions_df$Fold == fold_idx, ]
y_true <- fold_data$True
y_pred <- fold_data$Predicted
计算相关性
r
corr[fold_idx] <- cor(y_true, y_pred)^2
p <- ggplot(fold_data, aes(x = True, y = Predicted)) +
geom_point(color = "blue", alpha = 0.6) +
geom_smooth(method = "lm", color = "red", se = FALSE) +
labs(
title = paste("Fold", fold_idx, ": Predicted vs. True Phenotypes"),
x = "True Phenotype",
y = "Predicted Phenotype"
) +
annotate(
"text",
x = min(y_true) + 0.1 * (max(y_true) - min(y_true)),
y = max(y_pred) - 0.1 * (max(y_pred) - min(y_pred)),
label = sprintf("Correlation: %.3f", corr[fold_idx]),
hjust = 0,
vjust = 1
) +
theme_minimal()
ggsave(
filename = paste0("correlation_plot_fold_epi_", fold_idx, ".png"),
plot = p,
width = 6,
height = 5,
dpi = 150
)
}
cat("Correlation across folds:\n")
cat("Mean Cor:", mean(corr), "\n")
8. 结论
- 最终模型:训练好的模型可以保存,并用于预测新的基因组数据。
- 性能评估:通过5折交叉验证,我们计算了模型的平均相关性和 RMSE 值,帮助我们了解模型的泛化能力。