线性回归

线性模型形式简单、易于建模,但却蕴含着机器学习中一些重要的基本思想。许多功能更为强大的非线性模型都可在线性模型的基础上引入层级结构或高维映射得到。

基本形式

给定由d个属性描述的示例x=(x1; x2;...;xd),其中xix是第i个属性上的取值,线性模型试图学得一个通过属性的线性组合来进行预测的函数,即f(x)=w1x1+w2x2+...wdxd+b,一般用向量形式写成f(x)=wTx+b,w和b学得之后模型就得以确定

线性回归

下面我们用一个预测房价的例子来说明。

选择合适模型

横轴为房屋大学,纵轴为房屋出售的价格。由上述可知,w1和w0是需要学得的参数。不同的参数会拟合成不同的直线。我们需要的是一条成本最小的直线,通常用RSS残差平方和来表示。

那如果我们用更高阶的函数来拟合这个数据呢?


二次函数

高阶函数

我们可以看到二次函数的RSS比一次稍好些,更高阶的函数则可以完全拟合给出的点,但是这种情况明显是不好的,因为过拟合了,太符合样本的特征了。

那如何来选择合适模型呢?如果给出的数据足够大,可以用下面方法取得更好的结果。



这其实就是我们通常用到的训练集和测试集。常用的方法有留出法、交叉验证法、自助法。这个在之前的文章中提到过,就不再赘述。
训练误差、测试误差和模型复杂度之间的关系
QQ截图20171109054124.png

当然这只是一个参数的情况,实际的情况肯定是多个参数。

整体流程

实际案例分析

读取数据集
import pandas as pd
df = pd.read_csv('house_data.csv')
df.head()
可视化房屋数据集的特征
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context = 'notebook')
# 人口百分比,房屋建造时间,据市中心距离,犯罪率,房屋价格,税,房间数
cols = ['LSTAT', 'AGE', 'DIS', 'CRIM', 'MEDV', 'TAX', 'RM']
sns.pairplot(df[cols], size=2.5)
plt.show()


由此我们可以看出,房价和人口百分比成反比,与房间数成正比

通过梯度下降法计算回归参数,实现线性回归模型

关于梯度下降可以参看这篇文章

import numpy as np
class LinearRegressionByMyself(object):
    def __init__(self, Learn_rate=0.001, epoch=20):
        self.Learning_rate = Learn_rate
        self.epoch = epoch
        
    #训练方法
    def fit(self, X, y):
        #初始化参数
        self.w = np.zeros(1+X.shape[1])
        #误差
        self.cost_list = []
        
        for i in range(self.epoch):
            #将X数据集带入回归公式
            output = self.Regression_input(X)
            error = y - output
            self.w[1:] += self.Learning_rate * X.T.dot(error)
            self.w[0] += self.Learning_rate * error.sum()
            cost = (error**2).sum() / 2.0
            self.cost_list.append(cost)
        return self
    
    def Regression_input(self, X):
        return np.dot(X, self.w[1:])+self.w[0]
    
    def predict(self, X):
        return self.Regression_input(X)

此时需要的两个参数为X,y。X为一个二维数组,y是一个一维数组

X = df[['LSTAT']].values
y = df['MEDV'].values

在构造回归模型之前,先观察数据,发现数据相差比较大,这会对结果造成误差。我们用Scikie-learn里面的方法来实现归一化

from sklearn.preprocessing import StandardScaler
StandardScaler_x = StandardScaler()
StandardScaler_y = StandardScaler()
X_Standard = StandardScaler_x.fit_transform(X)
y_Standard = StandardScaler_y.fit_transform(y)

训练模型,拟合数据

model = LinearRegressionByMyself()
model.fit(X_Standard, y_Standard)

观察误差

plt.plot(range(1, model.epoch+1), model.cost_list)
plt.ylabel('SSE')
plt.xlabel('Epoch')
plt.show()
画出拟合图像
def Regression_plot(X, y, model):
    plt.scatter(X, y, c='blue')
    plt.plot(X, model.predict(X), color='red')
    return None

Regression_plot(X_Standard, y_Standard, model)
plt.xlabel('Percentage of the population')
plt.ylabel('House price')
plt.show()
使用sklearn实现线性回归模型
from sklearn.linear_model import LinearRegression
sk_model = LinearRegression()
sk_model.fit(X, y)
print('Slope: %.3f' % sk_model.coef_[0])
print('Inercept: %.3f' % sk_model.intercept_)
Regression_plot(X, y, sk_model)
plt.xlabel('Percentage of the population')
plt.ylabel('House price')
plt.show()
评估线性回归模型
from sklearn.cross_validation import train_test_split
cols = ['LSTAT', 'AGE', 'DIS', 'CRIM', 'TAX', 'RM']
X = df[cols].values
y = df['MEDV'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
sk_model = LinearRegression()
sk_model.fit(X_train, y_train)
y_train_predict = sk_model.predict(X_train)
y_test_predict = sk_model.predict(X_test)
plt.scatter(y_train_predict, y_train_predict - y_train, c='red', marker='x', label='Training data')
plt.scatter(y_test_predict, y_test_predict - y_test, c='black', marker='o', label='Test data')
plt.xlabel('Predicted values')
plt.ylabel('Residuals')
plt.legend(loc='upper left')
plt.hlines(y=0, xmin=-10, xmax=50, lw=1, color='green')
plt.xlim([-10, 50])
plt.show()

预测值和训练值残差关系图


均方误差与R2评分
from sklearn.metrics import mean_squared_error
print('MSE train %.3f, test %.3f' % (
    mean_squared_error(y_train, y_train_predict),
    mean_squared_error(y_test, y_test_predict)))#MSE train 25.106, test 36.671
from sklearn.metrics import r2_score
print('R^2 train %.3f, test %.3f' % (
    r2_score(y_train, y_train_predict),
    r2_score(y_test, y_test_predict)))#R^2 train 0.706, test 0.551,

R2越接近1,效果越好

多项式回归

X = df[['RM']].values
y = df['MEDV'].values
Regression_model = LinearRegression()
from sklearn.preprocessing import PolynomialFeatures
quadratic = PolynomialFeatures(degree=2)
cubic = PolynomialFeatures(degree=3)
X_squared = quadratic.fit_transform(X)
X_cubic = cubic.fit_transform(X)
X_fit = np.arange(X.min(), X.max(), 0.01)[: , np.newaxis]
Linear_model = Regression_model.fit(X, y)
#拟合线性
y_line_fit = Linear_model.predict(X_fit)
linear_r2 = r2_score(y, Linear_model.predict(X))
#二次模型,先二次变换再线性回归
Squared_model = Regression_model.fit(X_squared, y)
y_quad_fit = Squared_model.predict(quadratic.fit_transform(X_fit))
quadratic_r2 = r2_score(y, Squared_model.predict(X_squared))
#三次模型
Cubic_model = Regression_model.fit(X_cubic, y)
y_cubic_fit = Cubic_model.predict(cubic.fit_transform(X_fit))
cubic_r2 = r2_score(y, Cubic_model.predict(X_cubic))
#画图
plt.scatter(X, y, label='Training point', color='lightgray')
plt.plot(X_fit, y_line_fit, label='linear, $R^2=%.2f$' % linear_r2, color='blue', lw=2, linestyle=':')
plt.plot(X_fit, y_quad_fit, label='quadratic, $R^2=%.2f$' % quadratic_r2, color='red', lw=2, linestyle='-')
plt.plot(X_fit, y_cubic_fit, label='cubic, $R^2=%.2f$' % cubic_r2, color='green', lw=2, linestyle='--')
plt.xlabel('Room number')
plt.ylabel('House price')
plt.legend(loc='upper left')
plt.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容