📮 求内推
👩 个人简介:听障人,96年,计算机专业(本科),从事数据分析工作
🛠 语言与工具:包括但不限于Python、SQL、tableaubi、finebi、powerbi。
💻 期望岗位:数据分析、数据运营、报表开发等(hc偏技术方向)
📍 期望城市:杭州
背景说明
本数据集是人工合成的天气数据,旨在模拟用于分类任务的天气信息,并将其分为雨天、晴天、多云和雪天四种类型。
本数据集专为数据科学学习者、学生及初学者设计,用于实践数据预处理、特征工程、异常值检测方法、探索分类算法性能及模型评估。
本数据集为人工生成,不包含真实世界天气数据,其包含的异常值旨在提供实践异常检测和处理的机会。
数据说明
字段 | 说明 |
---|---|
Temperature(数值型) | 温度(单位:摄氏度),范围从极端寒冷到极端炎热 |
Humidity(数值型) | 湿度百分比,包括超过100%的异常值 |
Wind Speed(数值型) | 风速(单位:km/h),范围包括不切实际的高值 |
Precipitation(百分比)(数值型 | 降水量百分比,包括异常值 |
Cloud Cover(类别型) | 云量描述 |
Atmospheric Pressure(数值型) | 大气压力(hPa),覆盖广泛范围 |
UV Index(数值型) | 紫外线指数,表示紫外线辐射的强度 |
Season(类别型) | 数据记录时的季节 |
Visibility(数值型) | 能见度(单位:km),包括非常低或非常高的值 |
Location(类别型) | 数据记录的地点 |
Weather Type(类别型) | 分类目标变量,表示天气类型;雨天(Rainy),晴天(Sunny),多云(Cloudy),雪天(Snowy) |
问题描述
特征相关性分析
特征重要性分析
天气类型预测及模型评估
数据概览与清洗
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.feature_selection import SelectFromModel # 自动选择特征
from sklearn.ensemble import RandomForestClassifier # 随机森林算法
from sklearn.metrics import accuracy_score,recall_score, precision_score, roc_auc_score, classification_report # 评估模型性能
df = pd.read_csv(r'/home/mw/input/07292689/weather_classification_data.csv')
# 修改列名,加上该列名的单位
df.rename(columns=({'Temperature':'Temperature(℃)','Humidity':'Humidity(%)','Wind Speed':'Wind Speed(km/h)','Atmospheric Pressure':'Atmospheric Pressure(hPa)'}),inplace=True)
display(df.head())
print('-'*50)
print('数据集大小:',df.shape)
print('-'*50)
print('数据集存在重复值个数:',df.duplicated().sum())
print('-'*50)
print('数据集存在空值个数:',df.isna().sum())
print('-'*50)
print('数据集信息:',df.info())
print('-'*50)
display('数据集的统计描述:',df.describe(include='all'))
- Temperature: 世界上有记录以来地球表面的最高气温被认为是56.7摄氏度,那么我们设超过60摄氏度的温度为异常。
- Humidity(%): 湿度超过100%的为异常。
- Precipitation (%): 和湿度同理。
- Atmospheric Pressure: 最小值800 aPh通常在非常强烈的低气压系统例如在强烈的风暴中心中才会见到,而最大值1199 aPh在自然环境中几乎不可能出现,实际上气压很少超过1050 aPh。那么我们设超过1050 aPh的气压为异常。
以上四个异常情况需要处理。注:以上异常情况的判断源于AI。
# 剔除异常值以更新数据集
df = df[(df['Temperature(℃)']<=60) & (df['Humidity(%)']<=100) & (df['Precipitation (%)']<=100) & (df['Atmospheric Pressure(hPa)']<=1050)]
df.describe(include='all')
ok,数据应该处理得干净了。接下来看看分类变量的唯一值及其计数。
# print([df[f].unique() for f in ['Cloud Cover','Season','Weather Type']])
for f in ['Cloud Cover','Season','Weather Type','Location']:
display(df[f].value_counts().reset_index(name='count'))
特征相关性分析
corr_df = df.select_dtypes(include=[np.number]).corr().round(2)
# display(corr_df)
fig = px.imshow(corr_df,text_auto=True,aspect='auto') # 显示数据标签,自动调整图像的比例
fig.update_xaxes(side='top') # 将x轴标签放在顶部
fig.update_layout(width=1000,height=500)
fig.show()
- Temperature与Precipitation之间存在显著的负相关性。这意味着温度较高时,降水量通常较少。
- Temperature与UV Index之间存在显著的正相关性。这意味着温度较高时,紫外线强度也较强。
- Humidity与Precipitation之间存在显著的正相关性。这意味着湿度较大时,降水量通常较多。
- Humidity与UV Index之间存在显著的负相关性。这意味着湿度较高时,紫外线指数较低。
- Humidity与Visibility之间存在显著的负相关性。这意味着湿度较高时,能见度通常较低。
- Wind Speed与Precipitation之间存在显著的正相关性。这意味着风速较大时,降水量通常较多。但是需要注意的是,这种相关性并不一定意味着因果关系,因为风速和降水量可能受到其他因素的共同影响。
- Precipitation与UV Index之间存在显著的负相关性。这意味着降水量较大时,紫外线指数较低。
- Precipitation与Visibility之间存在显著的负相关性。这意味着降水量较大时,能见度通常较低。
- Atmospheric Pressure与Temperature之间存在微弱的正相关性。着意味着温度较高时,大气压力略微升高。不过需要注意的是,这种相关性较弱,而且实际情况下这两者的关系可能更加复杂。
- UV Index与Visibility之间存在显著的正相关性。这意味着紫外线指数较高时,能见度通常较好。
天气类型预测及模型评估
前期准备工作
ndf = df.copy()
# 对分类变量进行独热编码处理
cat_list = ['Cloud Cover','Season','Location']
ndf = pd.get_dummies(ndf,columns=cat_list)
# display(ndf.head())
# 准备数据集
x = ndf.drop('Weather Type',axis=1)
y = ndf['Weather Type']
# 划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=42)
使用随机森林算法进行天气类型预测
# 选择模型并训练
rf_model = RandomForestClassifier()
rf_model.fit(x_train,y_train)
# 预测及预测效果
pre = rf_model.predict(x_test)
print(f'Model prediction accuracy:{accuracy_score(y_test,pre)*100:.2f}%')
# 使用训练好的模型输出特征重要性
feature_importances = rf_model.feature_importances_*100
f_importance_df = pd.DataFrame({'Feature':x.columns,'Importance':feature_importances})
f_importance_df = f_importance_df.sort_values(by='Importance',ascending=False,ignore_index=True)
display(f_importance_df)
Model prediction accuracy:94.50%
使用 SelectFromModel 选择特征并进行天气类型预测
# 使用SelecFromModel选择特征
# 创建SelectFromModel创建对象,并使用随机森林分类器作为基础估计器。threshold={'median'|'mean'}表示选择特征重要性高于中位数/平均数的特征。
selector = SelectFromModel(RandomForestClassifier(),threshold='median')
selector.fit(x_train,y_train) # 训练
# 选择特征
# 使用transform方法从训练集中选择特征
x_train_selector = selector.transform(x_train)
x_test_selector = selector.transform(x_test)
# 重新训练模型
# 使用选择的特征重新训练随机森林分类器
rf_model_selected = RandomForestClassifier()
rf_model_selected.fit(x_train_selector,y_train)
# 预测
pre_sel = rf_model_selected.predict(x_test_selector)
# 使用训练好的模型输出特征重要性
feature_importances_sel = rf_model_selected.feature_importances_*100
# selector.get_support()表示返回一个布尔数组,表示哪些特征被留下来,传递给x.columns来筛选那些被标记为True的特征名。
selected_feature_names = x.columns[selector.get_support()]
f_sel_df = pd.DataFrame({'Feature':selected_feature_names,'Importance':feature_importances_sel})
f_sel_df = f_sel_df.sort_values(by='Importance',ascending=False,ignore_index=True)
display(f_sel_df)
# 评估模型
# 预测准确率
print(f'Model prediction accuracy:{accuracy_score(y_test,pre_sel)*100:.2f}%')
# score是模型的一个方法,大多数模型都有该方法。而上面的accuracy_score是sklearn的一个函数,适用于所有模型。
# print(f'score:{rf_model_selected.score(x_test_selector,y_test)}')
# 交叉验证
# N折交叉验证(5-fold cross-validation)的意思是将数据集分成N个相等的部分(称为“折”),然后进行N次迭代,在每次迭代中,选择其中一个部分作为测试集,其余N-1个部分组成训练集。这样,每个部分都会被用作一次测试集,而其余部分则作为训练集。
# 使用cross_val_score函数进行5折交叉验证,scoring='accuracy'表示使用准确率作为评估指标。
cv_scores = cross_val_score(rf_model_selected,x_train_selector,y_train,cv=5,scoring='accuracy')
# 计算五次交叉验证的平均准确率
mean_av_scores = cv_scores.mean()*100
print(f'Mean cross-validation accuracy:{mean_av_scores:.2f}%')
# 精确率
# precision_score函数默认是为二分类问题设计的。
# 当目标变量是多分类时,需要指定一个合适的average参数来计算精度
# average='weighted'计算每个类别的精确度,然后按每个类别的支持度(即每个类别的实际出现次数)加权平均
precision = precision_score(y_test,pre_sel,average='weighted')*100
print(f'Model prediction precision:{precision:.2f}%')
# 召回率
recall = recall_score(y_test,pre_sel,average='weighted')*100
print(f'Model recall score:{recall:.2f}%')
# 分类报告
print()
report = classification_report(y_test,pre_sel)
print(report)
Model prediction accuracy:93.87% Mean cross-validation accuracy:94.25% Model prediction precision:93.95% Model recall score:93.87%
小结
- 第一个模型的预测准确率为94.41%,第二个模型的预测准确率约为94%左右。这两个准确率非常接近,表示特征选择并没有显著降低模型的性能。
- 第二个模型的预测准确率约为94%左右,表明该模型在测试集上的预测表现很好。
- 第二个模型的交叉验证准确率约为94%,表示该模型在不同数据子集上具有一致的表现。
- 第二个模型的精确率和召回率均为94%,表示该模型不仅能够很好的预测正类(正确的天气类型),而且很少将非正类误判为正类。
接下来看看分类报告
Cloudy:
- Precision (精确率): 0.94,意味着模型预测为多云的样本中有94%实际上是多云。
- Recall (召回率): 0.92,意味着实际多云的样本中有92%被模型正确识别为多云。
- F1-Score (F1分数): 0.93,是精确率和召回率的加权平均值。
- Support (支持度): 635,即测试集中实际多云的样本总数。
其他类别,这里就不赘述了。本563,即测试集中实际晴天的样本总数。
总结
- 从报告中可以看出,模型在四个天气类别上的性能非常好,精确率和召回率都很高,且接近一致。
- 模型在预测多云和晴天时略显保守,召回率相对低一些,而在预测下雨和下雪时,则更加准确,具有较高的召回率。
- 加权平均和宏平均的指标也都接近94%,意味着模型的整体性能良好,并且在不同类别间的性能差异不大。
- 支持度的分布显示了每个类别的样本数量,这对理解性能指标的加权方式是有帮助的。