第17周:天气预测

目录

前言

一、前期准备

1.1 导入库

1.2 导入数据

1.2.1 数据介绍

1.2.2 数据导入

二、探索式数据分析(EDA)

2.1 数据相关性探索

2.2 是否会下雨

2.3 地理位置与下雨的关系

2.4 湿度和压力对下雨的影响

2.5 气温对下雨的影响

三、数据预处理

3.1 缺失值处理

3.2 构建数据集

四、预测是否会下雨

4.1 模型搭建

4.2 模型训练

4.3 结果可视化

总结


前言

说在前面

本周目标:根据每日天气观测数据对RainTomorrow进行一个预测,同时增加了探索式数据分析(EDA)

我的环境:Python3.6、Pycharm2020、TensorFlow2.4.0

数据来源:[K同学啊](https://mtyjkh.blog.csdn.net/)


一、前期准备

1.1 导入库

代码如下:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
import tensorflow as tf
warnings.filterwarnings('ignore')

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
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
from sklearn.preprocessing import LabelEncoder
from tensorflow.keras.optimizers import Adam

1.2 导入数据

1.2.1 数据介绍

       该数据集提供了来自澳大利亚许多地点的大约10年的每日天气观测数据(2008.12.01—2017.06.05),记录了22个参数包含Location、MinTemp、MaxTemp、Rainfall、Evaporation、Sunshine、WindGustDir、WindGustSpeed、WindDir9am、WindDir3am、WindSpeed9am、WindSpeed3am、Humidity9am、Humidity3am、Pressure9am、Pressure3am、Cloud9am、Cloud3am、Temp9am、Temp3am、RainTomorrow、RainToday

1.2.2 数据导入

  • data.describe():describe()函数就是返回数据的统计变量,具体包括count--数据统计,此列共有多少有效值,mean--平均值,std--标准差,min--最小值,25%--四分之一分位数,50%--二分之一分位数,75%--四分之三分位数,max--最大值
  • data.dtypes:返回DataFrame中的dtypes。它返回具有每个列的数据类型的Series

代码如下:

#导入数据
data = pd.read_csv("weatherAUS.csv")
df = data.copy()
print(data.head())
print(data.describe())   #查看各参数的统计量
print(data.dtypes)   #查看参数
data['Date'] = pd.to_datetime(data['Date'])
print(data['Date'])
#增加年、月、日三个时间特征
data['year'] = data['Date'].dt.year
data['Month'] = data['Date'].dt.month
data['day'] = data['Date'].dt.day
print(data.head())
data.drop('Date',axis=1,inplace=True)
print(data.columns)

打印输出为:

一开始的数据如下(data.head())

         Date Location  MinTemp  ...  Temp3pm  RainToday  RainTomorrow
0  2008-12-01   Albury     13.4  ...     21.8         No            No
1  2008-12-02   Albury      7.4  ...     24.3         No            No
2  2008-12-03   Albury     12.9  ...     23.2         No            No
3  2008-12-04   Albury      9.2  ...     26.5         No            No
4  2008-12-05   Albury     17.5  ...     29.7         No            No

[5 rows x 23 columns]

数据的统计变量返回(data.describe())

  MinTemp        MaxTemp  ...        Temp9am       Temp3pm
count  143975.000000  144199.000000  ...  143693.000000  141851.00000
mean       12.194034      23.221348  ...      16.990631      21.68339
std         6.398495       7.119049  ...       6.488753       6.93665
min        -8.500000      -4.800000  ...      -7.200000      -5.40000
25%         7.600000      17.900000  ...      12.300000      16.60000
50%        12.000000      22.600000  ...      16.700000      21.10000
75%        16.900000      28.200000  ...      21.600000      26.40000
max        33.900000      48.100000  ...      40.200000      46.70000

[8 rows x 16 columns]

数据类型返回(data.dtype())

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

增加时间特征之后数据前几行返回:

Date Location  MinTemp  MaxTemp  ...  RainTomorrow  year  Month day
0 2008-12-01   Albury     13.4     22.9  ...            No  2008     12   1
1 2008-12-02   Albury      7.4     25.1  ...            No  2008     12   2
2 2008-12-03   Albury     12.9     25.7  ...            No  2008     12   3
3 2008-12-04   Albury      9.2     28.0  ...            No  2008     12   4
4 2008-12-05   Albury     17.5     32.3  ...            No  2008     12   5

[5 rows x 26 columns]

数据各列列名返回(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)

2.1 数据相关性探索

  • data.corr(method, min_periods):变量之间的相关性,取值范围为[-1,1],取值接近-1,表示反相关,类似反比例函数,取值接近1,表正相关

       参数说明:method----相关系数计算方法,可选值为‘pearson’、‘kendall’、‘spearman’;min_periods----样本最少的数据量

代码如下(示例):

plt.figure(figsize=(15,13))
ax = sns.heatmap(data.corr(), square=True, annot=True, fmt='.2f')  #data.corr默认为Pearson
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
plt.show()
plt.savefig('相关性分析.png')

相关性分析热图如下:

2.2 是否会下雨

sns.countplot():用于类别特征的频数条形图,可以画类别特征和y值(y值特征也是类比的话)的条形图

sns.countplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, dodge=True, ax=None, **kwargs)

参数说明

x: x轴上的条形图,以x标签划分统计个数

y:y轴上的条形图,以y标签划分统计个数

hue:在x或y标签划分的同时,再以hue标签划分统计个数

data:df或array或array列表,用于绘图的数据集,x或y缺失时,data参数为数据集,同时x或y不可缺少,必须要有其中一个

order, hue_order:分别是对x或y的字段排序,hue的字段排序。排序的方式为列表

orient:强制定向,v:竖直方向;h:水平方向

palette:使用不同的调色板

ax:画子图的时候

pd.crosstab():pandas 库中的一个函数,用于计算两个或多个因子变量之间的频率表。通常,这个函数用于对分类数据进行分析,并帮助我们理解这些分类变量之间的关系

pd.crosstab(index, columns, values=None, aggfunc=None, rownames=None, colnames=None, margins=False, margins_name='All', dropna=True, normalize=False)

参数说明:

index: 指定行索引,可以是一个 Series、数组或列表。
columns: 指定列索引,也可以是一个 Series、数组或列表。
values(可选):要汇总的数据列。如果不提供,则默认计算频数。
aggfunc(可选):指定如何聚合数据列(如果提供了 values 参数)。通常可以使用函数如 'sum'、'mean'、'count' 等。
rownames和colnames(可选):分别为行和列指定名称。
margins(可选):如果设置为 True,则在结果中包括行和列的总计。
margins_name(可选):设置总计的名称。
dropna(可选):如果设置为 True,则删除包含 NaN 值的行和列。
normalize(可选):如果设置为 True,则计算相对频率而不是绝对频率

代码如下:

#2.2是否会下雨
sns.set(style="darkgrid")
plt.figure(figsize=(4,3))
sns.countplot(x='RainTomorrow', data=data)
plt.savefig('明天下雨与否数量统计.png')
plt.figure(figsize=(4,3))
sns.countplot(x='RainToday', data=data)
plt.savefig('今天下雨与否数量统计.png',bbox_inches='tight')
x = pd.crosstab(data['RainTomorrow'], data['RainToday'])  #pd.crosstab交叉表(data['RainTomorrow']--行索引, data['RainToday']--列索引)
print(x)
y = x/x.transpose().sum().values.reshape(2, 1)*100
print(y)
y.plot(kind="bar", figsize=(4, 3), color=['#006666', '#d279a6'])
plt.savefig('是否会下雨条形图.png',bbox_inches='tight')

打印输出如下:

   

上面的数据说明

  • 如果今天不下雨,那么明天下雨的机会=53.22%
  • 如果今天下雨明天也下雨的计划=46.78%

2.3 地理位置与下雨的关系

代码如下:

#2.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)  #对列名为‘yes’的列排序,ascending是否按指定列的数组升序排列
print(y)
fig, ax = plt.subplots(figsize=(15, 20))
color = ['#cc6699', '#006699', '#006666', '#862d86', '#ff9966']
y['Yes'].plot(kind='barh', ax=ax, color=color)
plt.savefig('地理位置与下雨的关系.png')

输出图如下:

根据上图举例说明,位置影响下雨的情况,对于Portland来说,有36%的时间在下雨,而对于Woomers来说,只有6%的时间在下雨

2.4 湿度和压力对下雨的影响

代码如下:

#2.4 湿度和压力对下雨的影响
print(data.columns)
plt.figure(figsize=(8,6))
  #sns.scatterplot绘制散点图,不同的数据点根据"RainTomorrow"列的数值被着以不同的颜色
sns.scatterplot(data=data, x='Pressure9am', y='Pressure3pm', hue='RainTomorrow')
plt.savefig('压力对下雨的影响.png')
plt.figure(figsize=(8, 6))
sns.scatterplot(data=data, x='Humidity9am', y='Humidity3pm', hue='RainTomorrow')
plt.savefig('湿度对下雨的影响.png')

输出如下:

低压和高湿度会增加第二天下雨的概率,尤其是下午3点的空气湿度

2.5 气温对下雨的影响

代码如下(示例):

#2.5 气温对下雨的影响
plt.figure(figsize=(8,6))
sns.scatterplot(x='MaxTemp', y='MinTemp', data=data, hue='RainTomorrow')
plt.savefig('气温对下雨的影响.png')

结论:当一天的最高气温和最低气温接近时,第二天下雨的概率会增加

三、数据预处理

3.1 缺失值处理

data.isnull():元素级别的判断,把对应的所有元素的位置都列出来,元素为空或者NA就显示True,否则就是False

代码如下:

#3.1 处理缺失值
data.isnull().sum()/data.shape[0]*100  #计算每列中缺失数据的百分比
 #在该列中随机选择数进行填充
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)
print(object_cols)
for i in object_cols:
    data[i].fillna(data[i].mode()[0], inplace=True)  #inplace=True直接修改原对象,不创建副本
    #data[i].mode()[0]返回频率出现最高的选项,众数

t = (data.dtypes == "float64")  #检查哪些列的数据类型是float64,并将结果存储在一个名为t的布尔类型Series中
num_cols = list(t[t].index)
print(num_cols)
for i in num_cols:
    data[i].fillna(data[i].median(), inplace=True)  #data[i].median()中位数

print(data.isnull().sum())

输出如下:

  • object_cols——['Location', 'WindGustDir', 'WindDir9am', 'WindDir3pm', 'RainToday', 'RainTomorrow']
  • num_cols——['MinTemp', 'MaxTemp', 'Rainfall', 'Evaporation', 'Sunshine', 'WindGustSpeed', 'WindSpeed9am', 'WindSpeed3pm', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm', 'Cloud9am', 'Cloud3pm', 'Temp9am', 'Temp3pm']
  • pdata.isnull().sum()

3.2 构建数据集

代码如下:

#3.2 构建数据集
label_encoder = LabelEncoder()
#一般先对训练数据fit_transform,对测试数据用transform
for i in object_cols:
    data[i] = label_encoder.fit_transform(data[i])  #fit_transform()的作用就是先拟合数据,然后转化它将其转化为标准形式
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)

四、预测是否会下雨

4.1 模型搭建

  • 模型——包含多个带有tanh激活函数的密集层,接着是dropout层用于防止过拟合,并以sigmoid激活函数结束,用于二元分类。您正在使用Adam优化器,特定的学习率,二元交叉熵损失函数,以及准确率作为评估指标
  • model.compile()函数被设计为一个编译器,用于将模型的图形结构定义与计算引擎进行链接,以实现优化、损失函数的选择和训练过程的配置
  • callbacks回调函数,一般的训练过程是先训练一遍,然后得到一个验证集的正确率变化趋势,从而知道最佳的epoch,设置最佳epoch,再训练一遍得到最终结果,十分浪费时间!!! 节省时间的一个办法是在验证集准确率不再上升的时候,终止训练。
  • EarlyStopping(早停)的作用就是当模型在验证集上的性能不再增加的时候就停止训练,从而达到充分训练的作用,又避免过拟合为解决epoch数量需要手动设置的问题 将数据分为训练集和验证集,每个epoch结束后(或每N个epoch后): 在验证集上获取测试结果, 随着epoch的增加,如果在验证集上发现测试误差上升,则停止训练;将停止之后的权重作为网络的最终参数

代码如下:

#4.1 搭建神经网络
model = Sequential()
model.add(Dense(units=24, activation='tanh'))  #units该层神经元节点数
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")
early_stop = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=25, restore_best_weights=True)

4.2 模型训练

model.fit( ) :将训练数据在模型中训练一定次数,返回loss和测量指标

model.fit(x, y, batch_size, epochs, verbose, validation_split, validation_data, validation_freq)

参数说明:

  • x——输入
  • y——输出
  • batch_size——每一个batch的大小(批尺寸),即训练一次网络所用的样本数;
  • verbose——0:不输出信息;1:显示进度条(一般默认为1);2:每个epoch输出一行记录;
  • validation_split——(0,1)的浮点数,分割数据当验证数据,其它当训练数据
  • validation_data——指定验证数据,该数据将覆盖validation_spilt设定的数据
  • validation_freq——指定验证数据的epoch
  • callback——在每个training/epoch/batch结束时,可以通过回调函数Callbacks查看一些内部信息。

代码如下:

#4.2 模型训练
model.fit(x=X_train, y=y_train, validation_data=(X_test, y_test), verbose=1, callbacks=[early_stop], epochs=10, batch_size=32)
  #model.fit中将训练集loss、测试集loss、训练集准确率保存了下来为history

训练过程如下:

4.3 结果可视化

代码如下:

#4.3 结果可视化
acc = model.history.history['accuracy']
val_acc = model.history.history['val_accuracy']
loss = model.history.history['loss']
val_loss = model.history.history['val_loss']
epoch_range = range(10)

plt.figure(figsize=(14,4))
plt.subplot(1, 2, 1)
plt.plot(epoch_range, acc, label='Training Accuracy')
plt.plot(epoch_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')

plt.subplot(1, 2, 2)
plt.plot(epoch_range, loss, label='Training Loss')
plt.plot(epoch_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

plt.savefig('训练结果可视化.png')

打印输出如下:


总结

  • 通过tensflow框架进行对下雨与否的预测
  • 进行了详细的探索式数据分析(EDA)——提供了多个方法和角度进行分析判断
  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值