您的位置:首页 > 其它

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

2018-03-31 11:03 381 查看

目录

1、最小二乘法

1.1 原理推导

1.2 代码样例

2、SKlearn

2.1 代码样例

2.2 多项式扩展

2.3 正则化

2.4 逻辑回归和多酚类

1、最小二乘法解

1.1 算法原理

回归算法推导

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

θ=(XTX)−1XTYθ=(XTX)−1XTY

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,
4000
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θ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 多项式扩展

一般比较少用,计算复杂度比较大,一般会用高斯函数映射。

含义:找特征之间的关系和多次的关系。

例如:(x1,x2,x3)(x1,x2,x3)进行2次项扩展变成:

(x1,x2,x3,x1x2,x1x3,x2x3,x21,x32,x23)(x1,x2,x3,x1x2,x1x3,x2x3,x12,x23,x32)

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

# 多项式扩展包
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]¶
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  机器学习实战