本次竞赛的目标是根据降雨数据集,预测是否降雨。
train.csv- 培训数据集;rainfall是二进制目标 test.csv- 测试数据集;您的目标是预测rainfall每行 sample_submission.csv- 以正确格式的示例提交文件。
id:记录的唯一标识符。 day:表示日期或天数,通常是数据的时间索引。 pressure:气压,通常是大气中的压力,单位一般为hPa(百帕)。 maxtemp:最高温度,单位通常为摄氏度(°C)。 temparature:温度,表示当天的平均气温,单位为摄氏度(°C)。 mintemp:最低温度,单位为摄氏度(°C)。 dewpoint:露点温度,表示空气中水蒸气达到饱和状态时的温度。 humidity:湿度。 cloud:云量,表示天空中被云覆盖的比例。 sunshine:阳光时长,表示阳光照射的时间长度,单位为小时。 winddirection:风向,表示风的方向。 windspeed:风速,表示风的速度,单位通常为米每秒(m/s)。
是一种常见的缺失值处理方法,它通过已知数据点来估算未知数据点(即缺失值)。在时间序列或其他序列数据中,插值法尤其有效,因为我们可以假设缺失的数据点在某些条件下遵循已有数据的模式或趋势。插值方法可以用于数值型数据的填充,适用于连续的数据。
线性插值是最常见和简单的插值方法。它假设数据之间的变化是线性的,即缺失值可以通过前后相邻数据点的线性关系来估算。在这种方法中,缺失值会通过两个相邻数据点之间的线性方程来估算。
test_df['winddirection'] = test_df['winddirection'].interpolate(method='linear')
如果数据不是简单的线性关系,可能会使用多项式插值,它基于多项式拟合数据点。对于包含多个缺失值的数据,使用高阶多项式(如二次或三次插值)可能会更准确,但这也容易导致过拟合问题。 常见的多项式插值方法包括拉格朗日插值法和牛顿插值法。
对于数据变化较为复杂的情况,可以使用多项式插值。Pandas 通过 method='polynomial'
参数实现多项式插值,需要指定一个阶数(order
),即多项式的次数。
test_df['winddirection'] = test_df['winddirection'].interpolate(method='polynomial', order=3)
样条插值(例如立方样条插值)是另一种平滑插值方法,它通过分段多项式来拟合数据,并且在数据的每个分段之间保证连续性和可导性。
相比于简单的线性插值,样条插值可以提供更平滑的曲线,适合于数据变化比较复杂的情况。
样条插值(例如立方样条插值)适合于平滑地估算缺失值,可以通过 method='spline'
参数来实现。通常,样条插值用在更复杂的连续数据上。
test_df['winddirection'] = test_df['winddirection'].interpolate(method='spline', order=3)
虽然不是严格意义上的插值法,但也常用来填充缺失值。前向填充(ffill)将缺失值用前一个已知值替代,后向填充(bfill)则用下一个已知值填充,适用于当缺失值的内容与前一个数据点相似时。method='ffill’表示前向填充,值为bfill表示后向填充。
test_df['winddirection'] = test_df['winddirection'].fillna(method='ffill')
有时你可能希望基于某些特定规则自定义插值方法。Pandas 插值提供了 limit 参数,可以限制填充的最大数量。也可以通过 limit_direction 参数指定填充的方向(“forward”, “backward” 或 “both”)。
test_df['winddirection'] = test_df['winddirection'].interpolate(method='linear', limit=5, limit_direction='both')
limit=5:表示一次最多填充 5 个连续的缺失值。 limit_direction=‘both’:表示可以同时向前和向后填充缺失值。
如果你的数据是时间序列数据,Pandas 也允许根据时间差异进行插值。这种方法特别适用于基于时间间隔的数据。
test_df['winddirection'] = test_df['winddirection'].interpolate(method='time')
import numpy as np
import pandas as pd
train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
sub_df = pd.read_csv('sample_submission.csv')
可以看到test_df中有一个缺失值,接下来填充这个缺失值。
train_df1 = train_df.dropna()
test_df['winddirection'] = test_df['winddirection'].interpolate()
interpolate()
是 Pandas 中的一个方法,用于处理缺失值。interpolate() 方法会基于已有数据推测并填补缺失值。插值的过程根据数据的类型和上下文会有不同的方式,但通常是根据数据的趋势、规律等来推断缺失的数值。
train= train_df1.drop(columns=['id','rainfall'])
label = train_df1['rainfall']
test = test_df.drop(columns=['id'])
划分好目标变量。
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
from sklearn.linear_model import LogisticRegression
import optuna
import numpy as np
from sklearn.preprocessing import StandardScaler
x = train
y = label
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# ================== 逻辑回归超参数优化 ==================
def objective_lr(trial):
params = {
'C': trial.suggest_float('C', 1e-5, 100, log=True), # 正则化强度参数
'solver': trial.suggest_categorical('solver', ['liblinear', 'saga', 'lbfgs']), # 优化算法
'max_iter': trial.suggest_int('max_iter', 200, 500), # 增加最大迭代次数
'random_state': 42
}
# 使用逻辑回归模型
model = LogisticRegression(**params)
model.fit(X_train_scaled, y_train)
pred = model.predict_proba(X_test_scaled)[:, 1] # 预测类别概率
return roc_auc_score(y_test, pred) # 返回AUC作为优化目标
study_lr = optuna.create_study(direction='maximize')
study_lr.optimize(objective_lr, n_trials=50)
best_lr = study_lr.best_params
best_lr['random_state'] = 42
print("逻辑回归最佳参数:", best_lr)
# ================== 训练最佳模型并评估 ==================
lr_model = LogisticRegression(**best_lr)
lr_model.fit(X_train_scaled, y_train)
lr_pred = lr_model.predict_proba(X_test_scaled)[:, 1]
auc = roc_auc_score(y_test, lr_pred)
print(f"逻辑回归模型的AUC: {auc:.5f}")
逻辑回归最佳参数: {‘C’: 47.981164316576546, ‘solver’: ‘saga’, ‘max_iter’: 274, ‘random_state’: 42} 逻辑回归模型的AUC: 0.87271
使用逻辑回归进行二分类建模,并使用optuna进行参数优化,最终使用auc作为二分类结果的评估指标。
接下来使用可视化,进一步评估模型。
是一种评估二分类模型在不平衡数据集上的性能的有效工具。特别是当数据集中某一类别的样本远远多于另一类别时,传统的评估指标(如准确率)往往不能反映模型的真实性能,而 PR 曲线能够提供更为细致的评价。
PR 曲线是在 召回率(Recall)为横轴、精确率(Precision)为纵轴的二维坐标系中绘制的。通过不同的阈值调整,PR 曲线展示了精确率和召回率之间的平衡。
精确率和召回率都非常高,意味着大多数正类被正确预测,并且预测为正类的样本大多数是真正的正类。理想的 PR 曲线将接近图的右上角,即召回率和精确率都接近1。
精确率和召回率都很低,表示模型在识别正类时存在很大问题,可能是无法有效区分正类与负类,或者大量的正类被错误预测为负类。差的 PR 曲线通常会远离右上角,接近于图的左下方。
PR 曲线下的面积(AUC-PR)是评价模型的一个重要指标。面积越大,模型的性能越好。具体来说:
AUC-PR(Precision-Recall AUC):是指 PR 曲线下的面积。AUC-PR 的取值范围是 0 到 1,越接近 1,模型的性能越好,说明模型在各个阈值下都有较高的精确率和召回率。 AUC-PR = 1:意味着模型在所有阈值下都能达到最好的精确率和召回率。 AUC-PR 接近 0:表示模型的精确率和召回率都很低,表现很差。
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score
import matplotlib.pyplot as plt
# 计算精准率、召回率和阈值
precision, recall, thresholds = precision_recall_curve(y_test, lr_pred)
average_precision = average_precision_score(y_test, lr_pred)
# 绘制 Precision-Recall 曲线
plt.figure(figsize=(8, 6))
plt.plot(recall, precision, color='b', label=f'PR curve (AP = {average_precision:.2f})')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend(loc='lower left')
plt.show()
from sklearn.metrics import roc_curve, auc
# 计算假正率、真正率和阈值
fpr, tpr, thresholds = roc_curve(y_test, lr_pred)
roc_auc = auc(fpr, tpr)
# 绘制 ROC 曲线
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='b', label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='gray', linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc='lower right')
plt.show()
在树模型(如决策树、随机森林、XGBoost 等)中,特征重要性通常是基于特征在树的分裂节点上的贡献来计算的。具体而言,树模型通过特征划分数据并基于节点的纯度变化来决定每个特征的重要性。
然而,逻辑回归作为一个线性模型,它并没有树结构。但仍然可以通过模型的 系数 来评估特征的重要性。具体来说:
逻辑回归模型通过线性决策边界进行分类,其决策规则为:
其中,w1,w2是指各个特征x1,x2…的权重系数,b 是偏置项。
每个系数的大小反映了该特征对模型决策的影响, 具体来说:
因此,逻辑回归模型的 特征重要性 是基于每个特征系数的绝对值来评估的。虽然逻辑回归是一个线性模型,但我们仍然可以通过这种方法判断哪些特征对模型输出的影响较大。
import numpy as np
import matplotlib.pyplot as plt
# 获取逻辑回归的系数
feature_importance = np.abs(lr_model.coef_[0])
# 绘制特征重要性
plt.figure(figsize=(8, 6))
plt.barh(range(len(feature_importance)), feature_importance, align='center')
plt.yticks(range(len(feature_importance)), X_train.columns)
plt.xlabel('Feature Importance')
plt.title('Feature Importance (Logistic Regression)')
plt.show()
from sklearn.metrics import confusion_matrix
import seaborn as sns
# 计算混淆矩阵
cm = confusion_matrix(y_test, lr_model.predict(X_test_scaled))
# 可视化混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Class 0', 'Class 1'], yticklabels=['Class 0', 'Class 1'])
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Confusion Matrix')
plt.show()
给定混淆矩阵如下:
准确率是指模型预测正确的样本占总样本数的比例:
精确率是指在所有预测为正类(1)的样本中,实际为正类(1)的比例:
召回率是指在所有实际为正类(1)的样本中,模型正确预测为正类(1)的比例:
F1分数是精确率和召回率的调和平均值,它综合考虑了模型的精确性和召回能力:
总体来看,模型在捕捉正类样本方面表现非常出色,尤其是召回率较高。假正类(FP)相对较少,精确率也处于一个较高的水平。F1分数的表现进一步证明了该模型的平衡性。