机器学习实战04:基于支持向量机(SVM)模型的户外烧烤天气预测

发布于:2025-05-18 ⋅ 阅读:(24) ⋅ 点赞:(0)

目录

一、项目背景与目标

二、数据预处理与探索性分析

1. 数据读取与筛选

2. 特征工程

3. 数据可视化

三、机器学习模型构建

1. 数据平衡处理

2. 特征归一化

3. 模型训练与评估

四、关键分析与结果

1. 数据不平衡处理效果

2. 特征相关性分析

3. 模型性能

五、全代码

六、数据集说明(获取callme)

1. weather_dataset.csv(部分字段)

2. weather_labels.csv

七、总结与展望

一、项目背景与目标

在日常生活中,天气是影响户外活动计划的重要因素。本项目聚焦于通过历史天气数据预测特定天气条件下是否适合进行户外烧烤。以布达佩斯的天气数据为例,利用机器学习模型分析温度、湿度、气压等气象指标与烧烤天气(BUDAPEST_BBQ_weather)之间的关联,旨在构建一个准确的预测模型,为户外活动规划提供科学依据。

二、数据预处理与探索性分析

1. 数据读取与筛选

首先读取包含多城市天气数据的weather_dataset.csv和标签数据weather_labels.csv,提取布达佩斯相关的特征(如温度、湿度、气压等),并将日期格式转换为datetime类型以便后续分析:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']  # 支持中文显示

# 读取数据并筛选布达佩斯相关特征
df = pd.read_csv('weather_dataset.csv')
labels = pd.read_csv('weather_labels.csv')
df_budapest = pd.concat([df.iloc[:, :2], df.iloc[:, 11:19]], axis=1)  # 提取日期、月份和布达佩斯气象指标
df_budapest['DATE'] = pd.to_datetime(df_budapest['DATE'], format='%Y%m%d')

2. 特征工程

  • 按月统计均值:定义函数计算各月气象指标的平均值,分析季节性规律:
    def mean_for_mth(feature):
        mean = []
        for x in range(12):
            mean.append(float("{:.2f}".format(df_budapest[df_budapest['MONTH'] == (x+1)][feature].mean())))
        return mean
    
  • 处理标签数据:从labels中提取布达佩斯的烧烤天气标签(BUDAPEST_BBQ_weather),并转换为二进制数值(1 = 适合,0 = 不适合)。

3. 数据可视化

  • 温度变化趋势:绘制 2000 年布达佩斯的温度变化曲线,观察季节性波动:
    plt.figure(figsize=(12, 6))
    plt.plot(df_budapest['DATE'][:365], df_budapest['BUDAPEST_temp_mean'][:365])
    plt.title('2000年的温度变化图')
    plt.xlabel('DATE')
    plt.ylabel('DEGREE')
    plt.show()
    
  • 各月均值对比:通过柱状图展示不同月份的平均温度和湿度,揭示夏季温度高、冬季湿度大的规律:
    months = ['Jan', 'Febr', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    mean_temp = mean_for_mth('BUDAPEST_temp_mean')
    plt.figure(figsize=(12, 6))
    bar = plt.bar(x=months, height=mean_temp, width=0.8, color=['thistle', 'mediumaquamarine', 'orange'])
    plt.xticks(rotation=45)
    plt.xlabel('MONTHS')
    plt.ylabel('DEGREES')
    plt.title('布达佩斯(匈牙利首都)年平均温度')
    plt.bar_label(bar)
    plt.show()
    
  • 特征分布分析:利用直方图和小提琴图展示气压、湿度等指标的分布及与烧烤天气的关联:
    fig, axs = plt.subplots(2, 2, figsize=(12, 8))
    fig.suptitle('各指标的分布次数图')
    sns.histplot(data=df_budapest, x='BUDAPEST_pressure', ax=axs[0, 0], color='red', kde=True)
    sns.histplot(data=df_budapest, x='BUDAPEST_humidity', ax=axs[0, 1], color='orange', kde=True)
    sns.histplot(data=df_budapest, x='BUDAPEST_temp_mean', ax=axs[1, 0], kde=True)
    sns.histplot(data=df_budapest, x='BUDAPEST_global_radiation', ax=axs[1, 1], color='green', kde=True)
    plt.show()
    

三、机器学习模型构建

1. 数据平衡处理

原始标签数据存在严重不平衡(适合烧烤的天数占比低),采用随机过采样(RandomOverSampler)平衡正负样本:

from imblearn.over_sampling import RandomOverSampler

labels_budapest = labels['BUDAPEST_BBQ_weather'].astype(int)
df_budapest = df_budapest.drop(['DATE', 'MONTH'], axis=1)  # 删除日期和月份列
oversample = RandomOverSampler()
ovrspl_X, ovrspl_y = oversample.fit_resample(df_budapest, labels_budapest)

2. 特征归一化

使用MinMaxScaler对数值型特征进行归一化,确保各特征对模型的贡献权重一致:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
norm_X = scaler.fit_transform(ovrspl_X)
norm_X = pd.DataFrame(norm_X, columns=df_budapest.columns)

3. 模型训练与评估

  • 数据集划分:按 7:3 比例划分训练集与测试集:
    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(norm_X, ovrspl_y, test_size=0.3, random_state=42)
    
  • 支持向量机(SVM)模型:选择线性核函数构建分类模型,并评估性能:
    from sklearn.svm import SVC
    from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
    
    model = SVC(verbose=True, kernel='linear', random_state=0)
    model.fit(X_train, y_train)
    y_predict = model.predict(X_test)
    
    print('Classification report--------------------------------')
    print(classification_report(y_test, y_predict))
    sns.heatmap(confusion_matrix(y_test, y_predict), annot=True, fmt='g').set(title='Confusion Matrix')
    print(f'Model accuracy is: {accuracy_score(y_test, y_predict)*100:.2f}%')
    

四、关键分析与结果

1. 数据不平衡处理效果

过采样后,正负样本比例从原始的约 20%:80% 调整为均衡分布,提升模型对少数类的识别能力:

true_val = len(ovrspl_y[ovrspl_y == 1])
false_val = len(ovrspl_y[ovrspl_y == 0])
print(f'Precent of True values: {true_val/(true_val+false_val)*100:.1f}%')  # 约50%
print(f'Precent of False values: {false_val/(true_val+false_val)*100:.1f}%')  # 约50%

2. 特征相关性分析

通过热力图观察特征间相关性,发现温度(BUDAPEST_temp_mean)与烧烤天气呈正相关,湿度(BUDAPEST_humidity)呈负相关:

plt.figure(figsize=(12, 6))
sns.heatmap(df_budapest.corr(), annot=True, cmap='coolwarm').set(title='Correlation between features')
plt.show()

3. 模型性能

  • 准确率:约 85%,表明模型在平衡数据集上具有较好的泛化能力。
  • 混淆矩阵:显示模型对正负样本的预测误差分布,可进一步通过调整阈值优化。

五、全代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']

# 读取数据并预处理
df = pd.read_csv('weather_dataset.csv')
labels = pd.read_csv('weather_labels.csv')
df_budapest = pd.concat([df.iloc[:, :2], df.iloc[:, 11:19]], axis=1)
df_budapest['DATE'] = pd.to_datetime(df_budapest['DATE'], format='%Y%m%d')

# 计算按月均值的函数
def mean_for_mth(feature):
    mean = []
    for x in range(12):
        mean.append(float("{:.2f}".format(df_budapest[df_budapest['MONTH'] == (x+1)][feature].mean())))
    return mean

# 绘制温度变化图
plt.figure(figsize=(12, 6))
plt.plot(df_budapest['DATE'][:365], df_budapest['BUDAPEST_temp_mean'][:365])
plt.title('2000年的温度变化图')
plt.xlabel('DATE')
plt.ylabel('DEGREE')
plt.show()

# 绘制年平均温度和湿度柱状图
months = ['Jan', 'Febr', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
mean_temp = mean_for_mth('BUDAPEST_temp_mean')
plt.figure(figsize=(12, 6))
bar = plt.bar(x=months, height=mean_temp, width=0.8, color=['thistle', 'mediumaquamarine', 'orange'])
plt.xticks(rotation=45)
plt.xlabel('MONTHS')
plt.ylabel('DEGREES')
plt.title('布达佩斯(匈牙利首都)年平均温度')
plt.bar_label(bar)
plt.show()

mean_humidity = mean_for_mth('BUDAPEST_humidity')
plt.figure(figsize=(12, 6))
bar = plt.bar(x=months, height=mean_humidity, width=0.8, color=['thistle', 'mediumaquamarine', 'orange'])
plt.xticks(rotation=45)
plt.xlabel('MONTHS')
plt.ylabel('HUMIDITY')
plt.title('布达佩斯(匈牙利首都)的年平均湿度')
plt.bar_label(bar)
plt.show()

# 绘制各指标分布直方图
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle('各指标的分布次数图')
sns.histplot(data=df_budapest, x='BUDAPEST_pressure', ax=axs[0, 0], color='red', kde=True)
sns.histplot(data=df_budapest, x='BUDAPEST_humidity', ax=axs[0, 1], color='orange', kde=True)
sns.histplot(data=df_budapest, x='BUDAPEST_temp_mean', ax=axs[1, 0], kde=True)
sns.histplot(data=df_budapest, x='BUDAPEST_global_radiation', ax=axs[1, 1], color='green', kde=True)
plt.show()

# 处理标签数据并平衡样本
labels_budapest = labels['BUDAPEST_BBQ_weather'].astype(int)
df_budapest = df_budapest.drop(['DATE', 'MONTH'], axis=1)
oversample = RandomOverSampler()
ovrspl_X, ovrspl_y = oversample.fit_resample(df_budapest, labels_budapest)

# 特征归一化
scaler = MinMaxScaler()
norm_X = scaler.fit_transform(ovrspl_X)
norm_X = pd.DataFrame(norm_X, columns=df_budapest.columns)

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(norm_X, ovrspl_y, test_size=0.3, random_state=42)

# 训练SVM模型并评估
model = SVC(verbose=True, kernel='linear', random_state=0)
model.fit(X_train, y_train)
y_predict = model.predict(X_test)

print('Classification report--------------------------------')
print(classification_report(y_test, y_predict))
sns.heatmap(confusion_matrix(y_test, y_predict), annot=True, fmt='g').set(title='Confusion Matrix')
print(f'Model accuracy is: {accuracy_score(y_test, y_predict)*100:.2f}%')

六、数据集说明(获取callme)

1. weather_dataset.csv(部分字段)

  • DATE:日期(格式:YYYYMMDD)
  • MONTH:月份(1-12)
  • BUDAPEST_temp_mean:布达佩斯平均温度
  • BUDAPEST_humidity:湿度
  • BUDAPEST_pressure:气压
  • BUDAPEST_global_radiation:全球辐射量

2. weather_labels.csv

  • BUDAPEST_BBQ_weather:是否适合烧烤(True/False,过采样后转换为 1/0)

七、总结与展望

本项目通过数据可视化和机器学习建模,成功构建了布达佩斯烧烤天气预测模型。未来可进一步尝试:

  1. 特征工程优化:引入滞后特征(如前一天温度)或衍生特征(如温度变化率)。
  2. 模型调参:使用网格搜索优化 SVM 超参数(如C、核函数参数)。
  3. 集成学习:尝试随机森林、XGBoost 等模型提升鲁棒性。
  4. 实时预测:结合 API 获取实时天气数据,实现动态预测。

通过此类模型,用户可根据天气预报提前规划户外活动,降低天气因素带来的不便,体现了机器学习在生活场景中的实际应用价值。


网站公告

今日签到

点亮在社区的每一天
去签到