当前位置 博文首页 > CSDN资讯:程序员教你如何用 13 种模型预测天气预报 | 原力计划
作者 | 荣仔!最靓的仔!
责编 | 王晓曼
出品 | CSDN博客
天气数据集爬取
?
爬取思路:
确定目标(目标网站:大同历史天气预报 2020年5月份)
请求网页(第三方库 requests)
解析网页(数据提取)
保存数据(这里以 .csv?格式存储到本地)
import?requests
from?bs4?import?BeautifulSoup
import?pandas?as?pd
def?get_data(url):
????#?请求网页(第三方?requests)
????resp?=?requests.get(url)
????#?对于获取到的?HTML?二进制文件进行?'gbk'?转码成字符串文件
????html?=?resp.content.decode('gbk')
????#?通过第三方库?BeautifulSoup?缩小查找范围(同样作用的包库还有re模块、xpath等)
????soup?=?BeautifulSoup(html,'html.parser')
????#?获取?HTML?中所有<tr>…</tr>标签,因为我们需要的数据全部在此标签中存放
????tr_list?=?soup.find_all('tr')
????#?初始化日期dates、气候contains、温度temp值
????dates,contains,temp?=?[],[],[]
????for?data?in?tr_list[1:]:??#?不要表头
????????#?数据值拆分,方便进一步处理(这里可以将获得的列表输出[已注释],不理解的读者可运行查看)
????????sub_data?=?data.text.split()
????????#?print(sub_data)
????????#?观察上一步获得的列表,这里只想要获得列表中第二个和第三个值,采用切片法获取
????????dates.append(sub_data[0])
????????contains.append(','.join(sub_data[1:3]))
????????#?print(contains)
????????#?同理采用切片方式获取列表中的最高、最低气温
????????temp.append(','.join(sub_data[3:6]))
????????#?print(temp)
????#?使用?_data?表存放日期、天气状况、气温表头及其值
????_data?=?pd.DataFrame()
????#?分别将对应值传入?_data?表中
????_data['日期']?=?dates
????_data['天气状况']?=?contains
????_data['气温']?=?temp
????return?_data
#?爬取目标网页(大同市2020年5月份天气[网站:天气后报])
data_5_month?=?get_data('http://www.tianqihoubao.com/lishi/datong/month/202005.html')
#?拼接所有表并重新设置行索引(若不进行此步操作,可能或出现多个标签相同的值)
data?=?pd.concat([data_5_month]).reset_index(drop?=?True)
#?将?_data 表以 .csv 格式存入指定文件夹中,并设置转码格式防止乱花(注:此转码格式可与 HTML 二进制转字符串的转码格式不同)
data.to_csv('F:/DaTong5Mouth.csv',encoding='utf-8')
数据可视化
?
数据可视化用到了可视化工具。
其要点包含有:读取数据、数据清洗、数据处理、可视化工具的使用。
#?数据可视化
from?matplotlib?import?pyplot?as?plt
import?pandas?as?pd
#?解决显示中文问题
plt.rcParams['font.sans-serif']?=?['SimHei']
#?第一步:数据读取
data?=?pd.read_csv('F:/DaTong5Mouth.csv')
#?第二步:数据处理(由于我们知道文本内容,不存在脏数据,故忽略数据清理步骤)
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
data['最低气温']?=?data['气温'].str.split('/',expand=True)[1]
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
data['最低气温']?=?data['最低气温'].map(lambda?x:x.replace('℃,',''))
dates?=?data['日期']
highs?=?data['最高气温']
lows?=?data['最低气温']
#?画图(折线图)
#?设置画布大小及比例
fig?=?plt.figure(dpi=128,figsize=(10,6))
#?设置最高温最低温线条颜色及宽度等信息
L1,=plt.plot(dates,lows,label='最低气温')
L2,=plt.plot(dates,highs,label='最高气温')
plt.legend(handles=[L1,L2],labels=['最高气温','最低气温'],?loc='best')#?添加图例
#?图表格式
#?设置图形格式
plt.title('2020年5月上旬大同天气',fontsize=25)??#?字体大小设置为25
plt.xlabel('日期',fontsize=10)???#?x轴显示“日期”,字体大小设置为10
fig.autofmt_xdate()?#?绘制斜的日期标签,避免重叠
plt.ylabel('气温',fontsize=10)??#?y轴显示“气温”,字体大小设置为10
plt.tick_params(axis='both',which='major',labelsize=10)
#?plt.plot(highs,lows,label?=?'最高气温')
#?修改刻度
plt.xticks(dates[::1])??#?由于数据不多,将每天的数据全部显示出来
#?显示折线图
plt.show()
模型预测数据
?
1、单变量线性回归
模型一:单变量线性回归模型
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
#?将数据从上一步存入的?.csv?格式文件中读取
data?=?pd.read_csv(r'F:\DaTong5Mouth.csv')
#?由于最高气温与最低气温中有?/?分隔,故将其分开,即“气温”列由一列变为两列——“最高气温”和“最低气温”
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
#?日次操作同理,这里不再赘述
data['日期']?=?data['日期'].map(lambda?x:x.replace('2020年05月0',''))
data['日期']?=?data['日期'].map(lambda?x:x.replace('日',''))
#?不理解的小伙伴可运行下两行代码查看运行结果(这里先注释掉了)
#?print(data['日期'])
#?print(data['最高气温'])
def?initPlot():
????#?先准备好一块画布
????plt.figure()
????#?生成图表的名字
????plt.title('2020年5月上旬大同天气')
????#?横坐标名字
????plt.xlabel('日期')
????#?纵坐标名字
????plt.ylabel('当日最高气温')
????#?表内有栅格(不想要栅格把此行注释掉即可)
????plt.grid(True)?
????return?plt
plt?=?initPlot()??#?画图
#?传入对应日期及其最高气温参数
xTrain?=?np.array([1,2,3,4,5,6,7,8,9])
yTrain?=?np.array([33,35,28,20,26,27,23,22,22])
#?k是黑色,.是以点作为图上显示
plt.plot(xTrain,?yTrain,?'k.')
#?将图显示出来
plt.show()
可以看到:
最高气温随着日期的变化,大致呈现线性变化(最近气温下降);
如果根据现有的训练数据能够拟合出一条直线,使之与这些训练数据的各点都比较接近,那么根据该直线,就可以计算出在10号或者11号的温度情况(气温受到影响因素较多,故这里仅预测为数不多的数据)。
解决方案:
采用Python scikit-learn库中提供的sklearn.linear_model.LinearRegression对象来进行线性拟合。
根据判别函数,绘制拟合直线,并同时显示训练数据点。
拟合的直线较好的穿过训练数据,根据新拟合的直线,可以方便的求出最近日期下对应的最高气温(预测结果)。
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
from?sklearn.linear_model?import?LinearRegression
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
#?将数据从上一步存入的?.csv?格式文件中读取
data?=?pd.read_csv(r'F:\DaTong5Mouth.csv')
#?由于最高气温与最低气温中有?/?分隔,故将其分开,即“气温”列由一列变为两列——“最高气温”和“最低气温”
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
#?日次操作同理,这里不再赘述
data['日期']?=?data['日期'].map(lambda?x:x.replace('2020年05月0',''))
data['日期']?=?data['日期'].map(lambda?x:x.replace('日',''))
#?不理解的小伙伴可运行下两行代码查看运行结果(这里先注释掉了)
#?print(data['日期'])
#?print(data['最高气温'])
#?传入对应日期及其最高气温参数
#?#?应以矩阵形式表达(对于单变量,矩阵就是列向量形式)
xTrain?=?np.array([1,2,3,4,5,6,7,8,9])[:,?np.newaxis]
#?为方便理解,也转换成列向量
yTrain?=?np.array([33,35,28,20,26,27,23,22,22])
#?创建模型对象
model?=?LinearRegression()
#?根据训练数据拟合出直线(以得到假设函数)
hypothesis?=?model.fit(xTrain,?yTrain)
#?截距
print("theta0=",?hypothesis.intercept_)
#?斜率
print("theta1=",?hypothesis.coef_)
#?预测2020年5月10日的最高气温
print("预测2020年5月10日的最高气温:",?model.predict([[10]]))
#?也可以批量预测多个日期的气温,注意要以列向量形式表达(有余数据集量少,故间隔时间长气温可能有较大差异)
#?此处仅利用模型表示,不代表真实值(假设要预测10号、11号、12号的天气)
xNew?=?np.array([0,10,?11,?12])[:,?np.newaxis]
yNew?=?model.predict(xNew)
print("预测新数据:",?xNew)
print("预测结果:",?yNew)
def?initPlot():
????#?先准备好一块画布
????plt.figure()
????#?生成图表的名字
????plt.title('2020年5月上旬大同天气')
????#?横坐标名字
????plt.xlabel('日期')
????#?纵坐标名字
????plt.ylabel('当日最高气温')
????#?表内有栅格(不想要栅格把此行注释掉即可)
????plt.grid(True)
????return?plt
plt?=?initPlot()??#?画图
#?k是黑色,.是以点作为图上显示
plt.plot(xTrain,?yTrain,?'k.')
#?画出通过这些点的连续直线
plt.plot(xNew,?yNew,?'g--')
#?将图显示出来
plt.show()
模型评价:
拟合出来的判别函数效果如何:对训练数据的贴合度如何?对新数据的预测准确度如何?
可通过残差(residuals)和R方(r-squared)判断,?在Python中如何对单变量线性回归模型的效果进行评估。
手动计算:
假设hpyTrain代表针对训练数据的预测最高气温值,hpyTest代表针对测试数据的预测最高气温值。
训练数据残差平方和:ssResTrain = sum((hpyTrain - yTrain) ** 2)
测试数据残差平方和:ssResTest = sum((hpyTest - yTest) ** 2)
测试数据偏差平方和:ssTotTest = sum((yTest - np.mean(yTest)) ** 2)
R方:Rsquare = 1 -ssResTest / ssTotTest
LinearRegression对象提供的方法:
训练数据残差平方和:model._residues
R方:model.score(xTest,yTest)
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
from?sklearn.linear_model?import?LinearRegression
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
#?将数据从上一步存入的?.csv?格式文件中读取
data?=?pd.read_csv(r'F:\DaTong5Mouth.csv')
#?由于最高气温与最低气温中有?/?分隔,故将其分开,即“气温”列由一列变为两列——“最高气温”和“最低气温”
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
#?日次操作同理,这里不再赘述
data['日期']?=?data['日期'].map(lambda?x:x.replace('2020年05月0',''))
data['日期']?=?data['日期'].map(lambda?x:x.replace('日',''))
#?不理解的小伙伴可运行下两行代码查看运行结果(这里先注释掉了)
#?print(data['日期'])
#?print(data['最高气温'])
#?传入对应日期及其最高气温参数
#?#?#?应以矩阵形式表达(对于单变量,矩阵就是列向量形式)
#?xTrain?=?np.array(data['日期'])[:,?np.newaxis]
#?#?为方便理解,也转换成列向量
#?yTrain?=?np.array(data['最高气温'])
xTrain?=?np.array([1,2,3,4,5,6,7,8,9])[:,?np.newaxis]??#?训练数据(日期)
yTrain?=?np.array([33,35,28,20,26,27,23,22,22])????????#?训练数据(最高气温)
xTest?=?np.array([3,6,9,10,11])[:,np.newaxis]??????????#?测试数据(日期)
yTest?=?np.array([28,27,22,20,19])????????????????????#?测试数据(最高气温)
#?创建模型对象
model?=?LinearRegression()
#?根据训练数据拟合出直线(以得到假设函数)
hypothesis?=?model.fit(xTrain,?yTrain)
hpyTrain?=?model.predict(xTrain)
#?针对测试数据进行预测
hpyTest?=?model.predict(xTest)
#?手动计算训练数据集残差
ssResTrain?=?sum((hpyTrain?-?yTrain)?**?2)
print(ssResTrain)
#?Python计算的训练数据集残差
print(model._residues)
#?手动计算测试数据集残差
ssResTest?=?sum((hpyTest?-?yTest)?**?2)
#?手动计算测试数据集y值偏差平方和
ssTotTest?=?sum((yTest?-?np.mean(yTest))?**?2)
#?手动计算R方
Rsquare?=?1?-?ssResTest?/?ssTotTest
print(Rsquare)
#?Python计算的训练数据集的R方
print(model.score(xTest,?yTest))
#?corrcoef函数是在各行元素之间计算相关性,所以x和y都应是行向量
print(np.corrcoef(xTrain.T,?yTrain.T))??#?计算训练数据的相关性
print(np.corrcoef(xTest.T,?yTest.T))????#?计算测试数据的相关性
def?initPlot():
????#?先准备好一块画布
????plt.figure()
????#?生成图表的名字
????plt.title('2020年5月上旬大同天气')
????#?横坐标名字
????plt.xlabel('日期')
????#?纵坐标名字
????plt.ylabel('当日最高气温')
????#?表内有栅格(不想要栅格把此行注释掉即可)
????plt.grid(True)
????return?plt
plt?=?initPlot()
plt.plot(xTrain,?yTrain,?'r.')??????????#?训练点数据(红色)
plt.plot(xTest,?yTest,?'b.')????????????#?测试点数据(蓝色)
plt.plot(xTrain,?hpyTrain,?'g-')????????#?假设函数直线(绿色)
plt.show()
查看上述拟合效果:
红色为训练数据点,蓝色为测试数据点,绿色为判别函数(拟合直线);
计算出的R方为0.833,效果良;
计算出训练数据的相关性为-0.763,测试数据的相关性为-0.968。可以发现,根据数据集的不同,日期与最高气温之间的相关性波动较大。这也能解释为何针对测试数据的R方事实上不够理想。
2、多变量线性回归
在单变量线性回归中,最高气温仅与日期有关(尝试可知,这显然是极不合理的),按照这一假设,其预测的结果并不令人满意(R方=0.833)。因此在多变线性回归模型中再引入一个新的影响因素:最低气温(此处要注意和最高气温一样,计算前先利用 .map 方法将?℃?置空,仅将最低气温调整成数值,以便能够进行数值计算)。
模型二:基于LinearRegression实现的多变量线性回归模型
与单变量线性回归类似,但要注意训练数据此时是(是训练数据条数,是自变量个数)
针对测试数据的预测结果,其R方约为0.466,这时我们发现还没有单变量量线性回归R方值大,说明拟合效果差于单变量线性回归。这是什么问题呢?经过思考,我认为最高气温的影响因素不能拿日期和最低气温来衡量,也就是说,最高气温的走势依据情况特殊而复杂,不能单靠日期和最低气温等片面的为数不多的方面来进行拟合。
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
from?sklearn.linear_model?import?LinearRegression
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
#?将数据从上一步存入的?.csv?格式文件中读取
data?=?pd.read_csv(r'F:\DaTong5Mouth.csv')
#?由于最高气温与最低气温中有?/?分隔,故将其分开,即“气温”列由一列变为两列——“最高气温”和“最低气温”
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
data['最低气温']?=?data['气温'].str.split('/',expand=True)[1]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最低气温']?=?data['最低气温'].map(lambda?x:x.replace('℃,',''))
#?日次操作同理,这里不再赘述
data['日期']?=?data['日期'].map(lambda?x:x.replace('2020年05月0',''))
data['日期']?=?data['日期'].map(lambda?x:x.replace('日',''))
#?不理解的小伙伴可运行下两行代码查看运行结果(这里先注释掉了)
#?print(data['日期'])
#?print(data['最高气温'])
#?print(data['最低气温'])
#?传入对应日期及其最高气温参数
#?#?#?应以矩阵形式表达(对于单变量,矩阵就是列向量形式)
#?xTrain?=?np.array(data['日期'])[:,?np.newaxis]
#?#?为方便理解,也转换成列向量
#?yTrain?=?np.array(data['最高气温'])
#?训练集
xTrain?=?np.array([1,?2,?3,?4,?5,?6,?7,?8,?9])??#?无需手动添加Intercept?Item项
yTrain?=?np.array([[33,?8],?[35,?9],?[28,?4],?[20,?4],?[26,?6],?[27,10],?[23,10],?[22,7],?[22,3]])
#?测试集
xTest?=?np.array([3,?6,?9,?10,?11])
yTest?=?np.array([[28,?4],?[27,?10],?[22,?3],?[20,?5],?[19,?7]])
#?创建模型对象
model?=?LinearRegression()
#?根据训练数据拟合出直线(以得到假设函数)
model.fit(yTrain,?xTrain)
#?针对测试数据进行预测
hpyTest?=?model.predict(yTest)
print("假设函数参数:",?model.intercept_,?model.coef_)
print("测试数据预测结果与实际结果差异:",?hpyTest?-?xTest)
print("测试数据R方:",?model.score(yTest,?xTest))
模型三:基于成本函数和梯度下降实现的多变量线性回归模型
经过模型三的拟合,我们发现R方仅为0.164,还不如模型二的预测结果呢。而根据理论知识我们知道,这个模型预测结果应该是线性回归模型中预测拟合效果较好的一种,低的这个R方值经过思考,可进一步说明最高气温的影响因素不仅仅取决于日期和最低气温,甚至我们可推断出可能与日期及最低气温值等影响因素无关。
通过运行结果发现“50000次循环后,计算仍未收敛”。这说明①在未对自变量归一化处理的情况下,运算出现异常,无法收敛;②设置了过大的学习速率,会导致计算不收敛。
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
import?bgd_resolver
from?sklearn.linear_model?import?LinearRegression
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
def?costFn(theta,?X,?y):??#?成本函数
????temp?=?X.dot(theta)?-?y
????return?(temp.T.dot(temp))?/?(2?*?len(X))
def?gradientFn(theta,?X,?y):??#?根据成本函数,分别对x0,x1...xn求导数(梯度)
????return?(X.T).dot(X.dot(theta)?-?y)?/?len(X)
#?将数据从上一步存入的?.csv?格式文件中读取
data?=?pd.read_csv(r'F:\DaTong5Mouth.csv')
#?由于最高气温与最低气温中有?/?分隔,故将其分开,即“气温”列由一列变为两列——“最高气温”和“最低气温”
data['最高气温']?=?data['气温'].str.split('/',expand=True)[0]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最高气温']?=?data['最高气温'].map(lambda?x:x.replace('℃,',''))
data['最低气温']?=?data['气温'].str.split('/',expand=True)[1]
#?我们要对数值进行分析,所以将多余的单位?℃?从列表中去掉,只保留数值部分
data['最低气温']?=?data['最低气温'].map(lambda?x:x.replace('℃,',''))
#?日次操作同理,这里不再赘述
data['日期']?=?data['日期'].map(lambda?x:x.replace('2020年05月0',''))
data['日期']?=?data['日期'].map(lambda?x:x.replace('日',''))
#?不理解的小伙伴可运行下两行代码查看运行结果(这里先注释掉了)
#?print(data['日期'])
#?print(data['最高气温'])
#?print(data['最低气温'])
#?传入对应日期及其最高气温参数
#?#?#?应以矩阵形式表达(对于单变量,矩阵就是列向量形式)
#?xTrain?=?np.array(data['日期'])[:,?np.newaxis]
#?#?为方便理解,也转换成列向量
#?yTrain?=?np.array(data['最高气温'])
#?训练集
xTrain?=?np.array([1,?2,?3,?4,?5,?6,?7,?8,?9])??#?无需手动添加Intercept?Item项
yTrainData?=?np.array([[33,?8],?[35,?9],?[28,?4],?[20,?4],?[26,?6],?[27,10],?[23,10],?[22,7],?[22,3]])
yTrain?=?np.c_[yTrainData,?np.ones(len(yTrainData))]
np.random.seed(0)
init_theta?=?np.random.randn(yTrain.shape[1])
theta?=?bgd_resolver.batch_gradient_descent(costFn,?gradientFn,?init_theta,?yTrain,?xTrain)
print("theta值",?theta)
#?测试集
xTest?=?np.array([3,?6,?9,?10,?11])
yTestData?=?np.array([[28,?4],?[27,?10],?[22,?3],?[20,?5],?[19,?7]])
yTest?=?np.c_[yTestData,?np.ones(len(yTestData))]
print("测试数据预测值与真实值的差异:",?xTest.dot(theta)?-?xTest)
rsquare?=?bgd_resolver.batch_gradient_descent_rsquare(theta,?yTest,?xTest)
print("测试数据R方:",?rsquare)
3、以"线性回归"的方式来拟合高阶曲线
这一部分我们分别使用一阶曲线(直线)、二阶曲线和三阶曲线进行拟合,并检查拟合效果。
在拟合数据点时,一般来说,对于一个自变量的,拟合出来是一条直线;对于两个自变量的,拟合出来时一个直平面。这种拟合结果是严格意义上的“线性”回归。但是有时候,采用“曲线”或“曲面”的方式来拟合,能够对训练数据产生更逼近的效果。这就是“高阶拟合”。
首先,我们查看要拟合的数据:
import?numpy?as?np
import?matplotlib.pyplot?as?plt
#?解决中文问题(若没有此步骤,表名字及横纵坐标中的汉语将无法显示[具体会显示矩形小方格])
plt.rcParams['font.sans-serif']?=?['SimHei']
xTrain?=?np.array([1,2,3,4,5,6,7,8,9])[:,?np.newaxis]??#?训练数据(日期)
yTrain?=?np.array([33,35,28,20,26,27,23,22,22])????????#?训练数据(最高气温)
xTest?=?np.array([3,6,9,10,11])[:,np.newaxis]??????????#?测试数据(日期)
yTest?=?np.array([28,27,22,20,19])????????????????????#?测试数据(最高气温)
plotData?=?np.array(np.linspace(0,?15,?30))[:,np.newaxis]??????????#?作图用的数据点
def?initPlot():
????plt.figure()
????plt.title('2020年5月上旬大同天气')
????plt.xlabel('日期')
????plt.ylabel('气温')
????plt.grid(True)
????return?plt
plt?=?initPlot()
plt.plot(xTrain,?yTrain,?'r.')??????????#?训练点数据(红色)
plt.plot(xTest,?yTest,?'b.')????????????#?测试点数据(蓝色)
plt.show()
模型四:一阶线性拟合
from?sklearn.linear_model?import?LinearRegression
#?线性拟合
linearModel?=?LinearRegression()
linearModel.fit(xTrain,?yTrain)
linearModelTrainResult?=?linearModel.predict(plotData)
#?计算R方
linearModelRSquare?=?linearModel.score(xTest,?yTest)
print("线性拟合R方:",?linearModelRSquare)
plt?=?initPlot()
plt.plot(xTrain,?yTrain,?'r.')??????????#?训练点数据(红色)
plt.plot(xTest,?yTest,?'b.')????????????#?测试点数据(蓝色)
plt.plot(plotData,?linearModelTrainResult,?'y-')???????????#?线性拟合线
plt.show()
模型五:二阶曲线拟合
PolynomialFeatures.fit_transform提供了将1阶数据扩展到高阶数据的方法;
训练样本和测试样本都需要进行扩充。
from?sklearn.preprocessing?import?PolynomialFeatures
from?sklearn.linear_model?import?LinearRegression
#?二阶曲线拟合??theta0?+?theta1*x?+?theta2*x*x???x*x?=>?z?????theta0+theta1*x+theta2*z
quadratic_featurizer?=?PolynomialFeatures(degree=2)
xTrain_quadratic?=?quadratic_featurizer.fit_transform(xTrain)
print(xTrain_quadratic)????#?查看扩展后的特征矩阵
quadraticModel?=?LinearRegression()
quadraticModel.fit(xTrain_quadratic,?yTrain)
#?计算R方(针对测试数据)
xTest_quadratic?=?quadratic_featurizer.fit_transform(xTest)
quadraticModelRSquare?=?quadraticModel.score(xTest_quadratic,?yTest)
print("二阶拟合R方:",?quadraticModelRSquare)
#?绘图点也同样需要进行高阶扩充以便使用曲线进行拟合
plotData_quadratic?=?quadratic_featurizer.fit_transform(plotData)
quadraticModelTrainResult?=?quadraticModel.predict(plotData_quadratic)
plt?=?initPlot()
plt.plot(xTrain,?yTrain,?'r.')??????????#?训练点数据(红色)
plt.plot(xTest,?yTest,?'b.')????????????#?测试点数据(蓝色)
plt.plot(plotData,?quadraticModelTrainResult,?'g-')????????#?二阶拟合线
plt.show()
模型六:三阶曲线拟合
from?sklearn.preprocessing?import?PolynomialFeatures
from?sklearn.linear_model?import?LinearRegression
#?三阶曲线拟合
cubic_featurizer?=?PolynomialFeatures(degree=3)
xTrain_cubic?=?cubic_featurizer.fit_transform(xTrain)
cubicModel?=?LinearRegression()
cubicModel.fit(xTrain_cubic,?yTrain)
plotData_cubic?=?cubic_featurizer.fit_transform(plotData)
cubicModelTrainResult?=?cubicModel.predict(plotData_cubic)
#?计算R方(针对测试数据)
xTest_cubic?=?cubic_featurizer.fit_transform(xTest)
cubicModelRSquare?=??cubicModel.score(xTest_cubic,?yTest)
print("三阶拟合R方:",?cubicModelRSquare)
plt?=?initPlot()
plt.plot(xTrain,?yTrain,?'r.')??????????#?训练点数据(红色)
plt.plot(xTest,?yTest,?'b.')????????????#?测试点数据(蓝色)
plt.plot(plotData,?cubicModelTrainResult,?'p-')????????????#?三阶拟合线
plt.show()
综上对比我们发现,一阶拟合R方约为0.833,二阶拟合R方约为0.218,三阶拟合R方约为0.800。很显然,得到的拟合R方值并不是随着阶数的增高而增大,同前理,说明日期和最低气温并不是最高气温的影响因素。这正与我们常识所知的结论相吻合。因此,想要预测天气值就错综而复杂,不得片面考虑一个或为数不多的几个因素,且不应考虑到与气温影响因素无关的影响变量:比如说像上例中所提及的日期、最低气温等。
4、线性回归预测天气
模型七:线性回归预测模型
使用sklearn.linear_model.LinearRegression处理。
无需对自变量进行归一化处理,也能得到一致的结果。针对训练数据的R方约为0.583。
(1)装载并查看数据信息
import?numpy?as?np
xTrain?=?np.array([1,2,3,4,5,6,7,8,9])[:,?np.newaxis]??#?训练数据(日期)
yTrain?=?np.array([33,35,28,20,26,27,23,22,22])????????#?训练数据(最高气温)
#?查看天气统计数据
print("天气数据统计:")
print("最低:%.2f, 最高:%.2f, 平均:%.2f, 中位数:%.2f, 标准差:%.2f"?%
?????(np.min(yTrain),?np.max(yTrain),?np.mean(yTrain),?np.median(yTrain)?,np.std(yTrain)))
(2)使用LinearRegression,没有进行归一化预处理
'''?使用LinearRegression,没有进行归一化预处理?'''
import?numpy?as?np
from?sklearn.linear_model?import?LinearRegression
train_data?=?np.array([1,2,3,4,5,6,7,8,9])[:,?np.newaxis]??#?训练数据(日期)
train_temp?=?np.array([33,35,28,20,26,27,23,22,22])[:,?np.newaxis]??????#?训练数据(最高气温)
xTrain?=?np.array(train_data[:,?0:2])
yTrain?=?np.array(train_temp[:,?-1])
xTrain?=?np.c_[xTrain,?np.ones(len(xTrain))]
model?=?LinearRegression()
model.fit(xTrain,?yTrain)
(3)使用LinearRegression,进行归一化预处理?