线性回归---梯度下降、最小二乘法、Ridge回归(岭回归)(L2 norm)、LASSO回归(L1 norm)

 参考:机器学习经典算法详解及Python实现--线性回归(Linear Regression)算法

 

1、梯度下降

 

步长越小,越容易收敛,但迭代速度越慢

# 二维原始图像
def f2(x, y):
    return 0.6 * (x + y) ** 2 - x * y
# 导函数
def hx2(x, y):
    return 0.6 * 2 * (x + y) - y
def hy2(x, y):
    return 0.6 * 2 * (x + y) - x

# 使用梯度下降法求解
GD_X1 = []
GD_X2 = []
GD_Y = []
x1 = 4
x2 = 4
alpha = 0.5
f_change = f2(x1, x2)
f_current = f_change
GD_X1.append(x1)
GD_X2.append(x2)
GD_Y.append(f_current)
iter_num = 0
while f_change > 1e-10 and iter_num < 100:
    iter_num += 1
    prex1 = x1
    prex2 = x2
    x1 = x1 - alpha * hx2(prex1, prex2)
    x2 = x2 - alpha * hy2(prex1, prex2)
    
    tmp = f2(x1, x2)
    f_change = np.abs(f_current - tmp)
    f_current  = tmp
    GD_X1.append(x1)
    GD_X2.append(x2)
    GD_Y.append(f_current)
print(u"最终结果为:(%.5f, %.5f, %.5f)" % (x1, x2, f_current))
print(u"迭代过程中X的取值,迭代次数:%d" % iter_num)
print(GD_X1)


# 构建数据
X1 = np.arange(-4, 4.5, 0.2)
X2 = np.arange(-4, 4.5, 0.2)
X1, X2 = np.meshgrid(X1, X2)
Y = np.array(list(map(lambda t: f2(t[0], t[1]), zip(X1.flatten(), X2.flatten()))))
Y.shape = X1.shape


# 画图
fig = plt.figure(facecolor='w')
ax = Axes3D(fig)
ax.plot_surface(X1, X2, Y, rstride=1, cstride=1, cmap=plt.cm.rainbow)
ax.plot(GD_X1, GD_X2, GD_Y, 'ro--')

ax.set_title(u'函数$y=0.6 * (θ1 + θ2)^2 - θ1 * θ2$;\n学习率:%.3f; 最终解:(%.3f, %.3f, %.3f);迭代次数:%d' % (alpha, x1, x2, f_current, iter_num))
plt.show()

 

2、最小二乘法

最小二乘法是概率密度是高斯分布的最大似然估计的状况。

 

 

 

标量的转置等于 标量本身

# 引入所需要的全部包
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='data/household_power_consumption_1000.txt'
df = pd.read_csv(path1, sep=';', low_memory=False)#没有混合类型的时候可以通过low_memory=F调用更多内存,加快效率)

## 功率和电流之间的关系
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)

# 对测试集合进行测试
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.1 补充知识点:

矩阵、向量的求导公式推导(参考链接:矩阵求导公式的数学推导(矩阵求导——基础篇)):

记住几个公式:

2.1.1 向量求导:

2.1.2 矩阵求导:

 

 

3、 多项式拓展(解决欠拟合问题) ---特征工程的一种操作

将特征与特征之间融合形成新的特征,从数学上来讲,就是将低维空间转换到高维空间,从而低维空间中非线性关系的变量,找到在高维空间中的线性关系。

python: PolynomialFeatures() 

# 引入所需要的全部包
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline

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

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

# 加载数据
path = 'data/household_power_consumption_200.txt' ## 200行数据
path = 'data/household_power_consumption_1000.txt' ## 1000行数据
df = pd.read_csv(path, sep=';', low_memory=False)

# 日期、时间、有功功率、无功功率、电压、电流、厨房用电功率、洗衣服用电功率、热水器用电功率
names2=df.columns
names=['Date', 'Time', 'Global_active_power', 'Global_reactive_power', 'Voltage', 'Global_intensity', 'Sub_metering_1', 'Sub_metering_2', 'Sub_metering_3']

# 异常数据处理(异常数据过滤)
new_df = df.replace('?', np.nan)
datas = new_df.dropna(axis=0,how = 'any') # 只要有数据为空,就进行删除操作

## 创建一个时间字符串格式化字符串
def date_format(dt):
    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和y变量, 并将时间转换为数值型连续变量
X = datas[names[0:2]]
X = X.apply(lambda x: pd.Series(date_format(x)), axis=1)
Y = datas[names[4]]

# 对数据集进行测试集合训练集划分
X_train,X_test,Y_train,Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)

# 数据标准化
ss = StandardScaler()
X_train = ss.fit_transform(X_train) # 训练并转换
X_test = ss.transform(X_test) ## 直接使用在模型构建数据上进行一个数据标准化操作 

# 模型训练
t=np.arange(len(X_test))  #画图用
N = 6  
d_pool = np.arange(1,N,1) # 阶
fig=plt.figure(figsize=(16,8), facecolor='w')#创建一个绘图窗口,设置大小,设置颜色
for i,d in enumerate(d_pool):
    fig.add_subplot(N-1,1,i+1)
    plt.plot(t, Y_test, 'b-', label='真实值',  alpha=0.75,ms=10, zorder=N)  #画出真实值
    model.set_params(Poly__degree=d) ## 设置多项式的阶乘
    model.fit(X_train, Y_train) # 模型训练
    lin = model.get_params()['Linear']
    print ('%d阶,模型的系数(θ):' % d ,lin.coef_)
    print("模型的截距:", lin.intercept_)

    # 模型结果预测
    y_hat = model.predict(X_test)  # 计算评估值
    # 计算模型训练得到的相关参数
    s_test = model.score(X_test, Y_test)
#     s_train = model.score(X_train, Y_train)
#     MSE = np.average((y_hat-Y_test)**2)   #均方差、方差 
#     RMSE = np.sqrt(MSE)   #均方根、标准差
    
     #画出预测值
    label = '%d阶, 测试集准确率=%.3f' % (d,s_test)
    plt.plot(t, y_hat, 'r--', label=label, zorder=N+1)
    plt.legend(loc = 'lower left')
    plt.grid(True)
    plt.ylabel(u'%d阶结果' % d, fontsize=12)
    
plt.suptitle("线性回归预测时间和功率之间的多项式关系", fontsize=20)
plt.grid(b=True)
plt.show()

4、正则项(解决过拟合问题)

如果模型在训练集效果好,测试集效果不好,则认为存在过拟合的情况。多项式拓展阶数过高可能导致过拟合。从线性回归模型中,训练出来的模型参数越大,就表示越存在过拟合的情况。

损失函数;J(theta)由两部分组成:y预测值误差+模型复杂度误差

4.1 Ridge回归(岭回归)(L2 norm)

4.2 LASSO回归(L1 norm)

 

Scikit-learn中,性能评估所用的score到底是个什么意思(附Python实例)? 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值