您的位置:首页 > 编程语言 > Python开发

机器学习:线性回归与Python代码实现

2017-09-28 14:38 916 查看
前言:本篇博文主要介绍线性回归模型(linear
regression),首先介绍相关的基础概念和原理,然后通过Python代码实现线性回归模型。特别强调,其中大多理论知识来源于《统计学习方法_李航》斯坦福课程翻译笔记以及Coursera机器学习课程

1.线性回归

回归模型(regression model)也叫做拟合模型,通俗点解释,就是假设我们有很多数据,包含房子的面积X和对应的房价y,那么我们希望得到房价y关于面积X的关系(h(X) = y),那么现在你知道一个房屋的面积Xi,基本就可以根据这个关系预测(推导)出房价yi了。

之所以叫做“线性回归”,因为我们假设y与X具有的是一种线性关系,称为假设函数:



其中参数w0称为“偏置”,w1称为“权重”,x表示输入变量X的一个“特征变量”,这里先假设只有一个特征变量。

Note:我这里用w代表theta,他的实际含义都是“weight”,建议相关的知识细节,到这里学习!!!

2.成本函数(cost function)

我们要知道,拟合的函数h(x)有一定的误差,我们用成本函数J来表示“预测输出”h(x)与实际输出y之间的误差。这里使用最简单的“最小均方”(Least mean square)来描述:



其中,m表示样本的数量,i表示第i个样本,其中的1/2,是为了求导方便而添加的专业习惯。

3.参数学习(梯度下降)

所以我们现在的目标是,找出怎么样的参数,使得假设函数预测得到的误差最小,也就是最小化成本函数J。



关于成本函数J的图像大致像一个“碗”(上),我们来看看J关于一个参数w1(其实应该是theta,代表权重参数)的图像(下):


   
     


所以按照一般的思路,就是对权重参数求导,使得倒数为0的参数的值,就是成本函数J取得最小值的地方。但是大多时候,求得的偏导的数学表达式很复杂,所以我们采用一种叫做“梯度下降(gradient descent)”的方法



也就是如下:



通俗一点讲,就是希望权重参数“沿着J减小的方向(梯度减小的方向),一步一步(也就是学习率alpha)的走到那个最低点”。细节不解释了,还是老地方讲的深入浅出。

4.线性回归模型Python代码实现

先看看数据集

from sklearn.datasets import load_diabetes
diabetes = load_diabetes()
print diabetes.keys()
data = diabetes.data #real -0.2<x<0.2
target = diabetes.target #integer 25<y<346
print data.shape
print target.shape
print data[:5]
print target[:5]
输入:



划分一下数据集,这里就不划分验证集了:

import numpy as np
#use only one feature
X = data[:,:1]
y = target
#X_train = np.array([[0], [1], [2]])
#X_test = np.array([[3], [4], [6]])
#y_train = np.array([0,1,2]).reshape(-1,1)
#y_test = np.array([3,4,5]).reshape(-1,1)
X_train = X[:-20]
X_test = X[-20:]
y_train = y[:-20].reshape((-1,1))
y_test = y[-20:].reshape((-1,1))
print 'X_train=',X_train.shape
print 'X_test=',X_test.shape
print 'y_train=',y_train.shape
print 'y_test=',y_test.shape


接下来完成线性回归模型的类的编写:

class linear(object):
def __init__(self):
self.W = None
self.b = None

def loss(self,X,y):
num_feature  = X.shape[1]
num_train = X.shape[0]

h = X.dot(self.W) + self.b
loss = 0.5 *np.sum(np.square(h - y)) / num_train

dW = X.T.dot((h-y)) / num_train
db = np.sum((h-y)) / num_train

return loss,dW,db

def train(self,X,y,learn_rate = 0.001,iters = 10000):
num_feature = X.shape[1]
self.W = np.zeros((num_feature,1))
self.b = 0
loss_list = []

for i in xrange(iters):
loss,dW,db = self.loss(X,y)
loss_list.append(loss)
self.W += -learn_rate*dW
self.b += -learn_rate*db

if i%500 == 0:
print 'iters = %d,loss = %f' % (i,loss)
return loss_list

def predict(self,X_test):
y_pred = X.dot(self.W) + self.b
return y_pred

pass


测试训练一下:

classify = linear()
print 'start'
loss_list = classify.train(X_train,y_train)
print 'end'

print classify.W,classify.b


最后可视化一下,训练的结果:

import matplotlib.pyplot as plt
f = X_train.dot(classify.W) + classify.b
fig = plt.figure()
plt.subplot(211)
plt.scatter(X_train,y_train,color = 'black')
plt.scatter(X_test,y_test,color = 'blue')
plt.plot(X_train,f,color = 'red')
plt.xlabel('X')
plt.ylabel('y')

plt.subplot(212)
plt.plot(loss_list,color = 'blue')
plt.xlabel('epochs')
plt.ylabel('errors')
plt.show()




可以看到,线性回归学习得到的直线使得样本数据均匀分布在两边,由于样本的复杂性,加上这里模型只选择一个特征,太简单(其实属于欠拟合,高偏差),所以拟合的不好,误差较大,但是基本的原理基本就是这样了。

ps:至于其他的一些细节:正则化、特征归一化、多项式特征等问题,等有空再上代码,毕竟一下子也说不清。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 机器学习 算法