R5周:天气预测
- 🍨 本文为🔗365天深度学习训练营中的学习记录博客
- 🍖 原作者:K同学啊
一、导入数据
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.layers import Dropout
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import r2_score
from sklearn.metrics import mean_absolute_error, mean_absolute_percentage_error, mean_squared_error
data = pd.read_csv("F:/jupyter lab/DL-100-days/datasets/weather_pre/weatherAus.csv")
df = data.copy()
data.head()
data.describe()
data.dtypes
Date object Location object MinTemp float64 MaxTemp float64 Rainfall float64 Evaporation float64 Sunshine float64 WindGustDir object WindGustSpeed float64 WindDir9am object WindDir3pm object WindSpeed9am float64 WindSpeed3pm float64 Humidity9am float64 Humidity3pm float64 Pressure9am float64 Pressure3pm float64 Cloud9am float64 Cloud3pm float64 Temp9am float64 Temp3pm float64 RainToday object RainTomorrow object dtype: object
#将数据转换为日期时间格式
data['Date']= pd.to_datetime(data['Date'])
data['year']= data['Date'].dt.year
data['Month']= data['Date'].dt.month
data['day']= data['Date'].dt.day
data.head()
data.drop('Date',axis=1,inplace=True)
data.columns
Index(['Location', 'MinTemp', 'MaxTemp', 'Rainfall', 'Evaporation', 'Sunshine', 'WindGustDir', 'WindGustSpeed', 'WindDir9am', 'WindDir3pm', 'WindSpeed9am', 'WindSpeed3pm', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm', 'Cloud9am', 'Cloud3pm', 'Temp9am', 'Temp3pm', 'RainToday', 'RainTomorrow', 'year', 'Month', 'day'], dtype='object')
二、探索式数据分析(EDA)
1.数据相关性探索
plt.figure(figsize=(15,13))
#data.corr()表示了data中的两个变量之间的相关性
ax=sns.heatmap(data.corr(),square=True, annot=True, fmt='.2f')
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
plt.show()
2.是否会下雨
#设置样式和调色板
sns.set(style="whitegrid",palette="Set2")
#创建一个1行2列的图像布局
fig,axes =plt.subplots(1,2,figsize=(10,4)) #图形尺寸调大(10,4)
#图表标题样式
title_font ={f'fontsize':14,'fontweight':'bold','color':'darkblue'}
#第一张图:RainTomorrow
sns.countplot(x='RainTomorrow',data=data, ax=axes[0],edgecolor='black') # 添加边框
axes[0].set_title('Rain Tomorrow',fontdict=title_font)# 设置标题
axes[0].set_xlabel('Will it Rain Tomorrow?', fontsize=12) # X轴标签
axes[0].set_ylabel('Count', fontsize=12) # Y轴标签
axes[0].tick_params(axis='x', labelsize=11)#x轴刻度字体大小
axes[0].tick_params(axis='y', labelsize=11)# Y轴刻度字体大小
#第二张图:RainToday
sns.countplot(x='RainToday',data=data,ax=axes[1],edgecolor='black') #添加边框
axes[1].set_title('Rain Today',fontdict=title_font) # 设置标题
axes[1].set_xlabel('Did it Rain Today?',fontsize=12) # X轴标签
axes[1].set_ylabel('count', fontsize=12)#Y轴标签
axes[1].tick_params(axis='x',labelsize=11)#x轴刻度字体大小
axes[1].tick_params(axis='y',labelsize=11)#Y轴刻度字体大小
sns.despine()#去除图表顶部和右侧的边框
plt.tight_layout()#调整布局,避免图形之间的重叠
plt.show()
x=pd.crosstab(data['RainTomorrow'],data['RainToday'])
x
y=x/x.transpose().sum().values.reshape(2,1)*100
y
y.plot(kind="bar",figsize=(4,3),color=['#006666','#d279a6']);
3.地理位置与下雨的关系
x=pd.crosstab(data['Location'],data['RainToday']) #获取每个城市下雨天数和非下雨天数的百分比
y=x/x.transpose().sum().values.reshape((-1,1))*100 #按每个城市的雨天百分比排序
y=y.sort_values(by='Yes',ascending=True)
color=['#cc6699','#006699','#006666','#862d86','#ff9966']
y.Yes.plot(kind="barh",figsize=(15,20),color=color)
4.湿度和压力对下雨的影响
data.columns
Index(['Location', 'MinTemp', 'MaxTemp', 'Rainfall', 'Evaporation', 'Sunshine', 'WindGustDir', 'WindGustSpeed', 'WindDir9am', 'WindDir3pm', 'WindSpeed9am', 'WindSpeed3pm', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm', 'Cloud9am', 'Cloud3pm', 'Temp9am', 'Temp3pm', 'RainToday', 'RainTomorrow', 'year', 'Month', 'day'], dtype='object')
plt.figure(figsize=(8,6))
sns.scatterplot(data=data,x='Pressure9am',y='Pressure3pm',hue='RainTomorrow');
plt.figure(figsize=(8,6))
sns.scatterplot(data=data,x='Humidity9am',y='Humidity3pm',hue='RainTomorrow');
5.气温对下雨的影响
plt.figure(figsize=(8,6))
sns.scatterplot(x='MaxTemp',y='MinTemp',data=data,hue='RainTomorrow');
三、数据预处理
1.处理缺损值
#每列中缺失数据的百分比
data.isnull().sum()/data.shape[0]*100
Location 0.000000 MinTemp 1.020899 MaxTemp 0.866905 Rainfall 2.241853 Evaporation 43.166506 Sunshine 48.009762 WindGustDir 7.098859 WindGustSpeed 7.055548 WindDir9am 7.263853 WindDir3pm 2.906641 WindSpeed9am 1.214767 WindSpeed3pm 2.105046 Humidity9am 1.824557 Humidity3pm 3.098446 Pressure9am 10.356799 Pressure3pm 10.331363 Cloud9am 38.421559 Cloud3pm 40.807095 Temp9am 1.214767 Temp3pm 2.481094 RainToday 2.241853 RainTomorrow 2.245978 year 0.000000 Month 0.000000 day 0.000000 dtype: float64
Location 0.000000
MinTemp 1.020899
MaxTemp 0.866905
Rainfall 2.241853
Evaporation 43.166506
Sunshine 48.009762
WindGustDir 7.098859
WindGustSpeed 7.055548
WindDir9am 7.263853
WindDir3pm 2.906641
WindSpeed9am 1.214767
WindSpeed3pm 2.105046
Humidity9am 1.824557
Humidity3pm 3.098446
Pressure9am 10.356799
Pressure3pm 10.331363
Cloud9am 38.421559
Cloud3pm 40.807095
Temp9am 1.214767
Temp3pm 2.481094
RainToday 2.241853
RainTomorrow 2.245978
year 0.000000
Month 0.000000
day 0.000000
dtype: float64
#在该列中随机选择数进行填充
lst=['Evaporation','Sunshine','Cloud9am','Cloud3pm']
for col in lst:
fill_list = data[col].dropna()
data[col] = data[col].fillna(pd.Series(np.random.choice(fill_list, size=len(data.index))))
s=(data.dtypes =="object")
object_cols = list(s[s].index)
object_cols
['Location', 'WindGustDir', 'WindDir9am', 'WindDir3pm', 'RainToday', 'RainTomorrow']
# inplace=True:直接修改原对象,不创建副本
# data[i].mode()[0]返回频率出现最高的选项,众数
for i in object_cols:
data[i].fillna(data[i].mode()[0], inplace=True)
t=(data.dtypes == "float64")
num_cols = list(t[t].index)
num_cols
['MinTemp', 'MaxTemp', 'Rainfall', 'Evaporation', 'Sunshine', 'WindGustSpeed', 'WindSpeed9am', 'WindSpeed3pm', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm', 'Cloud9am', 'Cloud3pm', 'Temp9am', 'Temp3pm']
#.median(), 中位数
for i in num_cols:
data[i].fillna(data[i].median(),inplace=True)
data.isnull().sum()
Location 0 MinTemp 0 MaxTemp 0 Rainfall 0 Evaporation 0 Sunshine 0 WindGustDir 0 WindGustSpeed 0 WindDir9am 0 WindDir3pm 0 WindSpeed9am 0 WindSpeed3pm 0 Humidity9am 0 Humidity3pm 0 Pressure9am 0 Pressure3pm 0 Cloud9am 0 Cloud3pm 0 Temp9am 0 Temp3pm 0 RainToday 0 RainTomorrow 0 year 0 Month 0 day 0 dtype: int64
2.构建数据集
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
for i in object_cols:
data[i]= label_encoder.fit_transform(data[i])
X = data.drop(['RainTomorrow','day'],axis=1).values
y = data['RainTomorrow'].values
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.25,random_state=101)
scaler =MinMaxScaler()
scaler.fit(X_train)
X_train =scaler.transform(X_train)
X_test= scaler.transform(X_test)
四、预测是否下雨
1.搭建神经网络
from tensorflow.keras.optimizers import Adam
model = Sequential()
model.add(Dense(units=24,activation='tanh',))
model.add(Dense(units=18,activation='tanh'))
model.add(Dense(units=23,activation='tanh'))
model.add(Dropout(0.5))
model.add(Dense(units=12,activation='tanh'))
model.add(Dropout(0.2))
model.add(Dense(units=1,activation='sigmoid'))
optimizer =tf.keras.optimizers.Adam(learning_rate=1e-4)
model.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics="accuracy")
2.模型训练
model.fit(x=X_train,
y=y_train,
validation_data=(X_test,y_test),
verbose=1,
epochs = 10,
batch_size =32
)
Epoch 1/10 3410/3410 [==============================] - 21s 5ms/step - loss: 0.4584 - accuracy: 0.8010 - val_loss: 0.3922 - val_accuracy: 0.8279 Epoch 2/10 3410/3410 [==============================] - 16s 5ms/step - loss: 0.3952 - accuracy: 0.8324 - val_loss: 0.3782 - val_accuracy: 0.8361 Epoch 3/10 3410/3410 [==============================] - 16s 5ms/step - loss: 0.3873 - accuracy: 0.8353 - val_loss: 0.3750 - val_accuracy: 0.8388 Epoch 4/10 3410/3410 [==============================] - 16s 5ms/step - loss: 0.3828 - accuracy: 0.8378 - val_loss: 0.3744 - val_accuracy: 0.8389 Epoch 5/10 3410/3410 [==============================] - 17s 5ms/step - loss: 0.3812 - accuracy: 0.8386 - val_loss: 0.3721 - val_accuracy: 0.8400 Epoch 6/10 3410/3410 [==============================] - 17s 5ms/step - loss: 0.3796 - accuracy: 0.8390 - val_loss: 0.3716 - val_accuracy: 0.8389 Epoch 7/10 3410/3410 [==============================] - 17s 5ms/step - loss: 0.3787 - accuracy: 0.8389 - val_loss: 0.3708 - val_accuracy: 0.8399 Epoch 8/10 3410/3410 [==============================] - 17s 5ms/step - loss: 0.3779 - accuracy: 0.8393 - val_loss: 0.3708 - val_accuracy: 0.8400 Epoch 9/10 3410/3410 [==============================] - 17s 5ms/step - loss: 0.3774 - accuracy: 0.8393 - val_loss: 0.3704 - val_accuracy: 0.8403 Epoch 10/10 3410/3410 [==============================] - 18s 5ms/step - loss: 0.3770 - accuracy: 0.8394 - val_loss: 0.3700 - val_accuracy: 0.8403
3.结果可视化
import matplotlib.pyplot as plt
acc = model.history.history['accuracy']
val_acc = model.history.history['val_accuracy']
loss = model.history.history['loss']
val_loss = model.history.history['val_loss']
epochs_range = range(10)
plt.figure(figsize=(14, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range,acc,label='Training Accuracy')
plt.plot(epochs_range,val_acc,label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range,loss,label='Training Loss')
plt.plot(epochs_range,val_loss,label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
五、学习心得
1.本周使用探索式数据分析(EDA)开展天气预测,气象数据复杂,通过EDA,可以梳理结构、图表的性质显得非常直观。
2.天气数据中存在缺失,通过比例和填补法对数据进行相应的补充,相对完整,体量较大的数据更能进行全面的分析。
3.但是学习的还不够深入,有些地方不是很懂,接下来会找一些其他的案例进行练习。