记录生活中的点点滴滴

0%

机器学习入门

国庆节的时候学了一下机器学习,大概学了四天时间,虽然很多都不太懂,数学公式更是根本看不懂,后面就基本放弃了,本来大概有10章左右内容,我博客记录了前两章的案例实现,后面的感觉基本思想都差不多就懒得写了,虽然公式什么的都看不懂,主要就是熏陶熏陶就行,权当入门与练练python了,下面是博客记录,主要是案例分析预测python实现。

单变量线性回归

一个简单案例:波士顿房屋价格的拟合与预测

Scikit-learn 的内置数据集波士顿房屋价格为案例,采用单变量线性回归算法对数据进行拟合与预测

1
2
3
4
5
# 导入相关库
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
1
2
3
4
5
6
# 将读取的房价存储在boston变量中
boston = load_boston()
# 打印boston包含内容
print(boston.keys())
# 打印data的变量名
print(boston.feature_names)

输出结果为

1
2
3
dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
'B' 'LSTAT']

将data转换成DataFrame二维标签,它的column为5那一列就是 RM (每个房屋的房间数量),我们还要选取target的 MEDV (房屋价格)变量,进行单变量线性回归

1
2
bos = pd.DataFrame(boston.data)
bos

1
2
bos_target = pd.DataFrame(boston.target)
bos_target

上面我们已经得到了两个变量(RM和MEDV)的信息,接下来我们可以绘制一下两者的散点图

1
2
3
4
5
6
7
8
9
10
11
# 导入文字管理库
import matplotlib.font_manager as fm
x = bos.iloc[:,5:6]
y = bos_target
# 设定自定义字体,文件名是系统中文字体
myfont = fm.FontProperties(fname='C:/Windows/Fonts/msyh.ttc')
plt.scatter(x,y)
plt.xlabel(u'住宅平均房间数',fontproperties=myfont)
plt.ylabel(u'房屋价格',fontproperties=myfont)
plt.title(u'RM与MEDV的关系',fontproperties=myfont)
plt.show()

数据集划分

1
2
3
4
5
6
7
8
# 导入数据划分包
from sklearn.model_selection import train_test_split
# 将x y转化成数组形式,以便于计算
x = np.array(x.values)
y = np.array(y.values)
# 以25%的数据构建测试样本,剩余作为训练样本
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
x_train.shape,x_test.shape,y_train.shape,y_test.shape

输出结果:

1
((379, 1), (127, 1), (379, 1), (127, 1))

模型求解与预测的Python实现

1
2
3
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(x_train,y_train)

在Python中线性回归最常用的包还是 Scikit-learn 库中的 linear_model 函数,它是最小二乘法求解线性回归的程序包,并提供了一站式解决回归拟合问题的程序框架,并可以通过调整参数来实现不同的优化方法。

输出为:

1
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)

这里设置回归算法为 lr ,采用 lr.fit() 的方式进行训练求解

输出的是 LinearRegression() 中的相关参数的设置

对其中参数的求解结果,代码为:

1
2
print('求解参数为:',lr.intercept_)
print('求解系数为:',lr.coef_)

输出结果为:

1
2
求解参数为: [-38.57203329]
求解系数为: [[9.73554419]]

基于求解参数,对测试集进行预测,代码为:

1
2
y_hat = lr.predict(x_test)
y_hat

以上就是我们通过代码实现将原始数据分为训练集和测试集的情况下得到的拟合和预测结果,接下来就是对于拟合与预测结果的效果评价,以判断我们的求解结果是否良好

模型评价

在求得测试集y的预测值y_hat基础上,我们就可以对模型进行评价

首先将得到的测试集y_test与其对应的y_hat采用图形进行展示,初步观察预测的结果

1
2
3
4
5
6
7
8
9
# y_test与y_hat的可视化
plt.figure(figsize=(10,6)) #设置图片尺寸
t = np.arange(len(x_test)) # 创建t变量
# 绘制y_test曲线
plt.plot(t,y_test,'r',linewidth=2,label='x_test')
# 绘制y_hat曲线
plt.plot(t,y_hat,'g',linewidth=2,label='x_train')
plt.legend()
plt.show()

接下来,采用评估指标拟合度 R平方、MAE、MSE、RMSE对预测效果进行评价

1
2
3
4
5
6
7
8
9
10
11
12
13
# 导入metrics评价模块和r2_score的模块
from sklearn import metrics
from sklearn.metrics import r2_score
# 拟合优度R平方的输出方法一
print('r2:',lr.score(x_test,y_test))
# 拟合优度R平方的输出方法二
print('r2_score:',r2_score(y_test,y_hat))
# 计算 MAE
print('MSE:',metrics.mean_absolute_error(y_test,y_hat))
# 计算 MSE
print('MAE:',metrics.mean_squared_error(y_test,y_hat))
# 计算 RMSE
print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat)))

输出结果:

1
2
3
4
5
r2: 0.33304599912598243
r2_score: 0.33304599912598243
MSE: 4.70189787424189
MAE: 50.09850718706328
RMSE: 7.078029894473693

拟合优度R平方有两种输出方式,输入参数不同,但输出结果相同

与最小二乘法预测结果的比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import math
# 构建最小二乘法回归函数
def linefit(x,y):
N = len(x)
sx,sy,sxx,syy,sxy = 0,0,0,0,0
for i in range(0,N):
sx += x[i]
sy += y[i]
sxx += x[i]*x[i]
syy += y[i]*y[i]
sxy += x[i]*y[i]
a = (sxy-sx*sy/N) / (sxx-sx*sx/N)
b = (sy - a*sx) / N
return a,b
# 求解参数a,b
a,b = linefit(x_train,y_train)
# 对测试集的y值进行预测
y_hat1 = a * x_test + b
# 计算MAE
print('MAE:',metrics.mean_absolute_error(y_test,y_hat1))
# 计算MSE
print('MSE:',metrics.mean_squared_error(y_test,y_hat1))
# 计算RMSE
print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat1)))

输出结果:

1
2
3
MAE: 4.70189787424187
MSE: 50.098507187062395
RMSE: 7.078029894473631

可以看到,与 LinearRegression() 求解单变量线性回归的评估指标比较,相差不大,说明两种方法还需进一步改进,以获得更好的预测结果

小结

单变量线性回归算法,就是基于两个变量建立线性回归方程去拟合与预测两变量关系的一种算法。单变量线性回归的常规求解是最小二乘法,它是基于实际值与预测值之间偏差的平方和最小来拟合曲线

通过简单的单变量线性回归案例的机器学习解决方案整体介绍,可以总结出机器学习的基本操作流程包括:数据准备与需求分析、数据预处理、数据集划分、算法的训练、算法的测试、算法的评估等

其中最核心的环节就是数据集划分、算法的测试与评估

机器学习就是不断尝试各种算法,从而找到最优算法、预测能力最强算法的一个过程

线性回归算法进阶

由于单变量线性回归算法只有一个特征变量,所以在实际生活中有很大局限性,而多变量线性回归算法的求解原理取自于单变量线性回归算法,又克服了其局限性,因而应用广泛

多变量线性回归算法

Python实现:影厅观影人数的拟合

  • 导入数据

    1
    2
    3
    4
    5
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    df = pd.read_csv('https://www.gaosong.site/MachineLearn/3_film.csv')
    df.head()

  • 多变量的数据可视化之直方图

    1
    2
    df.hist(xlabelsize=12,ylabelsize=12,figsize=(12,7)) # 调整直方图尺寸
    plt.show()

  • 多变量的数据可视化之直方图

    1
    2
    df.plot(kind='density',subplots=True,layout=(2,2),sharex=False,fontsize=8,figsize=(12,7))
    plt.show()

  • 多变量的数据可视化之箱线图

    1
    2
    df.plot(kind='box',subplots=True,layout=(2,2),sharex=False,sharey=False,fontsize=8,figsize=(12,7))
    plt.show()

  • 多变量的数据可视化之相关系数热力图

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    names = ['filmnum','filmsize','ratio','quality'] # 设置变量名
    correlations = df.corr() # 计算变量之间的相关系数矩阵
    # 绘制相关系数热力图
    fig = plt.figure() # 创建一个绘图对象
    ax = fig.add_subplot(111) # 调用画板绘制第一个子图
    cax = ax.matshow(correlations,vmin=0.3,vmax=1) # 绘制热力图,从0.3到1
    fig.colorbar(cax) # 将matshow生成的热力图设置颜色渐变条
    ticks = np.arange(0,4,1)
    ax.set_xticks(ticks) #生成刻度
    ax.set_yticks(ticks) # 生成刻度
    ax.set_xticklabels(names) # 生成x轴标签
    ax.set_yticklabels(names) # 生成y轴标签
    plt.show()

  • 多变量的数据可视化之散点图矩阵

    1
    2
    3
    from pandas.plotting import scatter_matrix
    scatter_matrix(df,figsize=(8,8),c='b') # 绘制散点图矩阵
    plt.show()

  • 选取特征变量与响应变量,并进行数据划分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 设定x y变量
    x = df.iloc[:,1:4]
    y = df.filmnum
    from sklearn.model_selection import train_test_split
    # 把xy转化成数组形式,以便于计算
    x = np.array(x.values)
    y = np.array(y.values)
    # 以25%的数据构建测试样本,剩余作为训练样本
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=1)
    x_train.shape,x_test.shape,y_train.shape,y_test.shape

    输出结果:

    1
    ((94, 3), (32, 3), (94,), (32,))
  • 进行线性回归操作,并输出结果

    1
    2
    3
    4
    5
    from sklearn.linear_model import LinearRegression
    lr = LinearRegression() # 假定回归算法
    lr.fit(x_train,y_train) # 使用训练数据进行参数求解
    print('求解截距项为:',lr.intercept_)
    print('求解系数为:',lr.coef_)

    输出结果:

    1
    2
    求解截距项为: 4.353106493779016
    求解系数为: [ 0.37048549 -0.03831678 0.23046921]
  • 根据求出的参数对测试集进行预测

    1
    2
    y_hat = lr.predict(x_test)
    y_hat

    输出结果:

    1
    2
    3
    4
    5
    6
    7
    array([20.20848598, 74.31231952, 66.97828797, 50.61650336, 50.53930128,
    44.72762082, 57.00320531, 35.55222669, 58.49953514, 19.43063402,
    27.90136964, 40.25616051, 40.81879843, 40.01387623, 24.56900454,
    51.36815239, 38.97648053, 39.25651308, 65.4877603 , 60.82558336,
    54.29943364, 40.45641818, 29.69241868, 49.29096985, 44.60028689,
    48.05074366, 35.23588166, 72.29071323, 53.79760562, 51.94308584,
    46.42621262, 73.37680499])
  • 对测试集相应实际值与预测相比较

    1
    2
    3
    4
    5
    6
    7
    plt.figure(figsize=(10,6)) # 设置图片尺寸
    t = np.arange(len(x_test)) # 创建t变量
    # 绘制y_test及y_hat图像
    plt.plot(t,y_test,'r',linewidth=2,label='y_test')
    plt.plot(t,y_hat,'g',linewidth=2,label='y_train')
    plt.legend() # 设置图例
    plt.show()

  • 对预测结果进行评价

    1
    2
    3
    4
    5
    6
    7
    from sklearn import metrics
    from sklearn.metrics import r2_score
    print('r2:',lr.score(x_test,y_test))
    print('r2_score:',r2_score(y_test,y_hat))
    print('MAE:',metrics.mean_absolute_error(y_test,y_hat))
    print('MSE:',metrics.mean_squared_error(y_test,y_hat))
    print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat)))

    输出结果:

    1
    2
    3
    4
    5
    r2: 0.8279404383777595
    r2_score: 0.8279404383777595
    MAE: 4.63125112009528
    MSE: 46.63822281456598
    RMSE: 6.8292183165107545

梯度下降法求解多变量线性回归

  • 导入数据

    1
    2
    3
    4
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    df = pd.read_csv('https://www.gaosong.site/MachineLearn/3_film.csv')
  • 插入一列全为1的数组

    1
    2
    df.insert(1,'Ones',1) # 在df第1列和第2列插入1列全是1的数组
    df.head()

  • 选取特征变量与响应变量,并进行数据划分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    cols = df.shape[1] # 计算df的列数
    # 设定x y变量
    x = df.iloc[:,1:cols]
    y = df.filmnum
    from sklearn.model_selection import train_test_split
    # 把xy转化成数组形式,以便于计算
    x = np.array(x.values)
    y = np.array(y.values)
    # 以25%的数据构建测试样本,剩余作为训练样本
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=1)
    x_train.shape,x_test.shape,y_train.shape,y_test.shape

    输出结果:

    1
    ((94, 4), (32, 4), (94,), (32,))
  • 构建计算成本函数的函数

    1
    2
    3
    def computeCost(x,y,theta):
    inner = np.power(((x*theta.T)-y),2)
    return np.sum(inner)/(x*len(x))
  • 构建梯度下降法求解函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 梯度下降法函数xy是输入变量,theta是参数,alpha是学习率,iters是梯度下降迭代次数
    def gradientDescent(x,y,theta,alpha,iters):
    temp = np.matrix(np.zeros(theta.shape)) # 构建零值矩阵
    parameters = int(theta.ravel().shape[1]) # 计算需要求解的参数个数
    cost = np.zeros(iters) # 构建iters个0的数组
    for i in range(iters):
    error = (x*theta.T) - y # 对于h斯塔(x)-y
    for j in range(parameters): # 对于theta中的每一个元素依次计算
    term = np.multiply(error,x[:,j]) # 计算两矩阵相乘(h斯塔(x)-y)x
    temp[0,j] = theta[0,j] - ((alpha / len(x)) * np.sum(term)) # 更新法则
    theta = temp
    cost[i] = computeCost(x,y,theta) # 基于求出来的theta求解成本函数
    return theta,cost
  • 设定相关参数的初始值,并代入 gradientDescent() 函数中求解

    1
    2
    3
    4
    5
    6
    alpha = 0.000001 # 设定学习率
    iters = 100 # 设定迭代次数
    theta = np.matrix(np.array([0,0,0,0]))
    # 采用gradientDescent()函数优化求解
    g,cost = gradientDescent(x,y,theta,alpha,iters)
    g

    输出结果:

    1
    matrix([[-0.04136036,  0.43005475,  0.04386123,  0.15978382]])
  • 对预测集进行预测

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    y_hat = x_test * g.T #求出预测集y_test的预测值
    y_hat
    plt.figure(figsize=(10,6)) # 设置图片尺寸
    t = np.arange(len(x_test)) # 创建t变量
    # 绘制y_test曲线
    plt.plot(t,y_test,'r',linewidth=2,label='y_test')
    # 绘制y_hat曲线
    plt.plot(t,y_hat,'g',linewidth=2,label='y_train')
    plt.legend() # 设置图例
    plt.show()

  • 对预测结果进行评价

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from sklearn import metrics
    from sklearn.metrics import r2_score
    # 计算拟合优度r2方法二
    print('r2_score:',r2_score(y_test,y_hat))
    # 计算 MAE
    print('MAE:',metrics.mean_absolute_error(y_test,y_hat))
    # 计算 MSE
    print('MSE:',metrics.mean_squared_error(y_test,y_hat))
    # 计算 RMSE
    print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat)))

    输出结果:

    1
    2
    3
    4
    r2_score: 0.7559963309347564
    MAE: 6.2884702235683125
    MSE: 66.13929140666531
    RMSE: 8.132606679697801

线性回归的正则化

欠拟合与过拟合,是机器学习应用时经常会出现的两个问题

对于机器学习算法而言,欠拟合的问题是我们不断尝试各种合适的算法,优化算法中的参数调整,以及通过数据预处理、数据可视化等特征工程,找到模型拟合效果最优化的结果。而当模型过拟合的情况发生时,可以通过尽可能减少特征变量数,这种做法的缺点在于舍弃某些变量的同时,也舍弃了其所携带的信息。而了一种方法——正则化,可以保留全部特征变量,且每一个特征变量或多或少都对模型预测有些许影响,所以正则化是处理过拟合的一种实用方法

岭回归

  • 导入数据与划分数据集

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd

    df = pd.read_csv('https://www.gaosong.site/MachineLearn/3_film.csv')

    # 设定x y变量
    x = df.iloc[:,1:4]
    y = df.filmnum
    from sklearn.model_selection import train_test_split
    # 把xy转化成数组形式,以便于计算
    x = np.array(x.values)
    y = np.array(y.values)
    # 以25%的数据构建测试样本,剩余作为训练样本
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=1)
    x_train.shape,x_test.shape,y_train.shape,y_test.shape
  • 岭回归估计

    1
    2
    3
    4
    5
    from sklearn import linear_model
    ridge = linear_model.Ridge(alpha=0.1) # 设置lambda值
    ridge.fit(x_train,y_train) # 使用训练数据进行参数求解
    print('求解截距为:',ridge.intercept_)
    print('求解系数为:',ridge.coef_)

    输出结果:

    1
    2
    求解截距为: 4.35314337580391
    求解系数为: [ 0.37048481 -0.03831273 0.23046337]
  • 根据求出参数对测试集进行预测

    1
    2
    y_hat = ridge.predict(x_test)
    y_hat

    输出结果:

    1
    2
    3
    4
    5
    6
    7
    array([20.20853893, 74.31234956, 66.97821059, 50.6165136 , 50.53930114,
    44.72765631, 57.00323469, 35.55225421, 58.49957742, 19.43063223,
    27.90141477, 40.25616827, 40.81880372, 40.0138511 , 24.5690141 ,
    51.36816302, 38.97647244, 39.25651534, 65.4878337 , 60.82557067,
    54.29941514, 40.45644904, 29.6924055 , 49.29096192, 44.60027731,
    48.05075283, 35.23586124, 72.29061596, 53.79762601, 51.94295979,
    46.42624246, 73.37678549])
  • 对测试集相应变量实际值与预测值比较

    1
    2
    3
    4
    5
    6
    7
    plt.figure(figsize=(10,6)) # 设置图片尺寸
    t = np.arange(len(x_test)) # 创建t变量
    # 绘制y_test y_hat图像
    plt.plot(t,y_test,'r',linewidth=2,label='y_test')
    plt.plot(t,y_hat,'g',linewidth=2,label='y_hat')
    plt.legend() # 设置图例
    plt.show()

  • 对预测结果进行评价

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from sklearn import metrics
    from sklearn.metrics import r2_score
    # 计算拟合优度r2方法二
    print('r2_score:',r2_score(y_test,y_hat))
    # 计算 MAE
    print('MAE:',metrics.mean_absolute_error(y_test,y_hat))
    # 计算 MSE
    print('MSE:',metrics.mean_squared_error(y_test,y_hat))
    # 计算 RMSE
    print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat)))

    输出结果:

    1
    2
    3
    4
    r2_score: 0.8279400477123058
    MAE: 4.631262902381461
    MSE: 46.63832870779447
    RMSE: 6.829226069460175

Lasso回归

  • Lasso回归估计

    1
    2
    3
    4
    5
    from sklearn import linear_model
    lasso = linear_model.Lasso(alpha=0.1) # 设置lambda值
    lasso.fit(x_train,y_train) # 使用训练数据进行参数求解
    print('求解截距为:',lasso.intercept_)
    print('求解系数为:',lasso.coef_)

    输出结果:

    1
    2
    求解截距为: 4.358584829813829
    求解系数为: [ 0.36999035 -0.03494547 0.22750781]
  • 根据求出参数对测试集进行预测

    1
    2
    y_hat_lasso = lasso.predict(x_test) # 对测试集的预测
    y_hat_lasso

    输出结果:

    1
    2
    3
    4
    5
    6
    7
    array([20.233949  , 74.32855715, 66.94661945, 50.62126153, 50.5335356 ,
    44.75419636, 57.02133523, 35.56117031, 58.53426597, 19.4159754 ,
    27.92917866, 40.25883102, 40.82138372, 39.99097642, 24.57405304,
    51.36591903, 38.95827376, 39.24323884, 65.54967283, 60.81869771,
    54.29397646, 40.46344761, 29.68132638, 49.29153954, 44.59117818,
    48.06159774, 35.21604732, 72.23599759, 53.81139281, 51.87374947,
    46.44653125, 73.38703994])
  • 对测试集相应变量实际值与预测值比较

    1
    2
    3
    4
    5
    6
    7
    plt.figure(figsize=(10,6)) # 设置图片尺寸
    t = np.arange(len(x_test)) # 创建t变量
    # 绘制y_test y_hat图像
    plt.plot(t,y_test,'r',linewidth=2,label='y_test')
    plt.plot(t,y_hat_lasso,'g',linewidth=2,label='y_hat_lasso')
    plt.legend() # 设置图例
    plt.show()

  • 对预测结果进行评价

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from sklearn import metrics
    from sklearn.metrics import r2_score
    # 计算拟合优度r2方法二
    print('r2_score:',r2_score(y_test,y_hat_lasso))
    # 计算 MAE
    print('MAE:',metrics.mean_absolute_error(y_test,y_hat_lasso))
    # 计算 MSE
    print('MSE:',metrics.mean_squared_error(y_test,y_hat_lasso))
    # 计算 RMSE
    print('RMSE:',np.sqrt(metrics.mean_squared_error(y_test,y_hat_lasso)))

    输出结果:

    1
    2
    3
    4
    r2_score: 0.8276541436150417
    MAE: 4.638494755480021
    MSE: 46.71582547034623
    RMSE: 6.834897619595061