本次的赛题背景与第二期相比有了很大变化。第二期是三特征输入的时序预测,这次是多特征输入的回归拟合预测。数据集的量减少了,但是本质是一样的,主要是回归拟合。本次的比赛更偏向于对特征的分析和提取。对特征做好分类和排列是至关重要的。
对于此次的baseline,我在未发布Task01之前就在本地做了部署。在本地部署的时候也是花了很大功夫,在基本的训练模型生成之后,接着去预测测试集这一部分对代码的调试是一个难点。下面是我自己添加的测试集预测的输出代码,比Datawhale给的要简略一点,但是功能是相同的。
# Load data
train_data = pd.read_csv('train_data.csv')
# 缩小训练集,用于debug
# train_data = train_data.iloc[:32, :]
test_data = pd.read_csv('sample_submission.csv')
# 删除 concentration_unit 特征
train_data.drop('concentration_unit', axis=1)
test_data.drop('concentration_unit', axis=1)
# 自加行
columns = ['siRNA_antisense_seq', 'modified_siRNA_antisense_seq_list']
train_data.dropna(subset=columns + ['mRNA_remaining_pct'], inplace=True)
test_data.dropna(subset=columns, inplace=True)
# 删除训练数据集和测试数据集中特定列(siRNA_antisense_seq、modified_siRNA_antisense_seq_list)包含空值的行,以及训练数据集中
# mRNA_remaining_pct列包含空值的行。
# 自加行
train_data, val_data = train_test_split(train_data, test_size=0.1, random_state=42)
# Create vocabulary
tokenizer = GenomicTokenizer(ngram=3, stride=3)
all_tokens = []
for col in columns:
for seq in train_data[col]:
if ' ' in seq: # Modified sequence
all_tokens.extend(seq.split())
else:
all_tokens.extend(tokenizer.tokenize(seq))
vocab = GenomicVocab.create(all_tokens, max_vocab=10000, min_freq=1)
# Find max sequence length
max_len = max(max(len(seq.split()) if ' ' in seq else len(tokenizer.tokenize(seq))
for seq in train_data[col]) for col in columns)
# Create datasets
train_dataset = SiRNADataset(train_data, columns, vocab, tokenizer, max_len)
val_dataset = SiRNADataset(val_data, columns, vocab, tokenizer, max_len)
# Create data loaders
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32)
# Initialize model
model = SiRNAModel(len(vocab.itos))
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters())
train_model(model, train_loader, val_loader, criterion, optimizer, 100, device)
# # 假设测试数据集最后一列为空,我们需要预测并填入预测值
# X_test = test_data # 假设测试集最后一列为空,不包含目标变量
# 保存训练好的模型
torch.save(model, 'D:/pythonProject5/model3.pth')
# 在测试集上进行预测
test_dataset = SiRNADataset(test_data, columns, vocab, tokenizer, max_len)
test_loader = DataLoader(test_dataset, batch_size=32)
# 加载模型
model = torch.load('D:/pythonProject5/model3.pth', map_location=device)
print(model) # 打印模型结构
# 确保模型在评估模式下
model.eval()
predictions = []
# 使用 no_grad 来确保不计算梯度
with torch.no_grad():
for inputs, targets in test_loader:
# 确保输入移动到设备上
inputs = [x.to(device) for x in inputs]
# print("inputs:", inputs)
# 进行预测
outputs = model(inputs)
# 打印输出以进行调试
# print("Outputs:", outputs)
# 将预测结果移动到 CPU 并转换为 numpy 数组
predictions.extend(outputs.cpu().numpy())
# 确认 predictions 不为空
print("checking predictions:")
print(predictions, len(predictions), len(test_data))
# 检查预测结果的长度是否与测试数据匹配
if len(predictions) == len(test_data):
test_data['mRNA_remaining_pct'] = predictions
else:
print("预警:预测与测试数据的行数不匹配。")
# 将完整的测试集(包括预测结果)保存为CSV文件
test_data.to_csv('predicted_test_data2100.csv', index=False)
# 输出预测完成的信息
print("预测完成,并将结果保存为 predicted_test_data2100.csv 文件。")
从加载数据开始,开始添加代码。train model往下全是自己添加的。这个程序在本地跑50代的时间为两个多小时,不建议大家在本地跑。和大家在云端的服务器跑的结果差不多,0.5-0.6的样子。调参之后分数还是上不去。后续选择别的方法和程序再去预测,比如说SVR,Lightgbm,catboost,xgboost等等。
我利用SVR预测后的结果要好于运行200epochs的baseline,为0.69左右,以下是我用的SVR的一种代码,和大家一起交流学习。
import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# 读取数据
train_data = pd.read_csv('train_data.csv')
test_data = pd.read_csv('sample_submission.csv')
# 确保训练集和测试集中的列名和顺序一致
print("训练集列名:", train_data.columns)
print("测试集列名:", test_data.columns)
# 分离训练集的特征和目标变量
features_to_drop = ['mRNA_remaining_pct', 'concentration_unit']
X_train = train_data.drop(features_to_drop, axis=1)
y_train = train_data['mRNA_remaining_pct']
X_test = test_data.drop(features_to_drop, axis=1)
# 确认修改后的数据集
print("训练集特征:", X_train.columns)
print("测试集特征:", X_test.columns)
# 定义数值型和类别型特征列
numerical_features = X_train.select_dtypes(include=[np.number]).columns
categorical_features = X_train.select_dtypes(exclude=[np.number]).columns
# 数据预处理管道
numeric_transformer = Pipeline(steps=[
('scaler', StandardScaler()),
('imputer', SimpleImputer(strategy='mean')) # 添加缺失值填充
])
categorical_transformer = Pipeline(steps=[
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numerical_features),
('cat', categorical_transformer, categorical_features)
])
# 数据预处理和转换
X_train_processed = preprocessor.fit_transform(X_train)
X_test_processed = preprocessor.transform(X_test)
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
# 定义SVR模型
svr = SVR()
# # 定义SVR--linear模型参数
# svr = SVR(kernel='linear', C=1.0, epsilon=0.01)
# # 定义SVR模型参数--poly
# svr = SVR(kernel='poly', C=1.0, epsilon=0.1, degree=2, gamma='scale', coef0=1)
# # 定义SVR模型参数--rbf
# # 定义SVR模型参数,使用RBF核
# svr = SVR(kernel='rbf', C=1.0, epsilon=0.1, gamma='scale')
# # 定义参数网格,仅使用多项式核
param_grid = {
'C': [0.1,1,10], # 尝试不同的C值
'epsilon': [0.01], # 尝试不同的epsilon值
'kernel': ['poly'], # 只使用多项式核
'degree': [2,3,4], # 多项式的度数
'gamma': ['auto','scale'], # 定义gamma的值
'coef0': [0,1,10], # 独立项
}
# # 定义参数网格
# param_grid = {
# 'C': [0.1, 1, 10, 100], # 尝试不同的C值
# 'epsilon': [0.01, 0.1, 0.5, 1], # 尝试不同的epsilon值
# 'kernel': ['linear', 'rbf', 'poly'] # 尝试不同的核函数
# # 'gamma': ['scale', 'auto', 0.1, 1, 10], # 仅用于非线性核
# # 'degree': [2, 3, 4], # 仅用于多项式核
# # 'coef0': [0, 1, 10], # 仅用于非线性核
# }
# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=svr, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error')
# 训练模型并进行参数调优
grid_search.fit(X_train_processed, y_train)
# 打印最佳参数
print("最佳参数:", grid_search.best_params_)
# 使用最佳参数的模型进行预测
best_svr = grid_search.best_estimator_
y_pred = best_svr.predict(X_test_processed)
# 保存预测结果
test_data['mRNA_remaining_pct'] = y_pred
test_data.to_csv('predicted_test_data_poly_kernel.csv', index=False)
print("使用最佳参数的预测结果已保存到 predicted_test_data_poly_kernel.csv 文件中。")
这段代码是可以运行通的,大家可以试一试。虽然分数提高不多,但是可以多一中预测方式。
通过直播学习,后续会针对其特征进一步进行学习和调整,继续提分。