线性回归
回归分析(Regression Analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法 ,是一种预测性的建模技术。
线性回归,简单而言,就是将输入项分别乘以一些常量,再将结果加起来得到输出。线性回归包括一元线性回归和多元线性回归。
一、一元线性回归
1、一元线性回归
线型回归分析中,如果仅有一个自变量与一个因变量,且其关系大致上可用一条直线表示,则称之为简单回归分析。
如果发现因变量Y和自变量X之间存在高度的正相关,可以确定一条直线的方程,使得所有的数据点尽可能接近这条拟合的直线。简单回归分析的模型可以用以下方程表示:
Y=a+bx
其中:Y为因变量,a为截距,b为相关系数,x为自变量。
2、代码案例(房价预测)
一个简单的线性回归的案例就是房价的预测问题。一般来说,房子的价格与房子大小有很大的关系,房子越大,价值越大。
我们的初始数据如下:
接下来我们进行一元线性回归,
# -*- coding: utf-8 -*-
#导入需要的包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import datasets, linear_model
#读取数据
def get_data(file_name):
data = pd.read_csv(file_name) #用pandas 读取cvs 文件.
X_parameter = []
Y_parameter = []
for single_square_feet ,single_price_value in zip(data['square_feet'],data['price']):#遍历数据,
X_parameter.append([float(single_square_feet)])#存储在相应的list列表中
Y_parameter.append(float(single_price_value))
return X_parameter,Y_parameter
#用于将我们的数据拟合到线性模型的函数
def linear_model_main(X_parameters,Y_parameters,predict_value):
# 创建线性回归对象
regr = linear_model.LinearRegression()
regr.fit(X_parameters, Y_parameters) #训练模型
predict_value = np.array(predict_value).reshape(1, -1)
predict_outcome = regr.predict(predict_value)
predictions = {}
predictions['intercept'] = regr.intercept_
predictions['coefficient'] = regr.coef_
predictions['predicted_value'] = predict_outcome
return predictions
X,Y = get_data('input_data.csv')
predictvalue = 700
result = linear_model_main(X,Y,predictvalue)
print( "截距值 " , result['intercept'] )
print( "回归系数" , result['coefficient'] )
print( "Predicted value: ",result['predicted_value'])
# 显示线性拟合模型结果的函数。
def show_linear_line(X_parameters,Y_parameters):
#创建线性回归对象
regr = linear_model.LinearRegression()
regr.fit(X_parameters, Y_parameters)
plt.scatter(X_parameters,Y_parameters,color='blue')
plt.plot(X_parameters,regr.predict(X_parameters),color='red',linewidth=4)
plt.xticks(())
plt.yticks(())
plt.show()
show_linear_line(X,Y)
二、多元线性回归
1、多元线性回归
多元线性回归是简单线性回归的推广,指的是多个因变量对多个自变量的回归。其中最常用的是只限于一个因变量但有多个自变量的情况,也叫多重回归。多重回归的一般形式如下:
a代表截距,b1,b2,...,bk为回归系数。
2、代码案例
当结果值的印象因素有多个时,可以采用多元线性回归模型。例如:商品的销售额可以与广告投入有关系,广告有:电视、收音机、报纸。
import pandas as pd
import seaborn as sns
#读取数据并查看数据样式及维度
data = pd.read_csv('./Advertising.csv', index_col=0)
print(data.head())
print(data.tail())
print(data.shape)
# 使用散点图将特征和响应之间的关系可视化。
sns.pairplot(data, x_vars=['TV','radio','newspaper'], y_vars='sales', size=7, aspect=0.8)
plt.show()
sns.pairplot(data, x_vars=['TV','radio','newspaper'], y_vars='sales', size=7, aspect=0.8, kind='reg')
plt.show() #注意必须加上这个,否则无法显示
#这里选择TV Redio Newspaper作为特征,Sales作为观察值
#创建特征列表
feature_cols = ['TV', 'radio', 'newspaper']
# use the list to select a subset of the original DataFrame
X = data[feature_cols]
#使用列表选择原始DataFrame的子集
X = data[['TV', 'radio', 'newspaper']]
# 输出前五项数据
print(X.head())
print(type(X))
print(X.shape)
#从DataFrame中选择一个Series
y = data['sales']
y = data.sales
# 输出前五项数据
print(y.head())
print(type(y))
print(y.shape)
#构建训练集和测试集,分别保存在X_train,y_train,Xtest,y_test
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
print (X_train.shape)
print (y_train.shape)
print (X_test.shape)
print (y_test.shape)
linreg = LinearRegression()
linreg.fit(X_train, y_train)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
print (linreg.intercept_)
print (linreg.coef_)
# 将特征名称与系数对应
zip(feature_cols, linreg.coef_)
y_pred = linreg.predict(X_test)
print (np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
plt.figure()
plt.plot(range(len(y_pred)),y_pred,'b',label="predict")
plt.plot(range(len(y_pred)),y_test,'r',label="test")
plt.legend(loc="upper right") #显示图中的标签
plt.xlabel("the number of sales")
plt.ylabel('value of sales')
plt.show()
三、基于线性回归的股票预测
本次的案例使用的是股票数据,数据源从www.quandl.com 获取.本次案例主要是为了练习线性回归
pip install quandl 安装quandl库.
在使用的时候,把quandl的导入.import quandl
数据集介绍,Adj 的是除权重之后的数据,更能翻译股票数据特征,所有主要使用的特征为调整之后的开盘价,最高价,最低价,收盘价与交易额..
HL_PCT(代表的是股票最高价与最低价变化的百分比):
PAC_change :(股票收盘价与开盘价变化的百分比)
import quandl
from sklearn import preprocessing
import math
import numpy as np
df = quandl.get('WIKI/AAPL') #从数据集网站中导入数据集www.quandl.com 中获取
df.head() #其中adj的是由除权重之后的数据集
#开盘价(open),最高价(High),最低价(Low),收盘价(Close),交易额(Volume)
#以及调整后的开盘价(Adj.Open),最高价(Adj.High)
#除权之后的的数据
#数据的预测列变量,存放研究对象的标签名.
forecast_col = "Adj. Close"
df.columns
#定义预测天数,这里设置为所有数据量长度的1%
forecast_out = int(math.ceil(0.01*len(df)))
# 只用到df中下面的几个字段
df = df[['Adj. Open', 'Adj. High', 'Adj. Low', 'Adj. Close', 'Adj. Volume']]
# 构造两个新的列
# HL_PCT为股票最高价与最低价的变化百分比
df['HL_PCT'] = (df['Adj. High'] - df['Adj. Close']) / df['Adj. Close'] * 100.0
# PCT_change为股票收盘价与开盘价的变化百分比
df['PCT_change'] = (df['Adj. Close'] - df['Adj. Open']) / df['Adj. Open'] * 100.0
# 下面为真正用到的特征字段
df = df[['Adj. Close', 'HL_PCT', 'PCT_change', 'Adj. Volume']]
# 因为scikit-learn并不会处理空数据,需要把为空的数据都设置为一个比较难出现的值,这里取-9999,
df.fillna(-99999, inplace=True)
# 用label代表该字段,是预测结果
# 通过让与Adj. Close列的数据往前移动1%行来表示
df['label'] = df[forecast_col].shift(-forecast_out)
# 最后生成真正在模型中使用的数据X和y和预测时用到的数据数据X_lately
X = np.array(df.drop(['label'], 1))
X = preprocessing.scale(X)
# 上面生成label列时留下的最后1%行的数据,这些行并没有label数据,因此我们可以拿他们作为预测时用到的输入数据
X_lately = X[-forecast_out:]
X = X[:-forecast_out]
# 抛弃label列中为空的那些行
df.dropna(inplace=True)
y = np.array(df['label'])
# scikit-learn从0.2版本开始废弃cross_validation,改用model_selection
from sklearn import model_selection, svm
from sklearn.linear_model import LinearRegression
# 开始前,先X和y把数据分成两部分,一部分用来训练,一部分用来测试
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.33)
# 生成scikit-learn的线性回归对象
clf = LinearRegression(n_jobs=-1)
# 开始训练
clf.fit(X_train, y_train)
# 用测试数据评估准确性
accuracy = clf.score(X_test, y_test)
# 进行预测
forecast_set = clf.predict(X_lately)
print(forecast_set, accuracy)
import matplotlib.pyplot as plt
from matplotlib import style
import datetime
plt.figure(figsize=(12, 8))
# 修改matplotlib样式
style.use('ggplot')
one_day = 86400
# 在df中新建Forecast列,用于存放预测结果的数据
df['Forecast'] = np.nan
# 取df最后一行的时间索引
last_date = df.iloc[-1].name
last_unix = last_date.timestamp()
next_unix = last_unix + one_day
# 遍历预测结果,用它往df追加行
# 这些行除了Forecast字段,其他都设为np.nan
for i in forecast_set:
next_date = datetime.datetime.fromtimestamp(next_unix)
next_unix += one_day
# [np.nan for _ in range(len(df.columns) - 1)]生成不包含Forecast字段的列表
# 而[i]是只包含Forecast值的列表
# 上述两个列表拼接在一起就组成了新行,按日期追加到df的下面
df.loc[next_date] = [np.nan for _ in range(len(df.columns) - 1)] + [i]
# 开始绘图
df['Adj. Close'].plot()
df['Forecast'].plot()
plt.legend(loc=4)
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()