机器学习案例--回归分析

目录

  • 1、最小二乘法
    • 1.1 原理推导
    • 1.2 代码样例
  • 2、SKlearn
    • 2.1 代码样例
    • 2.2 多项式扩展
    • 2.3 正则化
    • 2.4 逻辑回归和多酚类

1、最小二乘法解

1.1 算法原理

回归算法推导
根据中心极限定理,误差服从正态分布,将误差带入之后用极大似然估计,取对数得到目标函数,目标函数是最小二乘的形式,求导得出的解是:

θ = ( X T X ) 1 X T Y

1.2 样例

数据集下载:
http://archive.ics.uci.edu/ml/datasets/Individual+household+electric+power+consumption
处理代码:

# 引入所需要的全部包
from sklearn.model_selection import train_test_split # 数据划分的类

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
from pandas import DataFrame
import time

## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False

# 加载数据
# 日期、时间、有功功率、无功功率、电压、电流、厨房用电功率、洗衣服用电功率、热水器用电功率
path1='datas/household_power_consumption_1000.txt'
df = pd.read_csv(path1, sep=';', low_memory=False)#没有混合类型的时候可以通过low_memory=F调用更多内存,加快效率)
#查看前两行数据
df.head(2)

这里写图片描述

## 通过active_power 和 reactive_power 预测intensity
X = df.iloc[:,2:4]
Y2 = df.iloc[:,5]

## 数据分割
X2_train,X2_test,Y2_train,Y2_test = train_test_split(X, Y2, test_size=0.2, random_state=0)

# 将X和Y转换为矩阵的形式
X = np.mat(X2_train)
Y = np.mat(Y2_train).reshape(-1,1)

# 计算θ
theta = (X.T * X).I * X.T * Y
print(theta)
#[[4.20324605]
# [1.36676171]]

# 对测试集合进行测试
y_hat = np.mat(X2_test) * theta

# 画图
#### 电流关系
t=np.arange(len(X2_test))
plt.figure(facecolor='w')
plt.plot(t, Y2_test, 'r-', linewidth=2, label=u'真实值')
plt.plot(t, y_hat, 'g-', linewidth=2, label=u'预测值')
plt.legend(loc = 'lower right')
plt.title(u"线性回归预测功率与电流之间的关系", fontsize=20)
plt.grid(b=True)
plt.show()

这里写图片描述

2 SKLearn 线性回归

class sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)[source]

  • 传入参数
    • fit_intercept: 是否要截距,也就是 θ 0
    • normalize:是否标准化
    • copy_X:是否复制训练集,不改变原数据
    • n_jobs:并行计算
  • 返回
    • coef_:各个特征前的系数 [ array, shape (n_features, ) or (n_targets, n_features) ]
    • intercept_:截距

2.1 例子:找时间和电压之间的关系

# 引入所需要的全部包
from sklearn.model_selection import train_test_split # 数据划分的类
from sklearn.linear_model import LinearRegression # 线性回归的类
from sklearn.preprocessing import StandardScaler # 数据标准化

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
from pandas import DataFrame
import time

## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False

## 创建一个时间函数格式化字符串
def date_format(dt):
    # dt显示是一个series/tuple;dt[0]是date,dt[1]是time
    import time
    t = time.strptime(' '.join(dt), '%d/%m/%Y %H:%M:%S')
    return (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)

X = datas.iloc[:,0:2]
X = X.apply(lambda x: pd.Series(date_format(x)), axis=1) #按行读取
Y = datas['Global_active_power']

#数据集划分
X_train,X_test,Y_train,Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)

#标准化操作,使各个变量的方差为1
ss = StandardScaler() # 模型对象创建
X_train = ss.fit_transform(X_train) # 训练模型并转换训练集
X_test = ss.transform(X_test) ## 直接使用在模型构建数据上进行一个数据标准化操作 (测试集)

## 模型训练
lr = LinearRegression(fit_intercept=True) # 模型对象构建
lr.fit(X_train, Y_train) ## 训练模型
## 模型校验
y_predict = lr.predict(X_test) ## 预测结果

print("训练集上R2:",lr.score(X_train, Y_train))
print("测试集上R2:",lr.score(X_test, Y_test))
mse = np.average((y_predict-Y_test)**2)
rmse = np.sqrt(mse)
print("rmse:",rmse)
#训练集上R2: 0.24409311805909026
#测试集上R2: 0.12551628513735869
#rmse: 1.1640923459736248

# 输出模型训练得到的相关参数
print("模型的系数(θ):", end="")
print(lr.coef_)
print("模型的截距:", end='')
print(lr.intercept_)

## 模型保存/持久化
# 在机器学习部署的时候,实际上其中一种方式就是将模型进行输出;另外一种方式就是直接将预测结果输出
# 模型输出一般是将模型输出到磁盘文件
from sklearn.externals import joblib

# 保存模型要求给定的文件所在的文件夹比较存在
joblib.dump(ss, "result/data_ss.model") ## 将标准化模型保存
joblib.dump(lr, "result/data_lr.model") ## 将模型保存

# 加载模型
ss3 = joblib.load("result/data_ss.model") ## 加载模型
lr3 = joblib.load("result/data_lr.model") ## 加载模型

# 使用加载的模型进行预测
data1 = [[2006, 12, 17, 12, 25, 0]]
data1 = ss3.transform(data1)
print(data1)
lr3.predict(data1)

## 预测值和实际值画图比较
t=np.arange(len(X_test))
plt.figure(facecolor='w')#建一个画布,facecolor是背景色
plt.plot(t, Y_test, 'r-', linewidth=2, label='真实值')
plt.plot(t, y_predict, 'g-', linewidth=2, label='预测值')
plt.legend(loc = 'upper left')#显示图例,设置图例的位置
plt.title("线性回归预测时间和功率之间的关系", fontsize=20)
plt.grid(b=True)#加网格
plt.show()

这里写图片描述
可以看到比较欠拟合,可以进行多项式扩充。

2.2 多项式扩展

一般比较少用,计算复杂度比较大,一般会用高斯函数映射。
含义:找特征之间的关系和多次的关系。
例如: ( x 1 , x 2 , x 3 ) 进行2次项扩展变成:
( x 1 , x 2 , x 3 , x 1 x 2 , x 1 x 3 , x 2 x 3 , x 1 2 , x 2 3 , x 3 2 )

继续上面的例子,加入多项式扩展,代码例子:

# 多项式扩展包
from sklearn.preprocessing import PolynomialFeatures
# pipeline可以让训练集进行一系列处理
# 即先扩展再放入线性回归之中
from sklearn.pipeline import Pipeline

models = [
    Pipeline([
            ('Poly', PolynomialFeatures()), # 给定进行多项式扩展操作, 第一个操作:多项式扩展
            ('Linear', LinearRegression(fit_intercept=False)) # 第二个操作,线性回归
        ])
]
model = models[0]

# 模型训练
t=np.arange(len(X_test))
N = 5
d_pool = np.arange(1,N,1) # 阶
m = d_pool.size
clrs = [] # 颜色
for c in np.linspace(16711680, 255, m):
    clrs.append('#%06x' % int(c))
line_width = 3

plt.figure(figsize=(12,6), facecolor='w')#创建一个绘图窗口,设置大小,设置颜色
for i,d in enumerate(d_pool):
    plt.subplot(N-1,1,i+1)
    plt.plot(t, Y_test, 'r-', label=u'真实值', ms=10, zorder=N)
    ### 设置管道对象中的参数值,Poly是在管道对象中定义的操作名称, 后面跟参数名称;中间是两个下划线
    model.set_params(Poly__degree=d) ## 设置多项式的阶乘
    model.fit(X_train, Y_train) # 模型训练
    # Linear是管道中定义的操作名称
    # 获取线性回归算法模型对象
    lin = model.get_params()['Linear']
    output = u'%d阶,系数为:' % d
    # 判断lin对象中是否有对应的属性
    if hasattr(lin, 'alpha_'):
        idx = output.find(u'系数')
        output = output[:idx] + (u'alpha=%.6f, ' % lin.alpha_) + output[idx:]
    if hasattr(lin, 'l1_ratio_'):
        idx = output.find(u'系数')
        output = output[:idx] + (u'l1_ratio=%.6f, ' % lin.l1_ratio_) + output[idx:]
    print (output, lin.coef_.ravel())

    # 模型结果预测
    y_hat = model.predict(X_test)
    # 计算评估值
    s = model.score(X_test, Y_test)

    # 画图
    z = N - 1 if (d == 2) else 0
    label = u'%d阶, 准确率=%.3f' % (d,s)
    plt.plot(t, y_hat, color=clrs[i], lw=line_width, alpha=0.75, label=label, zorder=z)
    plt.legend(loc = 'upper left')
    plt.grid(True)
    plt.ylabel(u'%d阶结果' % d, fontsize=12)

## 预测值和实际值画图比较
plt.suptitle(u"线性回归预测时间和功率之间的多项式关系", fontsize=20)
plt.grid(b=True)
plt.show()

这里写图片描述

可以看到随着阶数增多,拟合的情况会变好,但是会带来过拟合的问题,所以加入正则化,让参数不会过大。

2.3 正则化

from sklearn.linear_model import LinearRegression, LassoCV, RidgeCV, ElasticNetCV

三种方法:

正则化有三种 L1(Lasso), L2(RidgeCV), ElasticNet
L1: 能得到比较稀疏的解,训练速度快,但稳定性较差
L2: 稳定行比较好
Elastic: 综合前两项

models = [
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            ('Linear', LinearRegression(fit_intercept=False))
        ]),
#通过交叉验证确定参数,L2正则化。
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            # alpha给定的是Ridge算法中,L2正则项的权重值
            # alphas是给定CV交叉验证过程中,Ridge算法的alpha参数值的取值的范围
            ('Linear', RidgeCV(alphas=np.logspace(-3,2,50), fit_intercept=False))
        ]),
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            ('Linear', LassoCV(alphas=np.logspace(0,1,10), fit_intercept=False))
        ]),
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            # la_ratio:给定EN算法中L1正则项在整个惩罚项中的比例,这里给定的是一个列表;
            # 表示的是在CV交叉验证的过程中,EN算法L1正则项的权重比例的可选值的范围
            ('Linear', ElasticNetCV(alphas=np.logspace(0,1,10), l1_ratio=[.1, .5, .7, .9, .95, 1], fit_intercept=False))
        ])
]

2.4 逻辑回归与多项式回归

class sklearn.linear_model.LogisticRegressionCV(Cs=10, fit_intercept=True, cv=None, dual=False, penalty=’l2’, scoring=None, solver=’lbfgs’, tol=0.0001, max_iter=100, class_weight=None, n_jobs=1, verbose=0, refit=True, intercept_scaling=1.0, multi_class=’ovr’, random_state=None)[source]¶

猜你喜欢

转载自blog.csdn.net/xiayto/article/details/79766983