python 神经网络预测 持续性预测

2024-05-10

1. python 神经网络预测 持续性预测

学习人工智能时,我给自己定了一个目标--用Python写一个简单的神经网络。为了确保真得理解它,我要求自己不使用任何神经网络库,从头写起。多亏了Andrew Trask写得一篇精彩的博客,我做到了!下面贴出那九行代码:在这篇文章中,我将解释我是如何做得,以便你可以写出你自己的。我将会提供一个长点的但是更完美的源代码。

python 神经网络预测 持续性预测

2. python做BP神经网络,进行数据预测,训练的输入和输出值都存在负数,为什么预测值永远为正数?

因为sigmoid就是预测0到1之间的连续值。通常当二分类预测使用,你的问题是否复合二分类如果可以就把类别换成0和1就可以了,如果是做回归那就不行了,要换其他损失函数

3. 如何在Python中用LSTM网络进行时间序列预测

时间序列模型
时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征。这是一类相对比较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发生的先后顺序的,同样大小的值改变顺序后输入模型产生的结果是不同的。举个栗子:根据过去两年某股票的每天的股价数据推测之后一周的股价变化;根据过去2年某店铺每周想消费人数预测下周来店消费的人数等等
RNN 和 LSTM 模型
时间序列模型最常用最强大的的工具就是递归神经网络(recurrent neural network, RNN)。相比与普通神经网络的各计算结果之间相互独立的特点,RNN的每一次隐含层的计算结果都与当前输入以及上一次的隐含层结果相关。通过这种方法,RNN的计算结果便具备了记忆之前几次结果的特点。
典型的RNN网路结构如下:右侧为计算时便于理解记忆而产开的结构。简单说,x为输入层,o为输出层,s为隐含层,而t指第几次的计算;V,W,U为权重,其中计算第t次的隐含层状态时为St = f(U*Xt + W*St-1),实现当前输入结果与之前的计算挂钩的目的。对RNN想要更深入的了解可以戳这里。
RNN的局限:由于RNN模型如果需要实现长期记忆的话需要将当前的隐含态的计算与前n次的计算挂钩,即St = f(U*Xt + W1*St-1 + W2*St-2 + ... + Wn*St-n),那样的话计算量会呈指数式增长,导致模型训练的时间大幅增加,因此RNN模型一般直接用来进行长期记忆计算。
LSTM模型LSTM(Long Short-Term Memory)模型是一种RNN的变型,最早由Juergen Schmidhuber提出的。经典的LSTM模型结构如下:LSTM的特点就是在RNN结构以外添加了各层的阀门节点。阀门有3类:遗忘阀门(forget gate),输入阀门(input gate)和输出阀门(output gate)。这些阀门可以打开或关闭,用于将判断模型网络的记忆态(之前网络的状态)在该层输出的结果是否达到阈值从而加入到当前该层的计算中。如图中所示,阀门节点利用sigmoid函数将网络的记忆态作为输入计算;如果输出结果达到阈值则将该阀门输出与当前层的的计算结果相乘作为下一层的输入(PS:这里的相乘是在指矩阵中的逐元素相乘);如果没有达到阈值则将该输出结果遗忘掉。每一层包括阀门节点的权重都会在每一次模型反向传播训练过程中更新。更具体的LSTM的判断计算过程如下图所示:LSTM模型的记忆功能就是由这些阀门节点实现的。当阀门打开的时候,前面模型的训练结果就会关联到当前的模型计算,而当阀门关闭的时候之前的计算结果就不再影响当前的计算。因此,通过调节阀门的开关我们就可以实现早期序列对最终结果的影响。而当你不不希望之前结果对之后产生影响,比如自然语言处理中的开始分析新段落或新章节,那么把阀门关掉即可。(对LSTM想要更具体的了解可以戳这里)下图具体演示了阀门是如何工作的:通过阀门控制使序列第1的输入的变量影响到了序列第4,6的的变量计算结果。黑色实心圆代表对该节点的计算结果输出到下一层或下一次计算;空心圆则表示该节点的计算结果没有输入到网络或者没有从上一次收到信号。
Python中实现LSTM模型搭建
Python中有不少包可以直接调用来构建LSTM模型,比如pybrain, kears, tensorflow, cikit-neuralnetwork等(更多戳这里)。这里我们选用keras。(PS:如果操作系统用的linux或者mac,强推Tensorflow!!!)
因为LSTM神经网络模型的训练可以通过调整很多参数来优化,例如activation函数,LSTM层数,输入输出的变量维度等,调节过程相当复杂。这里只举一个最简单的应用例子来描述LSTM的搭建过程。
应用实例
基于某家店的某顾客的历史消费的时间推测该顾客前下次来店的时间。具体数据如下所示:
消费时间2015-05-15 14:03:512015-05-15 15:32:462015-06-28 18:00:172015-07-16 21:27:182015-07-16 22:04:512015-09-08 14:59:56....
具体操作:1. 原始数据转化首先需要将时间点数据进行数值化。将具体时间转化为时间段用于表示该用户相邻两次消费的时间间隔,然后再导入模型进行训练是比较常用的手段。转化后的数据如下:
消费间隔04418054....
2.生成模型训练数据集(确定训练集的窗口长度)这里的窗口指需要几次消费间隔用来预测下一次的消费间隔。这里我们先采用窗口长度为3, 即用t-2, t-1,t次的消费间隔进行模型训练,然后用t+1次间隔对结果进行验证。数据集格式如下:X为训练数据,Y为验证数据。PS: 这里说确定也不太合适,因为窗口长度需要根据模型验证结果进行调整的。
X1    X2    X3    Y0    44    18    044    18    0    54....    
注:直接这样预测一般精度会比较差,可以把预测值Y根据数值bin到几类,然后用转换成one-hot标签再来训练会比较好。比如如果把Y按数值范围分到五类(1:0-20,2:20-40,3:40-60,4:60-80,5:80-100)上式可化为:
X1    X2    X3    Y0    44    18    044    18    0    4... 
Y转化成one-hot以后则是(关于one-hot编码可以参考这里)
1    0    0    0    00    0    0    0    1...
3. 网络模型结构的确定和调整这里我们使用python的keras库。(用java的同学可以参考下deeplearning4j这个库)。网络的训练过程设计到许多参数的调整:比如
需要确定LSTM模块的激活函数(activation fucntion)(keras中默认的是tanh);
确定接收LSTM输出的完全连接人工神经网络(fully-connected artificial neural network)的激活函数(keras中默认为linear);
确定每一层网络节点的舍弃率(为了防止过度拟合(overfit)),这里我们默认值设定为0.2;
确定误差的计算方式,这里我们使用均方误差(mean squared error);
确定权重参数的迭代更新方式,这里我们采用RMSprop算法,通常用于RNN网络。
确定模型训练的epoch和batch size(关于模型的这两个参数具体解释戳这里)一般来说LSTM模块的层数越多(一般不超过3层,再多训练的时候就比较难收敛),对高级别的时间表示的学习能力越强;同时,最后会加一层普通的神经网路层用于输出结果的降维。典型结构如下:如果需要将多个序列进行同一个模型的训练,可以将序列分别输入到独立的LSTM模块然后输出结果合并后输入到普通层。结构如下:

4. 模型训练和结果预测将上述数据集按4:1的比例随机拆分为训练集和验证集,这是为了防止过度拟合。训练模型。然后将数据的X列作为参数导入模型便可得到预测值,与实际的Y值相比便可得到该模型的优劣。
实现代码
时间间隔序列格式化成所需的训练集格式
import pandas as pdimport numpy as npdef create_interval_dataset(dataset, look_back):   """    :param dataset: input array of time intervals    :param look_back: each training set feature length    :return: convert an array of values into a dataset matrix.    """   dataX, dataY = [], []    for i in range(len(dataset) - look_back):       dataX.append(dataset[i:i+look_back])       dataY.append(dataset[i+look_back])    return np.asarray(dataX), np.asarray(dataY)df = pd.read_csv("path-to-your-time-interval-file")    dataset_init = np.asarray(df)    # if only 1 columndataX, dataY = create_interval_dataset(dataset, lookback=3)    # look back if the training set sequence length这里的输入数据来源是csv文件,如果输入数据是来自数据库的话可以参考这里
LSTM网络结构搭建
import pandas as pdimport numpy as npimport randomfrom keras.models import Sequential, model_from_jsonfrom keras.layers import Dense, LSTM, Dropoutclass NeuralNetwork():   def __init__(self, **kwargs):       """        :param **kwargs: output_dim=4: output dimension of LSTM layer; activation_lstm='tanh': activation function for LSTM layers; activation_dense='relu': activation function for Dense layer; activation_last='sigmoid': activation function for last layer; drop_out=0.2: fraction of input units to drop; np_epoch=10, the number of epoches to train the model. epoch is one forward pass and one backward pass of all the training examples; batch_size=32: number of samples per gradient update. The higher the batch size, the more memory space you'll need; loss='mean_square_error': loss function; optimizer='rmsprop'        """       self.output_dim = kwargs.get('output_dim', 8)        self.activation_lstm = kwargs.get('activation_lstm', 'relu')        self.activation_dense = kwargs.get('activation_dense', 'relu')        self.activation_last = kwargs.get('activation_last', 'softmax')    # softmax for multiple output       self.dense_layer = kwargs.get('dense_layer', 2)     # at least 2 layers       self.lstm_layer = kwargs.get('lstm_layer', 2)        self.drop_out = kwargs.get('drop_out', 0.2)        self.nb_epoch = kwargs.get('nb_epoch', 10)        self.batch_size = kwargs.get('batch_size', 100)        self.loss = kwargs.get('loss', 'categorical_crossentropy')        self.optimizer = kwargs.get('optimizer', 'rmsprop')        def NN_model(self, trainX, trainY, testX, testY):       """        :param trainX: training data set        :param trainY: expect value of training data        :param testX: test data set        :param testY: epect value of test data        :return: model after training        """       print "Training model is LSTM network!"       input_dim = trainX[1].shape[1]       output_dim = trainY.shape[1] # one-hot label       # print predefined parameters of current model:       model = Sequential()        # applying a LSTM layer with x dim output and y dim input. Use dropout parameter to avoid overfitting       model.add(LSTM(output_dim=self.output_dim,                      input_dim=input_dim,                      activation=self.activation_lstm,                      dropout_U=self.drop_out,                      return_sequences=True))        for i in range(self.lstm_layer-2):           model.add(LSTM(output_dim=self.output_dim,                      input_dim=self.output_dim,                      activation=self.activation_lstm,                      dropout_U=self.drop_out,                      return_sequences=True))        # argument return_sequences should be false in last lstm layer to avoid input dimension incompatibility with dense layer       model.add(LSTM(output_dim=self.output_dim,                      input_dim=self.output_dim,                      activation=self.activation_lstm,                      dropout_U=self.drop_out))        for i in range(self.dense_layer-1):           model.add(Dense(output_dim=self.output_dim,                       activation=self.activation_last))       model.add(Dense(output_dim=output_dim,                       input_dim=self.output_dim,                       activation=self.activation_last))        # configure the learning process       model.compile(loss=self.loss, optimizer=self.optimizer, metrics=['accuracy'])        # train the model with fixed number of epoches       model.fit(x=trainX, y=trainY, nb_epoch=self.nb_epoch, batch_size=self.batch_size, validation_data=(testX, testY))        # store model to json file       model_json = model.to_json()        with open(model_path, "w") as json_file:           json_file.write(model_json)        # store model weights to hdf5 file       if model_weight_path:            if os.path.exists(model_weight_path):               os.remove(model_weight_path)           model.save_weights(model_weight_path) # eg: model_weight.h5       return model这里写的只涉及LSTM网络的结构搭建,至于如何把数据处理规范化成网络所需的结构以及把模型预测结果与实际值比较统计的可视化,就需要根据实际情况做调整了。

如何在Python中用LSTM网络进行时间序列预测

4. 如何用Python进行线性回归以及误差分析

数据挖掘中的预测问题通常分为2类:回归与分类。
简单的说回归就是预测数值,而分类是给数据打上标签归类。
本文讲述如何用Python进行基本的数据拟合,以及如何对拟合结果的误差进行分析。
本例中使用一个2次函数加上随机的扰动来生成500个点,然后尝试用1、2、100次方的多项式对该数据进行拟合。
拟合的目的是使得根据训练数据能够拟合出一个多项式函数,这个函数能够很好的拟合现有数据,并且能对未知的数据进行预测。
代码如下:
importmatplotlib.pyplot as plt
importnumpy as np
importscipy as sp
fromscipy.stats importnorm
fromsklearn.pipeline importPipeline
fromsklearn.linear_model importLinearRegression
fromsklearn.preprocessing importPolynomialFeatures
fromsklearn importlinear_model
''''' 数据生成 '''
x = np.arange(0, 1, 0.002)
y = norm.rvs(0, size=500, scale=0.1)
y = y + x**2
''''' 均方误差根 '''
defrmse(y_test, y):
returnsp.sqrt(sp.mean((y_test - y) ** 2))
''''' 与均值相比的优秀程度,介于[0~1]。0表示不如均值。1表示完美预测.这个版本的实现是参考scikit-learn官网文档 '''
defR2(y_test, y_true):
return1- ((y_test - y_true)**2).sum() / ((y_true - y_true.mean())**2).sum()
''''' 这是Conway&White《机器学习使用案例解析》里的版本 '''
defR22(y_test, y_true):
y_mean = np.array(y_true)
y_mean[:] = y_mean.mean()
return1- rmse(y_test, y_true) / rmse(y_mean, y_true)
plt.scatter(x, y, s=5)
degree = [1,2,100]
y_test = []
y_test = np.array(y_test)
ford indegree:
clf = Pipeline([('poly', PolynomialFeatures(degree=d)),
('linear', LinearRegression(fit_intercept=False))])
clf.fit(x[:, np.newaxis], y)
y_test = clf.predict(x[:, np.newaxis])
print(clf.named_steps['linear'].coef_)
print('rmse=%.2f, R2=%.2f, R22=%.2f, clf.score=%.2f'%
(rmse(y_test, y),
R2(y_test, y),
R22(y_test, y),
clf.score(x[:, np.newaxis], y)))
plt.plot(x, y_test, linewidth=2)
plt.grid()
plt.legend(['1','2','100'], loc='upper left')
plt.show()
该程序运行的显示结果如下:

[-0.16140183 0.99268453]
rmse=0.13, R2=0.82, R22=0.58, clf.score=0.82
[ 0.00934527 -0.03591245 1.03065829]
rmse=0.11, R2=0.88, R22=0.66, clf.score=0.88
[ 6.07130354e-02 -1.02247150e+00 6.66972089e+01 -1.85696012e+04
......
-9.43408707e+12 -9.78954604e+12 -9.99872105e+12 -1.00742526e+13
-1.00303296e+13 -9.88198843e+12 -9.64452002e+12 -9.33298267e+12
-1.00580760e+12]
rmse=0.10, R2=0.89, R22=0.67, clf.score=0.89
显示出的coef_就是多项式参数。如1次拟合的结果为
y = 0.99268453x -0.16140183
这里我们要注意这几点:
1、误差分析。
做回归分析,常用的误差主要有均方误差根(RMSE)和R-平方(R2)。
RMSE是预测值与真实值的误差平方根的均值。这种度量方法很流行(Netflix机器学习比赛的评价方法),是一种定量的权衡方法。
R2方法是将预测值跟只使用均值的情况下相比,看能好多少。其区间通常在(0,1)之间。0表示还不如什么都不预测,直接取均值的情况,而1表示所有预测跟真实结果完美匹配的情况。
R2的计算方法,不同的文献稍微有不同。如本文中函数R2是依据scikit-learn官网文档实现的,跟clf.score函数结果一致。
而R22函数的实现来自Conway的著作《机器学习使用案例解析》,不同在于他用的是2个RMSE的比值来计算R2。
我们看到多项式次数为1的时候,虽然拟合的不太好,R2也能达到0.82。2次多项式提高到了0.88。而次数提高到100次,R2也只提高到了0.89。
2、过拟合。
使用100次方多项式做拟合,效果确实是高了一些,然而该模型的据测能力却极其差劲。
而且注意看多项式系数,出现了大量的大数值,甚至达到10的12次方。
这里我们修改代码,将500个样本中的最后2个从训练集中移除。然而在测试中却仍然测试所有500个样本。
clf.fit(x[:498, np.newaxis], y[:498])
这样修改后的多项式拟合结果如下:

[-0.17933531 1.0052037 ]
rmse=0.12, R2=0.85, R22=0.61, clf.score=0.85
[-0.01631935 0.01922011 0.99193521]
rmse=0.10, R2=0.90, R22=0.69, clf.score=0.90
...
rmse=0.21, R2=0.57, R22=0.34, clf.score=0.57
仅仅只是缺少了最后2个训练样本,红线(100次方多项式拟合结果)的预测发生了剧烈的偏差,R2也急剧下降到0.57。
而反观1,2次多项式的拟合结果,R2反而略微上升了。
这说明高次多项式过度拟合了训练数据,包括其中大量的噪音,导致其完全丧失了对数据趋势的预测能力。前面也看到,100次多项式拟合出的系数数值无比巨大。人们自然想到通过在拟合过程中限制这些系数数值的大小来避免生成这种畸形的拟合函数。
其基本原理是将拟合多项式的所有系数绝对值之和(L1正则化)或者平方和(L2正则化)加入到惩罚模型中,并指定一个惩罚力度因子w,来避免产生这种畸形系数。
这样的思想应用在了岭(Ridge)回归(使用L2正则化)、Lasso法(使用L1正则化)、弹性网(Elastic net,使用L1+L2正则化)等方法中,都能有效避免过拟合。
下面以岭回归为例看看100次多项式的拟合是否有效。将代码修改如下:
clf = Pipeline([('poly', PolynomialFeatures(degree=d)),
('linear', linear_model.Ridge())])
clf.fit(x[:400, np.newaxis], y[:400])
结果如下:

[ 0. 0.75873781]
rmse=0.15, R2=0.78, R22=0.53, clf.score=0.78
[ 0. 0.35936882 0.52392172]
rmse=0.11, R2=0.87, R22=0.64, clf.score=0.87
[ 0.00000000e+00 2.63903249e-01 3.14973328e-01 2.43389461e-01
1.67075328e-01 1.10674280e-01 7.30672237e-02 4.88605804e-02
......
3.70018540e-11 2.93631291e-11 2.32992690e-11 1.84860002e-11
1.46657377e-11]
rmse=0.10, R2=0.90, R22=0.68, clf.score=0.90

5. 线性回归可以看作一个神经网络吗

可以的,都输入输出,线性回归有确切模型出来,神经网络不一定有确切模型

线性回归可以看作一个神经网络吗

6. python 线性回归 样本外效果预测

看起来你可能在做股票方面的回测。
你自己写个函数比较预测值和样本外的实际值的偏差不行吗?应该比较方便吧

7. 想做预测数据,希望通过算法来得到结果。有可能需要matlab或者python的机器学习(machine learning)等

你想通过训练来预测数据,一般可以通过BP人工神经网络来实现。


人工神经网络是由若干个神经元相互连接组成一个比较大的并行互联的网络,其结构为拓扑结构。
实现步骤:1、输入和输出数据;2、创建网络;3、划分训练,测试和验证数据的比例设定;4、训练网络;5、根据训练结果,预测未来数据
下图为用BP神经网络预测某地铁线路(14月至17月)客流量图


想做预测数据,希望通过算法来得到结果。有可能需要matlab或者python的机器学习(machine learning)等

8. 如何用python实现含有虚拟自变量的回归

利用python进行线性回归
理解什么是线性回归
线性回归也被称为最小二乘法回归(Linear Regression, also called Ordinary Least-Squares (OLS) Regression)。它的数学模型是这样的:
y = a+ b* x+e
其中,a 被称为常数项或截距;b 被称为模型的回归系数或斜率;e 为误差项。a 和 b 是模型的参数。
当然,模型的参数只能从样本数据中估计出来:
y'= a' + b'* x
我们的目标是选择合适的参数,让这一线性模型最好地拟合观测值。拟合程度越高,模型越好。那么,接下来的问题就是,我们如何判断拟合的质量呢?
这一线性模型可以用二维平面上的一条直线来表示,被称为回归线。

模型的拟合程度越高,也即意味着样本点围绕回归线越紧密。
如何计算样本点与回归线之间的紧密程度呢?
高斯和勒让德找到的方法是:被选择的参数,应该使算出来的回归线与观测值之差的平房和最小。用函数表示为:
这被称为最小二乘法。最小二乘法的原理是这样的:当预测值和实际值距离的平方和最小时,就选定模型中的两个参数(a 和 b)。这一模型并不一定反映解释变量和反应变量真实的关系。但它的计算成本低;相比复杂模型更容易解释。

模型估计出来后,我们要回答的问题是:我们的模型拟合程度如何?或者说,这个模型对因变量的解释力如何?(R2)
整个模型是否能显著预测因变量的变化?(F 检验)
每个自变量是否能显著预测因变量的变化?(t 检验)
首先回答第一个问题。为了评估模型的拟合程度如何,我们必须有一个可以比较的基线模型。
如果让你预测一个人的体重是多少?在没有任何额外信息的情况下,你可能会用平均值来预测,尽管会存在一定误差,但总比瞎猜好。
现在,如果你知道他的身高信息,你的预测值肯定与平均值不一样。额外信息相比平均值更能准确地预测被预测的变量的能力,就代表模型的解释力大小。

上图中,SSA 代表由自变量 x 引起的 y 的离差平方和,即回归平方和,代表回归模型的解释力;SSE 代表由随机因素引起的 y 的离差平方和,即剩余平方和,代表回归模型未能解释的部分;SST 为总的离差平方和,即我们仅凭 y 的平均值去估计 y 时所产生的误差。
用模型能够解释的变异除以总的变异就是模型的拟合程度:R2=SSA/SST=1-SSE
R2(R 的平方)也被称为决定系数或判定系数。
第二个问题,我们的模型是否显著预测了 y 的变化?
假设 y 与 x 的线性关系不明显,那么 SSA 相对 SSE 占有较大的比例的概率则越小。换句话说,在 y 与 x 无线性关系的前提下,SSA 相对 SSE 的占比越高的概率是越小的,这会呈现一定的概率分布。统计学家告诉我们它满足 F 分布,就像这样:

如果 SSA 相对 SSE 占比较大的情况出现了,比如根据 F 分布,这个值出现的概率小于 5%。那么,我们最好是拒绝 y 与 x 线性关系不显著的原始假设,认为二者存在显著的线性关系较为合适。
第三个问题,每个自变量是否能显著预测因变量的变化?换句话说,回归系数是否显著?
回归系数的显著性检验是围绕回归系数的抽样分布(t 分布)来进行的,推断过程类似于整个模型的检验过程,不赘言。
实际上,对于只有一个自变量的一元线性模型,模型的显著性检验和回归系数的检验是一致的,但对于多元线性模型来说,二者就不能等价了。
利用 statsmodels 进行最小二乘回归
#导入相应模块
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: import statsmodels.api as sm
#将数据导入 pandas 的 dataframe 对象,第一列(年份)作为行标签
In [4]: df=pd.read_csv('/Users/xiangzhendong/Downloads/vincentarelbundock-Rdatasets-1218370/csv/datasets/longley.csv', index_col=0)#查看头部数据In [5]: df.head()
Out[5]:
GNP.deflator      GNP  Unemployed  Armed.Forces  Population  Year  \
1947          83.0  234.289       235.6         159.0     107.608  1947
1948          88.5  259.426       232.5         145.6     108.632  1948
1949          88.2  258.054       368.2         161.6     109.773  1949
1950          89.5  284.599       335.1         165.0     110.929  1950
1951          96.2  328.975       209.9         309.9     112.075  1951
Employed
1947    60.323
1948    61.122
1949    60.171
1950    61.187
1951    63.221
#设置预测变量和结果变量,用 GNP 预测 Employed
In [6]: y=df.Employed #结果变量
In [7]: X=df.GNP #预测变量#为模型增加常数项,即回归线在 y 轴上的截距In [8]: X=sm.add_constant(X)
#执行最小二乘回归,X 可以是 numpy array 或 pandas dataframe(行数等于数据点个数,列数为预测变量个数),y 可以是一维数组(numpy array)或 pandas series
In [10]: est=sm.OLS(y,X)
使用 OLS 对象的 fit() 方法来进行模型拟合
In [11]: est=est.fit()#查看模型拟合的结果In [12]: est.summary()
Out[12]:

#查看最终模型的参数In [13]: est.params
Out[13]:
const    51.843590
GNP       0.034752
dtype: float64
#选择 100 个从最小值到最大值平均分布(equally spaced)的数据点
In [14]: X_prime=np.linspace(X.GNP.min(), X.GNP.max(),100)[:,np.newaxis]
In [15]: X_prime=sm.add_constant(X_prime)
#计算预测值
In [16]: y_hat=est.predict(X_prime)
In [17]: plt.scatter(X.GNP, y, alpha=0.3) #画出原始数据#分别给 x 轴和 y 轴命名
In [18]: plt.xlabel("Gross National Product")
In [19]: plt.ylabel("Total Employment")
In [20]: plt.plot(X_prime[:,1], y_hat, 'r', alpha=0.9) #添加回归线,红色

多元线性回归(预测变量不止一个)
我们用一条直线来描述一元线性模型中预测变量和结果变量的关系,而在多元回归中,我们将用一个多维(p)空间来拟合多个预测变量。下面表现了两个预测变量的三维图形:商品的销量以及在电视和广播两种不同媒介的广告预算。

数学模型是:
Sales = beta_0 + beta_1*TV + beta_2*Radio
图中,白色的数据点是平面上的点,黑色的数据点事平面下的点。平面的颜色是由对应的商品销量的高低决定的,高是红色,低是蓝色。
利用 statsmodels 进行多元线性回归
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: import statsmodels.api as sm
In [4]: df_adv=pd.read_csv('g.csv',index_col=0)
In [6]: X=df_adv[['TV','Radio']]
In [7]: y=df_adv['Sales']
In [8]: df_adv.head()
Out[8]:
TV  Radio  Newspaper  Sales
1  230.1   37.8       69.2   22.1
2   44.5   39.3       45.1   10.4
3   17.2   45.9       69.3    9.3
4  151.5   41.3       58.5   18.5
5  180.8   10.8       58.4   12.9
In [9]: X=sm.add_constant(X)
In [10]: est=sm.OLS(y,X).fit()
In [11]: est.summary()
Out[11]:

你也可以使用 statsmodels 的 formula 模块来建立多元回归模型
In [12]: import statsmodels.formula.api as smf
In [13]: est=smf.ols(formula='Sales ~ TV + Radio',data=df_adv).fit()
处理分类变量
性别或地域都属于分类变量。
In [15]: df= pd.read_csv('httd.edu/~tibs/ElemStatLearn/datasets/SAheart.data', index_col=0)
In [16]: X=df.copy()
利用 dataframe 的 pop 方法将 chd 列单独提取出来
In [17]: y=X.pop('chd')
In [18]: df.head()
Out[18]:
sbp  tobacco   ldl  adiposity  famhist  typea  obesity  alcohol  \
row.names
1          160    12.00  5.73      23.11  Present     49    25.30    97.20
2          144     0.01  4.41      28.61   Absent     55    28.87     2.06
3          118     0.08  3.48      32.28  Present     52    29.14     3.81
4          170     7.50  6.41      38.03  Present     51    31.99    24.26
5          134    13.60  3.50      27.78  Present     60    25.99    57.34
age  chd
row.names
1           52    1
2           63    1
3           46    0
4           58    1
5           49    1
In [19]: y.groupby(X.famhist).mean()
Out[19]:
famhist
Absent     0.237037
Present    0.500000
Name: chd, dtype: float64
In [20]: import statsmodels.formula.api as smf
In [21]: df['famhist_ord']=pd.Categorical(df.famhist).labels
In [22]: est=smf.ols(formula="chd ~ famhist_ord", data=df).fit()分类变量的编码方式有许多,其中一种编码方式是虚拟变量编码(dummy-encoding),就是把一个 k 个水平的分类变量编码成 k-1 个二分变量。在 statsmodels 中使用 C 函数实现。
In [24]: est=smf.ols(formula="chd ~ C(famhist)", data=df).fit()
In [26]: est.summary()
Out[26]:

处理交互作用
随着教育年限(education)的增长,薪酬 (wage) 会增加吗?这种影响对男性和女性而言是一样的吗?
这里的问题就涉及性别与教育年限的交互作用。
换言之,教育年限对薪酬的影响是男女有别的。
#导入相关模块
In [1]: import pandas as pd
In [2]: import numpy as np
In [4]: import statsmodels.api as sm
#导入数据,存入 dataframe 对象
In [5]: df=pd.read_csv('/Users/xiangzhendong/Downloads/pydatafromweb/wages.csv')
In [6]: df[['Wage','Education','Sex']].tail()
Out[6]:
Wage  Education  Sex
529  11.36         18    0
530   6.10         12    1
531  23.25         17    1
532  19.88         12    0
533  15.38         16    0
由于性别是一个二分变量,我们可以绘制两条回归线,一条是 sex=0(男性),一条是 sex=1(女性)
#绘制散点图
In [7]: plt.scatter(df.Education,df.Wage, alpha=0.3)
In [9]: plt.xlabel('education')
In [10]: plt.ylabel('wage')

#linspace 的作用是生成从最小到最大的均匀分布的 n 个数
In [17]: education_linspace=np.linspace(df.Education.min(), df.Education.max(),100)
In [12]: import statsmodels.formula.api as smf
In [13]: est=smf.ols(formula='Wage ~ Education + Sex', data=df).fit()
In [18]: plt.plot(education_linspace, est.params[0]+est.params[1]education_linspace+est.params[2]0, 'r')
In [19]: plt.plot(education_linspace, est.params[0]+est.params[1]education_linspace+est.params[2]1, 'g')

以上两条线是平行的。这是因为分类变量只影响回归线的截距,不影响斜率。
接下来我们可以为回归模型增加交互项来探索交互效应。也就是说,对于两个类别,回归线的斜率是不一样的。
In [32]: plt.scatter(df.Education,df.Wage, alpha=0.3)
In [33]: plt.xlabel('education')
In [34]: plt.ylabel('wage')
#使用*代表我们的回归模型中除了交互效应,也包括两个变量的主效应;如果只想看交互效应,可以用:代替,但通常不会只看交互效应
In [35]: est=smf.ols(formula='Wage ~ Sex*Education', data=df).fit()
In [36]: plt.plot(education_linspace, est.params[0]+est.params[1]0+est.params[2]education_linspace+est.params[3]0education_linspace, 'r')
In [37]: plt.plot(education_linspace, est.params[0]+est.params[1]1+est.params[2]education_linspace+est.params[3]1education_linspace, 'g')

参考资料:DataRobot | Ordinary Least Squares in Python
DataRoboe | Multiple Regression using Statsmodels
AnalyticsVidhya | 7 Types of Regression Techniques you should know!

最新文章
热门文章
推荐阅读