Skr-Eric的机器学习课堂(二)-- 线性回归、梯度下降算法和岭回归

线性回归和梯度下降算法

根据机器学习的任务把不同的业务模型划分为四种基本问题:

回归问题 \ 在有监督条件下,根据已知的输入和输出,构建

分类问题 / 预测模型,对未知输出的输入给出大概率的输出

输入 输出

1      2

2      4

3      6

4      8

------- y = x * 2

5      ? -> 10

输出是一个连续值,回归问题。

输入 输出

1      1

2      0

3      1

4      0

5      1

6      0

------- 奇数->1,偶数->0

7      ? -> 1

输出是一个离散值,分类问题。

聚类问题:在无监督模式下,根据输入的特征划分族群。

降维问题:在无监督模式下,对输入特征进行取舍以降低维度。

输入  输出

x1     y1

x2     y2

...

xm    ym

----------

y = w0+w1x - 通过线性方程描述输出和输入之间的关系,已解决回归问题,这就是线性回归。

                        模型参数

                         /      \

预测函数:y = w0+w1x

x1 -> y1'=w0+w1x1      y1          (y1-y1')^2

x2 -> y2'=w0+w1x2      y2          (y2-y2')^2

...

xm->ym'=w0+w1xm    ym         (ym-ym')^2

            |                              |                   |

      预测输出                 实际输出     单样本误差

总样本误差:

(y1-y1')^2 + (y2-y2')^2 + ... + (ym-ym')^2

--------------------------------------------------- = E

                                    2

损失函数:E = Loss(w0, w1)

损失函数体现了总样本误差即损失值随着模型参数的变化而变化。回归问题的等价问题就是求损失函数的极小值,即是E达到极小值的w0和w1。

模型参数的迭代公式:

w0 = w0 - n DE/Dw0

w1 = w1 - n DE/Dw1

DE/Dw0 = 1/2 [2(y1-y1')(-1)  + 2(y2-y2')(-1) + ...]

                = -[(y1-y1') + (y2-y2') + ...]

DE/Dw1 = -[(y1-y1')x1 + (y2-y2')x2 + ...]

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as mp
from mpl_toolkits.mplot3d import axes3d
train_x = np.array([0.5, 0.6, 0.8, 1.1, 1.4])
train_y = np.array([5.0, 5.5, 6.0, 6.8, 7.0])
n_epoches = 1000
lrate = 0.01
epoches, losses = [], []
w0, w1 = [1], [1]
for epoch in range(1, n_epoches + 1):
    epoches.append(epoch)
    losses.append(((train_y - (
        w0[-1] + w1[-1] * train_x)) ** 2).sum() / 2)
    print('{:4}> w0={:.8f}, w1={:.8f}, loss={:.8f}'.format(
        epoches[-1], w0[-1], w1[-1], losses[-1]))
    d0 = -(train_y - (w0[-1] + w1[-1] * train_x)).sum()
    d1 = -((train_y - (w0[-1] + w1[-1] * train_x)) * train_x).sum()
    w0.append(w0[-1] - lrate * d0)
    w1.append(w1[-1] - lrate * d1)
w0 = np.array(w0[:-1])
w1 = np.array(w1[:-1])
sorted_indices = train_x.argsort()
test_x = train_x[sorted_indices]
test_y = train_y[sorted_indices]
pred_test_y = w0[-1] + w1[-1] * test_x
grid_w0, grid_w1 = np.meshgrid(
    np.linspace(0, 9, 500),
    np.linspace(0, 3.5, 500))
flat_w0, flat_w1 = grid_w0.ravel(), grid_w1.ravel()
flat_loss = ((flat_w0 + np.outer(
    train_x, flat_w1) - train_y.reshape(
    -1, 1)) ** 2).sum(axis=0) / 2
grid_loss = flat_loss.reshape(grid_w0.shape)
mp.figure('Linear Regression', facecolor='lightgray')
mp.title('Linear Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(train_x, train_y, marker='s',
           c='dodgerblue', alpha=0.5, s=80,
           label='Training')
mp.scatter(test_x, test_y, marker='D',
           c='orangered', alpha=0.5, s=60,
           label='Testing')
mp.scatter(test_x, pred_test_y,
           c='orangered', alpha=0.5, s=80,
           label='Predicted')
for x, y, pred_y in zip(test_x, test_y, pred_test_y):
    mp.plot([x, x], [y, pred_y], c='orangered',
            alpha=0.5, linewidth=1)
mp.plot(test_x, pred_test_y, '--', c='limegreen',
        label='Regression', linewidth=1)
mp.legend()
mp.figure('Training Progress', facecolor='lightgray')
mp.subplot(311)
mp.title('Training Progress', fontsize=20)
mp.ylabel('w0', fontsize=14)
mp.gca().xaxis.set_major_locator(
    mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, w0, c='dodgerblue', label='w0')
mp.legend()
mp.subplot(312)
mp.ylabel('w1', fontsize=14)
mp.gca().xaxis.set_major_locator(
    mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, w1, c='limegreen', label='w1')
mp.legend()
mp.subplot(313)
mp.xlabel('epoch', fontsize=14)
mp.ylabel('loss', fontsize=14)
mp.gca().xaxis.set_major_locator(
    mp.MultipleLocator(100))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(epoches, losses, c='orangered', label='loss')
mp.legend()
mp.tight_layout()
mp.figure('Loss Function')
ax = mp.gca(projection='3d')
mp.title('Loss Function', fontsize=20)
ax.set_xlabel('w0', fontsize=14)
ax.set_ylabel('w1', fontsize=14)
ax.set_zlabel('loss', fontsize=14)
ax.plot_surface(grid_w0, grid_w1, grid_loss,
                rstride=10, cstride=10, cmap='jet')
ax.plot(w0, w1, losses, 'o-', c='orangered',
        label='BGD')
mp.legend(loc='lower left')
mp.figure('Batch Gradient Desent')
mp.title('Batch Gradient Desent', fontsize=20)
mp.xlabel('w0', fontsize=14)
mp.ylabel('w1', fontsize=14)
mp.contourf(grid_w0, grid_w1, grid_loss,
            1000, cmap='jet')
cntr = mp.contour(grid_w0, grid_w1, grid_loss,
                  10, colors='black', linewidths=0.5)
mp.clabel(cntr, inline_spacing=0.1, fmt='%.2f',
          fontsize=10)
mp.plot(w0, w1, 'o-', c='orangered', label='BGD')
mp.legend()
mp.show()

基于模型的机器学习实际上就是要找到一个函数,通过实际输出与预测输出之间的误差,表现模型的精度,在求该函数的极小值的过程中,寻找最优的模型参数。

E = Loss(w0, w1) - 正则项 x 正则强度(C)

import sklearn.linear_model as lm

# 创建模型

model = lm.LinearRegression()

# 训练模型

model.fit(输入, 输出) # 通过梯度下降法计算模型参数

# 预测输出

model.predict(输入)->输出

输入是一个二维数组,每一行是一个样本,每一列是一个特征。

y = wo + w1x1 + w2x2 + ... + wnxn

            特征1    特征2 ... 特征n

样本1   x11       x12       x1n     -> y1

样本2   x21       x22       x2n     -> y2

...

样本m xm1      xm2      xmn    -> ym

输出是一个一维数组,其中每个元素对应输入矩阵中的一行。

模型的保存和加载

import pickle

pickle.dump(内存对象, 磁盘文件) # 保存模型

                             \_________^

pickle.load(磁盘文件)->内存对象  # 加载模型

                             \_________^

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import pickle
import numpy as np
import sklearn.linear_model as lm
import sklearn.metrics as sm
import matplotlib.pyplot as mp
# 采集数据
x, y = [], []
with open('../../data/single.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr
                in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y)
# 创建模型
model = lm.LinearRegression()  # 线性回归
# 训练模型
model.fit(x, y)
# 根据输入预测输出
pred_y = model.predict(x)
# 打印每个样本的实际输出和预测输出
for true, pred in zip(y, pred_y):
    print(true, '->', pred)
# 平均绝对值误差:1/mΣ|实际输出-预测输出|
print(sm.mean_absolute_error(y, pred_y))
# 平均平方误差:SQRT(1/mΣ(实际输出-预测输出)^2)
print(sm.mean_squared_error(y, pred_y))
# 中位绝对值误差:MEDIAN(|实际输出-预测输出|)
print(sm.median_absolute_error(y, pred_y))
# R2得分,将[0,∞)区间的误差映射到[1,0)区间的分值
print(sm.r2_score(y, pred_y))
# 将训练好的模型对象保存到磁盘文件中
with open('../../data/linear.pkl', 'wb') as f:
    pickle.dump(model, f)
mp.figure('Linear Regression', facecolor='lightgray')
mp.title('Linear Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x, y, c='dodgerblue', alpha=0.75,
           s=60, label='Sample')
sorted_indices = x.T[0].argsort()
mp.plot(x[sorted_indices], pred_y[sorted_indices],
        c='orangered', label='Regression')
mp.legend()
mp.show()

 

岭回归

普通线性回归模型使用基于梯度下降的最小二乘法,在最小化损失函数的前提下,寻找最优模型参数,于此过程中,包括少数异常样本在内的全部训练数据都会对最终模型参数造成程度相等的影响,异常值对模型所带来影响无法在训练过程中被识别出来。为此,岭回归在模型迭代过程所依据的损失函数中增加了正则项,以限制模型参数对异常样本的匹配程度,进而提高模型面对多数正常样本的拟合精度。

model = lm.Ridge(正则强度, fit_intercept=是否训练截距,

    max_iter=最大迭代次数)

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp
# 采集数据
x, y = [], []
with open('../../data/abnormal.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr
                in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y)
# 创建模型
model = lm.LinearRegression()  # 线性回归
# 训练模型
model.fit(x, y)
# 根据输入预测输出
pred_y1 = model.predict(x)
# 创建模型
model = lm.Ridge(150, fit_intercept=True,
                 max_iter=10000)  # 岭回归
# 训练模型
model.fit(x, y)
# 根据输入预测输出
pred_y2 = model.predict(x)
mp.figure('Linear & Ridge', facecolor='lightgray')
mp.title('Linear & Ridge', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x, y, c='dodgerblue', alpha=0.75,
           s=60, label='Sample')
sorted_indices = x.T[0].argsort()
mp.plot(x[sorted_indices], pred_y1[sorted_indices],
        c='orangered', label='Linear')
mp.plot(x[sorted_indices], pred_y2[sorted_indices],
        c='limegreen', label='Ridge')
mp.legend()
mp.show()

 

 

 

 

 

想要看更多的课程请微信关注SkrEric的编程课堂

你可能感兴趣的:(机器学习)