机器学习

机器学习

1. 数学基础

1.1 导数

  • 理解倒数以及偏导数

1.2向量

  • 标量(Scalar):一个标量就是一个单独的数,如s属于R

    • R表示的维度,例如R方就是二维的,R的N次就是N维的
  • 向量,是指n个实数组成的有序数组,称为n维向量。 X 无特殊说明一般是一条列向量。x的转资就是一条横向量

  • 如一条向量表示一个实体,则向量中的每一个维度表示一个属性

1.2.1向量范数

是具有“长度”概念的函数。在线性代数,泛函分析及相关领域,范数是一个函数,其为向量空间内所有向量赋予非0的正长度或大小。
较常用范数有:

  • L1-范数:向量元素绝对值之和,曼哈顿距离

曼哈顿距离

  • L2-范数:欧几里得范数,欧式距离(任意维度一点到原点的距离)

        - ![](https://img2023.cnblogs.com/blog/2881050/202305/2881050-20230521221949176-1354917327.png)
    
  • ∞-范数:所有向量元素绝对值的最大值 (max|xi|)

  • P-范数:向量绝对值的p次方和p分之一次幂,一般形式。

1.2.2向量运算

向量运算

1.3矩阵

一个m*n的矩阵(matrix)是由m行,n列元素排列成的矩阵。其中,从左上角数起第i行第j列上的元素称为矩阵第(i,j)项,记做Aij。

  • 矩阵就可以看作是多个实体的集合,那么每一行就可以看作是一个单独的个体,而多个体的同一列的元素,就可以看作这多个个体的属性,元素的大小就表示该属性的修饰个体的程度
1.3.1矩阵的范数
  • F范数
  • p范数
    矩阵范数
1.3.2矩阵乘法

矩阵乘法

  • A矩阵的列数等于B矩阵的行数时,A可以和B相乘
  • 矩阵C的行数等于矩阵A的函数,举证C的列数等于B的列数
  • 乘积C的第M行和N列的元素等于矩阵A的第M行的元素与矩阵B的第N列对应元素乘积之和
1.3.3矩阵的运算

矩阵运算

1.3.4单位矩阵和逆矩阵
  • 单位矩阵:主对角线的元素都为1,其余元素为0的n阶单位矩阵
  • 逆矩阵:矩阵A的逆矩阵:!A逆矩阵](A逆矩阵.png)
1.3.5矩阵微分求导

矩阵微分

1.4 张量

在某些情况下,我们会讨论不止二维坐标的数组。如果一组数组中的元素分布在若干维坐标的规则网络中,就将其称为张量

  • 一副图,有三个通道(RGB),时三个张量;一个batch图像时四维张量

  • Tensorflow,PyTorch等都是围绕张量构建的计算库

1.5概率基础

  • 随机变量,用字母来表示一个时间可能发生的情况
  • 概率分布:来描述随机变量在每一个可能取到的状态的可能性大小。P(x=x1)
1.5.1条件概率

条件概率

1.5.2 期望,方差,协方差
  • 期望:实验中每次可能结果的概率乘以其结果的总和。反映随变量的平均值大小

  • 方差:用来衡量随机变量与其2数学期望之间的偏离程度,是各个样本数据分别与其平均数之差的平方和的平均数

  • 协方差:用于衡量两个随机变量X和Y之间的总体误差,在某种意义上给出两个变量线性相关性的强度协方差

1.5.3 贝叶斯规则

贝叶斯规则

1.6最大似然估计

最大似然估计
最大似然估计2

2.机器学习基础

  • 数据-->机器学习-->提高某种性能目标
  • 能够被计算机识别--》通过一定模型(建模)--->达到目标
  • x-->f-->y

2.1 基本术语

  1. 数据

    • 训练集,测试集,特征,标记
      数据
      先用训练集,机器学习用他的特征(建立一定模型)判断它的标记进行学习,在用该模型分析测试集的特征在做出它的标记判断。
  2. 任务

    • 预测目标:

      • 分类:离散值
        • 二分类
        • 多分类
      • 回归:连续值
        • 瓜的成熟度
          -聚类:无标记信息
    • 有无标记信息

      • 监督学习:分类,回归
      • 无监督学习:聚类
      • 半监督学习:两者结合
        监督学习区别
  3. 假设空间

    我们可以把学习过程看作一个在所有假设组成的空间中进行搜索的过程,搜索目标找到与训练集“匹配”的假设,即能够最大限度正确判断训练集Label的假设。假设的表示一旦确定,假设空间及其规模大小就确定了。简单来说,假设空间就是特征所有可能表示的集合

  4. 归纳偏好

    假设空间中有三个与训练集一致的假设,但他们对(色泽,长度,大小)来判断是否是好瓜
    归纳偏好
    通过建立模型(A,B),对于两者来说对色泽拟合的很好,而A对于长度拟合优于B,对于大小B优于A。那到底该选择哪一个模型?

    • “奥卡姆剃刀”是一种常用的,自然科学研究中最基本的原则,即“若有对各假设与观察一致,选择最简单的那一个”

    在某些问题上A由于B,但也必然存在另一些问题B优于A。在实际问题中,抛开具体问题,空谈毫无意义

基础

3.科学计算库Numpy

Numpy是高性能科学计算和数据分析的基础包,包括一下功能:

  • ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组
  • 用于对整数数组进行快速运算的标准数学函数
  • 线性代数,随机数生成,统计分析等等

4.线性回归

线性模型:通过属性的线性组合进行预测的函数
线性函数一般式

w:权重,不同属性xy目标影响大小

线性回归概念1.0

4.1 一元线性回归

一元线性回归

  • w:权重
  • xi:第i个数据的一个属性
  • Yi:实际值
  • F(xi):预测值
  • b:偏值
  1. 如何确定w,b?-->衡量$f(x)$与y之间的差别,使得每一个$x_i$所对应的$y_i$与对应用回归函数所求得的$f(x)$之间的差值最小化。即是$\sum_{x_i}^{i} (f(x)-y_i)^2$最小

  2. 均方误差:$$argmin_{(w,b)} \sum^{m}_{i=1} (y_i-wx_i-b)^2$$ 他对应常用的欧氏距离。基于均方误差最小化来进行模型求解的方法称为“最小二乘法”。

  3. 用均方误差求解w,b,分别对其求偏导:
    均方误差求偏导
    $$\frac{\partial E_(w,b)}{\partial w}=2(w \sum^m_{i=1} x2_i-\summ_{i=1}(y_i-b) x_i)\$$
    $$\frac{\partial E_(w,b)}{\partial b}=2(mb-\sum^m_{i=1}(y_i-wx_i)\$$

在另其为0,可得w,b最优闭解

$$w= \frac {\sum^m_{i=1} y_i(x_i- \bar x)} {\sum^{m}{i=1} x_i^2-\frac {1}{m} (\sum^m x_i)^2}$$
$$b=1/m \sum_{i=1}^m y_i - w*1/m \sum_{i=1}^m x_i=\bar y-w\bar x$$

向量化:$x=(x_1,x_2,...x_m)T$,$y=(y_1,y_2...y_m)T$
$x_d=(x_1-\bar x,x_2- \bar x,...x_m- \bar x)^T$,$y_d=(y_1-\bar y,y_2- \bar y,...y_m- \bar y)^T$
向量化1
向量化2
向量化3
$$w=\frac {x_d^T y_d}{x_d^T x_d}$$

损失函数:用来估计你的模型的预测值h(x)与真实值的不一定程度,它是一个非负实值函数。
损失函数

4.2多元线性回归

$$Y=a_1X_1+a_2X_2+....+a_n*X_n+b$$

  • a系数
  • x是变量
  • b偏置

$f(x_i)=w^T x_i+b$,使得$f(x_i)->y_i$.称为多元线性回归。
便于方便,$\hat{w}=(w;b)$
转换为向量的话,$X=(x_1,x_2,x_3....x_n,1)^T$
这$Y=\hat {w}*X$
但是对应每一个实体$x_i$又其对应的多个特征$x_{ij}$
$$X= \begin{pmatrix} x_{11} & x_{12} & ... & x_{1j} & 1\
x_{21} & x_{22} & ... & x_{2j} & 1\
... & ... & ... & ... & ...\
x_{i1} & x_{i2} & ... & x_{ij} & 1
\end{pmatrix}\quad =\begin{pmatrix}
x_1^T & 1\
x_2^T & 1 \
... & ... \
x_j^T & 1
\end{pmatrix}\quad$$

然后再把标记写为向量:$y=(y_1;y_2;...y_j)$,则类似于一元回归公式有:
$$ \hat w^*=argmin_{\hat w}(y-X \hat w)^T(y-X\hat w)$$

推导:
多元推导1
多元推导2
多元推导3
多元推导4
多元推导5
多元推导6

为求出$\hat w$,就对 $E_{\hat w}$求导
求导1
求导2
求导3

$$\hat w*=(XT X)^-1 X^T y$$
被称为解析解或者正规方程
代码实现:

np.dot(np.dot(iinv(np.dot(X.T,X),X),Y))

$$y=X \hat w $$

  • 注意:因为以上解涉及到矩阵的逆计算,即满足:$X^T X$ 为满秩矩阵或正定矩阵时,可以得到上述式子。
  • 但是往往现实中不是满秩矩阵(当特征的个数(x_i)比方程数多时。可以解出多个$\hat w$,他们往往都能使均方误差最小化,则要选择一个,我们往往采用正则化。

代码实例:

#用解析解(正规方程)求解多元线性回归
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
#读数据和数据预处理
data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32);

#对x数据加一列为1
index=np.ones((data.shape[0],1))#创建一个以data的行数为参数的为1向量
#np.shape[0]返回行数,np.shape[1]返回列数

# print(index)

data2=np.hstack((data,index)) #数据集合并全1列

# print(data2)

#取出目标值y,和特征值X

X=data[:,1:]
Y=data[:,0]

# print(X)
# print(Y)

#将数据集分成训练数据和测试数据.x的80%作为训练数据,剩下的作为测试数据
x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.8);


#训练模型

#求/hat w
x2_train=np.dot(x_train.T,x_train) #这一步求x向量于x转置的乘积
x2_ni_train=np.linalg.inv(x2_train)#这一步求逆
x3_train=np.dot(x2_ni_train,x_train.T)

weight=np.dot(x3_train,y_train)
# print(weight)

#用训练得到的数据预测

predict=np.dot(x_test,weight) #得到预测值
# print(predict)

#绘制曲线,查看拟合情况

plt.plot(range(len(y_test)),y_test,c="red",alpha=0.5) #绘制测试数据的真实值
plt.plot(range(len(y_test)),predict,c="green",alpha=0.5) #绘制测试数据的预测值
# plt.show()

用sklearn实现不满足逆矩阵的模型

#用sklearn实现线性回归模型

import numpy as np
from sklearn import linear_model
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import pickle
#读数据
data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32)#(文件名,分隔符,跳过第几行,元素类型)

#分出特征数据X和标签Y
X=data[:,1:]
Y=data[:,0]

#分割训练数据和测试数据

x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.8)

#使用线性模型sklearn
model=linear_model.LinearRegression()#使用linear_model下的对应线性回归模型

#训练模型
model.fit(x_train,y_train)

#查看训练好的模型参数
# print(model.coef_)#系数(权重)
# print(model.intercept_)#截距
# print(model.score(x_train,y_train))#预测率

predict=model.predict(x_test)

#保存训练好的模型
with open("model.pickle","wb") as f:
    pickle.dump(model,f)
#使用保存好的模型
'''
with open("model.pickle","wb") as f:
    model=pickle.load(f)
    该model模型和就是上述linear_model.LinearRegression()已经训练好的模型
'''
#绘图

plt.rcParams['font.sans-serif']=['SimHei']#避免plt图出现中文乱码
plt.title("散点图")
plt.xlabel("样本id")
plt.ylabel("目标值")
plt.scatter(np.arange(len(x_test))[:100],predict[:100])
plt.scatter(np.arange(len(x_test))[:100],y_test[:100],c="green")
plt.show()

4.3 梯度下降算法

//

当不能用解析解求得$\hat w$时2,一般的通常求解套路:迭代寻优算法(告诉机器一个正确的方向,让它慢慢逼近最优解)。此时可以用经典的梯度下降算法(优化算法)来找到损失函数的最低点附近。

正确方向:梯度下降方向(|k|下降的方向)

损失函数:J($\theta_0$,$\theta_1$)=$1/2m \sum^m_{i=1}(h_\theta (x_i)-y_i)^2)$

//

$$(\frac{\partial J}{\partial w_0},\frac{\partial J}{\partial w_1},\frac{\partial J}{\partial w_2}...\frac{\partial J}{\partial w_m})$$

  • 学习率a的大小直接决定这每次更新的挪动大小,如果a太小,那么每次挪动的距离只会一点一点的挪动,这样就需要很多不才能到达最低点

    //
    //

    $$\theta_j:=\theta_j-a \frac{\partial}{\partial{\theta_j}}j(\theta)$$
    a是正数--梯度下降

    • 当$\frac{\partial}{\partial{\Theta_j}}j(\theta)$>0z,在最低点的左边,此时$\Theta_j$减去一个正数,$\Theta_j$减小。靠近最低点
    • 反之, 当$\frac{\partial}{\partial{\theta_j}}j(\theta)$<0z,在最低点的右边边,此时$\theta_j$减去一个负数数,$\theta_j$增加。靠近最低点。
  • $J(\theta_0$,$\theta_1$)=$1/2m \sum^m_ {i=1}(h_\theta (x_i)-y_i)^2)$

    对$\partial{\theta_j}$求导推导:

    1. $$\frac{\partial j(\theta_0,\theta_1)}{\partial \theta_j}=i/m \sum^m_{t=1}(h_\theta (x_i)-y_i)x_{ij}$$

    2. $$\theta_1:=\theta_1 - a*1/m\sum^m_{i=1}(h_\theta (x_i)-y_i)x_{i1}$$

    3. $$\theta_2:=\theta_2 - a*1/m\sum^m_{i=1}(h_\theta (x_i)-y_i)x_{i2}$$

  • 向量化($\sum$的向量化)
    通用公式:$\sum_{i=n}^n x_i y_i=x^Ty$

    $\theta_j:=\theta_j - a*1/m\sum^m_{i=1}(h_\theta (x_i)-y_i)x{ij}$ 其中i 表示第i个样本,j表示每个样本的第j个特征

    又有= $\theta_j - a*1/m\sum^m_{i=1} x_{ij}(h_\theta (x_i)-y_i)$

    最终有:
    $$\theta_j - a*1/m[x_{1j},x_{2j}...x_{mj}] \begin{pmatrix}
    x_1^T \theta-y_1\
    x_2^T \theta-y_2\
    ...\
    x_m^T \theta-y_m\
    \end{pmatrix}\quad$$

$\theta_j$是$[\theta_1,\theta_2,..,\theta_n]$中的任意一值

则一般的式:

$$[\theta_1,\theta_2,..,\theta_n]^T=
[\theta_1,\theta_2,..,\theta_n]^T-a*1/m
\begin{pmatrix}
x_{11}&x_{21}&...&x_{m1} \
x_{12}&x_{22}&...&x_{m2} \
...&...&...&...\
x_{1j}&x_{2j}&...&x_{mj} \
\end{pmatrix}
\begin{pmatrix}
x_1^T \theta-y_1\
x_2^T \theta-y_2\
...\
x_m^T \theta-y_m\
\end{pmatrix}
$$

代码:Theta=Theta-alpha*np.dot(X.T,np.dot((X,Theta)-y)/m

4.3.1特征缩放

//

4.3.2批量梯度算法与代码实现

//

优点:能达到全局最优解,易于并行实现
缺点:当样本数目很多时,训练过程缓慢

  • 准确度评价指标
    //
  1. 批量梯度下降代码实例
import numpy as np
import matplotlib.pyplot as plt

'''随便给出一个拟合方程的参数,然后根据梯度下降算法去使得这个参数的损失函数逼近最小
而多项式拟合,是根据损失函数求导找到其损失函数的最小值(另损失函数为0时求得的参数)。但当数据集x的特征值比样本数多时无法求最优解

'''
#抽象化

#归一化函数
def featureNormalze(X):
    mu=X.mean(0)#求列均值
    std=np.std(X)
    X=(X-mu)/std
    index=np.ones((X.shape[0],1))#获取行数创建全1向量
    X=np.hstack((X,index))
    return X

#读数据
def readcsv():
    data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32)
    X=data[:,1:]
    Y=data[:,0].reshape(-1,1)
    # print(Y)
    X=featureNormalze(X)
    return X,Y

#计算损失函数
def lossFunction(X,Y,theta):
    m=X.shape[0]#样本个数
    loss=sum((np.dot(X,theta)-Y)**2)/(2*m)
    return loss

#实现梯度下降算法
def batchGradientDecent(X,Y,theta,alpha,num_iters):#需要写入迭代次数
    m=X.shape[0]
    loss_all=[];
    for i in range(num_iters):
        theta=theta-alpha*np.dot(X.T,(np.dot(X,theta)-Y))/m
        loss=lossFunction(X,Y,theta)
        loss_all.append(loss)
        print("第{}次的损失值为:{}".format(i+1,loss))
    return theta,loss_all

if __name__=="__main__":
    #1 2 读数据,归一化
    x,y=readcsv()

    #3.初始化theta参数
    theta=np.ones((x.shape[1],1))

    #4.初始化迭代次数
    num_iters=500
    alpha=0.01

    #5.调用梯度下降算法求参数
    theta,loss_all=batchGradientDecent(x,y,theta,alpha,num_iters)
    print(theta)

    ##6.预测
    y_predict=np.dot(x,theta)

    ##6.可视化
    # plt.scatter(np.arange(100),y[:100])
    # plt.scatter(np.arange(100),y_predict[:100],c="green")
    # plt.show()

    ##绘制损失函数,和迭代次数的曲线
    plt.plot(np.arange(num_iters),loss_all)
    plt.show()
  1. 随机梯度下降代码实例
#随机梯度下降算法(sklearn库)
import numpy as np
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error,mean_absolute_error,median_absolute_error,r2_score

from sklearn.preprocessing import StandardScaler#数据预处理包


#读数据
data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32,)
X=data[:,1:]#特征集  二维矩阵
Y=data[:,0]#目标集
x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.8)#随机的体现

#数据预处理

#生成一个标准化数据对象,可以对每一个特征维度二维化
scaler=StandardScaler()
scaler.fit(x_train) #计算均值和方差,标准差
# print(x_train)

x_train=scaler.transform(x_train)#得到标准化的矩阵
# print(x_train)


#用SGD模型训练,更新参数
sgd=SGDRegressor()#生成SGD对象
sgd.fit(x_train,y_train)


#预测
y_predict=sgd.predict(x_test)

#绘制
plt.scatter(np.arange(100),y_test[:100])  #真实值
plt.scatter(np.arange(100),y_predict[:100],c="green")  #预测值
plt.show()

#模型评价
print("mae",mean_absolute_error(y_test,y_predict))
print("mse",mean_squared_error(y_test,y_predict))
print("median-ae",median_absolute_error(y_test,y_predict))
print("r2",r2_score(y_test,y_predict))
  • 随机梯度算法

    优点:训练速度快

    缺点:准确度下降,并不是最优解,不易于并行实现

  1. 小批量梯度下降代码实现
#小批量梯度下降

import numpy as np
import matplotlib.pyplot as plt

'''随便给出一个拟合方程的参数,然后根据梯度下降算法去使得这个参数的损失函数逼近最小
而多项式拟合,是根据损失函数求导找到其损失函数的最小值(另损失函数为0时求得的参数)。但当数据集x的特征值比样本数多时无法求最优解

'''
#抽象化

#归一化函数
def featureNormalze(X):
    mu=X.mean(0)#求列均值
    std=np.std(X)
    X=(X-mu)/std
    index=np.ones((X.shape[0],1))#获取行数创建全1向量
    X=np.hstack((X,index))
    return X

#读数据
def readcsv():
    data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32)
    X=data[:,1:]
    Y=data[:,0].reshape(-1,1)
    # print(Y)
    X=featureNormalze(X)
    return X,Y

#计算损失函数
def lossFunction(X,Y,theta):
    m=X.shape[0]#样本个数
    loss=sum((np.dot(X,theta)-Y)**2)/(2*m)
    return loss

#实现梯度下降算法
def batchGradientDecent(X,Y,theta,alpha,num_iters):#需要写入迭代次数
    m=X.shape[0]
    loss_all=[];

    #小批量梯度下降代码体现
    index = np.random.choice(a=np.arange(m), size=500, replace=False)
    # 随机生成np数组,a是范围,size是元素个数,replace是包含重复选取

    X_new = X[index]  # 直接通过np数组去取出np数组数据
    Y_new = Y[index]

    for i in range(num_iters):


        theta=theta-alpha*np.dot(X_new.T,(np.dot(X_new,theta)-Y_new))/m
        loss=lossFunction(X_new,Y_new,theta)
        loss_all.append(loss)
        print("第{}次的损失值为:{}".format(i+1,loss))
    return theta,loss_all

if __name__=="__main__":
    #1 2 读数据,归一化
    x,y=readcsv()

    #3.初始化theta参数
    theta=np.ones((x.shape[1],1))

    #4.初始化迭代次数
    num_iters=500
    alpha=0.01

    #5.调用梯度下降算法求参数
    theta,loss_all=batchGradientDecent(x,y,theta,alpha,num_iters)
    print(theta)

    ##6.预测
    y_predict=np.dot(x,theta)

    ##6.可视化
    # plt.scatter(np.arange(100),y[:100])
    # plt.scatter(np.arange(100),y_predict[:100],c="green")
    # plt.show()

    ##绘制损失函数,和迭代次数的曲线
    plt.plot(np.arange(num_iters),loss_all)
    plt.show()

  • 小批量梯度下降介于上面两者之间,相对于随机梯度下架算法,降低了收敛的波动性,即降低了参数更新的方差,使得更新更加稳定。相对于批量梯度下降,其提高了每次学习的速度

4.4 多项式回归

  1. 在一元回归分析中,如果因变量y与自变量x的关系为非线性的,但是又找不到适当的函数曲线来拟合,则可以采用亿元多项式回归

  2. 多项式回归最大优点就是可以通过增加x的高次项对实测点进行逼近,直至满意为止

  3. 事实上,多项式回归可以处理相当一类非线性问题,他在回归分析中占有重要的地位,因为2任一函数都可以分段用多项式来逼近

  • 对于这样的曲线
    $h_\theta (x)=\theta_0+\theta_1 x_1+\theta_2 x_1^2+\theta_3 x_1^3$

    通过将:$x_2=x_1^2 和 x_3=x_1^3$
    来转换为线性回归模型

#随机梯度下降算法(sklearn库)
import numpy as np
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error,mean_absolute_error,median_absolute_error,r2_score

from sklearn.preprocessing import StandardScaler#数据预处理包


#读数据
data=np.loadtxt("aqi2.csv",delimiter=",",skiprows=1,dtype=np.float32,)
X=data[:,1:]#特征集  二维矩阵
Y=data[:,0]#目标集
x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.8)#随机的体现

#数据预处理

#生成一个标准化数据对象,可以对每一个特征维度二维化
scaler=StandardScaler()
scaler.fit(x_train) #计算均值和方差,标准差
# print(x_train)

x_train=scaler.transform(x_train)#得到标准化的矩阵
# print(x_train)


#用SGD模型训练,更新参数
sgd=SGDRegressor()#生成SGD对象
sgd.fit(x_train,y_train)


#预测
y_predict=sgd.predict(x_test)

#绘制
plt.scatter(np.arange(100),y_test[:100])  #真实值
plt.scatter(np.arange(100),y_predict[:100],c="green")  #预测值
plt.show()

#模型评价
print("mae",mean_absolute_error(y_test,y_predict))
print("mse",mean_squared_error(y_test,y_predict))
print("median-ae",median_absolute_error(y_test,y_predict))
print("r2",r2_score(y_test,y_predict))

4.5过拟合和欠拟合

  • 机器学习中一个重要的话题便是模型泛化能力,泛化能力强的模型才是好模型。 对于徐连好的模型,若在训练集表现差,不必说在测试集表现同样会差,这可能是欠拟合导致;若模型在训练集表现非常好,却在测试集上差,这便是过拟合导致。过拟合与欠拟合也可以用Bias与Variance的角度来解释,欠拟合会导致高Bias,过拟合会导致高Variance,所以模型需要在Bias与Variance之间做出一个权衡

  • 使用简单的模型取拟合复杂数据时,会导致模型很难拟合数据的真实分布,这时模型便欠拟合了,或者说有很大的Bias,Bias即为模型的期望输出与真实输出之间的差异;有时为例得到比较精确的模型而过度拟合训练数据,或者模型复杂度过高时,可能脸训练数据的噪音也拟合了,导致模型在训练集上的效果非常好,但泛化性能却很差,这时模型便过拟合了,或者说有很大的Variance,这时2模型在不同训练集上的得到的模型波动比较大,Variance刻画了不同训练集得到的模型的输出与这些模型期望输出的差异

//

  • 解决过拟合。

    • 丢弃一些不能帮助我们正确预测的特征,可以时手工选择保留那些特征,或者使用一些模型选择的算法来帮忙

    • 正则化。保留所有的特征,但是减小参数的大小

  • 正则化
    //其中$\lambda$又称为正则化参数,如果$\lambda$选取过大,会把所有的参数$\theta$均最小化,造成欠拟合。如果$\lambda$选取过小,会导致对过拟合问题解决不当,因此$\lambda$的选取很重要

  • 岭回归:加入正则化项(加上所有参数(不包括$\theta_0$)的平方和,即l2范数的回归,叫做岭回归。因为$\theta_0$是偏置

  • 对岭回归损失函数求偏导(岭回归梯度下降算法)
    //
    最终得到的$\theta_j$的更新方程为:
    $$(1-\frac{a\lambda}{m})\theta_j-\frac{a}{m}\sum_{i=1}^m(h_0(x_i)-y_i)x_{ij}$$

向量化表示:
$$\theta=(X^T X+\lambda I){-1}(XTy)$$
化为:
$$\theta=(X^TX+\lambda \begin{pmatrix}
0 & & & & &\
& 1 & & &\
& & 1 & &\
& & & ... &\
& & & & 1\
\end{pmatrix}){-1}XTy$$

\

  • lss回归,就是把正则项改为了一次绝对值(L1范数)
    \

\

5. 对数几率回归

广义线性模型:
$$y=g{-1}(wTx+b)$$
g(.)单调可微。

考虑而二分类任务,其输出标记$y \epsilon$ {0,1},而线性回归模型产生的预测值z=$w^Tx+b$是真实值,于是,我们需要将实值z转换为0/1值,最理想的是“单位阶跃函数“
//

但是单位阶跃函数是不连续的,因此不能直接用g(.)
,从而又了一定的替代函数,对数几率函数$y= \frac {1}{1+e^{-z}}$,且是单调可微的。

//
sigmoid函数形似S的函数,对率函数是Sigmoid函数最重要的代表。

  1. 把一般线性表达式代入sigmoid函数中有
    $$y=\frac {1}{1+e{-(wTx+b)}}$$
  2. 对两边同时取对数化简有:
    $$ln\frac{y}{1-y}=w^Tx+b$$
  3. 而二分类问题中的y有{0,1}两种可能,所有y和1-y则分别为目标值的两种可能,$\frac{y}{1-y}$则是两者的比
  4. $\frac{y}{1-y}$称为几率,反映2了x作为正例的相对可能性(y相对于1-y的可能性大小),对几率取对数就有了:对数几率 $ln\frac{y}{1-y}$

如何确定w,b

  1. 若将y视为类后验估计p(y=1|x)则有:
    $$ln\frac{p(y=1|x)}{p(y=0|x)}=w^T+b$$

  2. 分别表示y=0和y=1:
    $$p(y=1|x)=\frac {e{wTx+b}}{1+e{wTx+b}}$$
    $$p(y=0|x)=\frac {e{wTx+b}}{1+e{wTx+b}}$$

  3. 然后用极大似然法来估计w,b.给定数据集${(x_i,y_i)^m_{i=1}}$,对率回归模型最大化”对数似然“,有似然项:
    $$\iota(w,b)=\sum^m_{i=1}lnp(y_i|x_i;w,b)$$
    即令每个样本数据其真实标记的概率越大越好,为便于讨论,令$\beta=(w;b),\hat x=(x;1),则wT+b可简写为\betaT\hat x.令p_1(\hat x;\beta)=p(y=1|\hat x;\beta),p_0(\hat x;\beta)=p(y=0|\hat x;\beta)=1-p_1(\hat x;\beta)$
    则似然项可重写为:
    $$p(y_i|x_i;w,b)=y_ip_1(\hat x_i;\beta)+(1-y_i)p_0(\hat x_i;\beta)$$

$p(y_i|x_i;w,b)=y_ip_1(\hat x_i;\beta)+(1-y_i)p_0(\hat x_i;\beta)$ ,带入$\iota(w,b)=\sum^m_{i=1}lnp(y_i|x_i;w,b)$可有:
$$\iota(\beta)=\summ_{i=1}(-y_i\betaT \hat x_i+ln(1+e{\betaT \hat x_i}))$$

  1. 极大自然法(补充)(可忽略)
    //
    //
    由3 可得:
    $$p(y=1|x)=\frac{e{\betaT \hat x}}{1+e{\betaT \hat x}}=p_1(\hat x;\beta)$$
    $$p(y=0|x)=\frac{1}{1+e{\betaT \hat x}}=p_0(\hat x;\beta)$$

又如果,样本y时独立同分布的,则可以用伯努利表示为:
$$p(y|x;w,b)=yp_1(\hat x;\beta)+(1-y)p_0(\hat x;\beta)$$
或者
$$p(y|x;w,b)=[p_1(\hat x;\beta)]^y[p_0(\hat x;\beta)]^{1-y}$$

在根据似然函数定义:
$$lnL(w)=\sum^m_{i-1}lnf(y_i,w_1,w_2,...,w_k)$$

由于此时y为离散型,所以将对数似然函数中的概率密度函数转换为分布律:
$$\iota(w,b):=lnL(w,b)=\sum^m_{i=1}lnp(y_i|x_i;w,b)$$

则综上有:
$$\iota(\beta)=\sum^m_{i=1}ln(y_ip_1(\hat x;\beta)+(1-y_i)p_0(\hat x;\beta))$$

  • 证明方式一有:
    //
    //

  • 证明访问式二:
    //
    //

所以:
$$\iota(\beta)=\sum m_{i=1}(y_i\betaT\hat x_i-ln(1+e{\betaT \hat x_i}))$$
由于是求损失函数最小,所以将使得样本概率最大的似然估计方程添加"-"就求得了使之最小的w,b从而得到3 中最后的式子

  1. 最终求解:
    //

模型评价

  1. 对于二分类问题,可将样例根据其真实类别与学习器预测类别的组合划分为:真正例,假正例,反正例,假反例(TP,FP,TN,FN)满足:TP+FP+TN+FN=样本数
    TP和TN是预测真确的。
    //
  • 查准率:
    $$ P=\frac{TP}{TP+FP}$$
    P表示我预测正确的正例在我预测正例中所占比
    $$ R=\frac{TP}{TP+FN}$$
    R表示我预测正确的正例在真实情况中正确的正例的比率

所以对于准确率,查准率,查全率,特异度有如下公式:
//

准确率和查全率关系:
//

  1. 通过ROC曲线的方式来评估分类模型。
  • ROC曲线横纵坐标范围为[0,1],通常情况下ROC曲线与X轴2形成的面积越大,表示模型性能越好,但是当ROC曲线处于下图中蓝色虚线的位置,就表明了模型的计算结果基本都是随机得来的,在此种情况下模型起到的作用几乎为零。故而在实际中ROC曲线离图中蓝色虚线越远表示模型效果越好
    //

交叉熵

信息量

衡量信息量的大小就看这个信息消除事件的不确定性的程度。信息量的大小和事件发生的概率成反比
可用如下公式表示:
$$I(x)=logp(x)$$

  • x表示事件,p(x)表示事件发生的概率

信息熵

信息熵为信源信息量的期望,****即该信源所有可能发生事件的信息量的期望。**
$$H(x)=-\sum^m_{i=1}p(x_i)logp(x_i)$$
性质:

  • 单调性:即发生概率的事件,其所携带的信息熵越低。例如:
    • “太阳从东方升起”,因为为确定事件,所以不携带任何信息量。从信息论的角度,认为这句话没有消除任何不确定性。
  • 非负性:即你得知了某个信息后,却增加了不确定性是不合逻辑的
  • 累加性:即多随机事件同时发生存在的总不确定性的量度是可以表示为各事件不确定性的量度的和

**信息熵是用来衡量信源不确定性的,信息熵越大,信源越具有不确定性,信源越复杂

对于一类特殊问题:0-1分布。所只有两种概率p(x)和1-P(x).则期望可以表示为:
$$H(x)=-p(x)logp(x)-(1-p(x))log(1-p(x))$$

相对熵

是两个概率分布差异的非对称度量。在信息理论中,相对熵等价于两个概率分布的信息熵的差值。
定义为:
$$KL(p||q)=\sum^m_{i=1}p(x_i)*log(p(x_i)/q(x_i))$$
可以看出:q分布与p分布越近,KL散度越小,相对熵越小

交叉熵

  • 对相对熵展开:
    $$KL(p||q)=\sumn_{i=1}p(x_i)logp(x_i-\sumn_{i=1}p(x_i)*logq(x_i))$$

  • 第一项可以写为真实分布的信息熵
    $$KL(p||q)=-H(p)+(-\sum^n_{i=1}p(x_i)*logq(x_i))$$

  • 由于第一项真实分布的信息熵为恒定值,所以在机器学习中只需要优化最后一项,这一项就是交叉熵:
    $$H(p,q)=-\sum^n_{i=1}p(x_i)*logq(x_i)$$

  • 同样,对于0-1分布问题,得到二进制交叉熵:
    $$H(p,q)=-p(x)logq(x)-(1-p(x))log(1-q(x))$$

机器学习中交叉熵loss意义

我们在线性回归中,经常使用均方差(MSE)loss,为什么在拟合分布时要采用交叉熵?下面进行分析:

  • 假设使用MSE来衡量预测分布于真实分布的差异,这里考虑简单的情况,单个样本:
    $$z=wx+b$$
    $$L=1/2(y-\mu(z))^2$$

    由于分布的概率值在(0,1)之间,所以在计算MSE时通常对预测值使用sigmod函数进行转换到(0,1)区间,sigmoid函数图像如下:
    //

    • 对其执行一次梯度下降,对L求关于x的偏导得到:
      $$\frac {\partial L}{\partial w}=-(y-\mu(z)) \mu{'}(z)x$$

      $$\frac {\partial L}{\partial b}=-(y-\mu(z)) \mu{'}(z)$$

    由sigmoid函数图像可以看出,z越接近0或1,曲线越平缓,即梯度越小,使得偏导数计算的值很小,严重降低了学习速度

  • 但如果用交叉熵loss:

    • $$L^{'}=-yloga-(1-y)log(1-a)$$

    • 同样求偏导有:
      $$\frac {\partial L^{'}}{\partial w}=(\mu(z)-y)x$$

      $$\frac {\partial L^{'}}{\partial b}=\mu(z)-y$$

    用交叉熵loss 求出的偏导数值于sigmoid函数的梯度无关,这也避免了均方误差loss的缺陷,所以在拟合分布时采用交叉熵loss

多分类问题

多分类问题一般由二分类问题推广。
例如对于有N个类别$C_I,C_2,C_3...C_n$.用“拆解法"将多分类任务拆为若干个二分类任务求解。

那对于数据集$D={{(x_1,y_1),(x_2,y_2),...(x_n,y_n)}}$如何拆分:

  • ”一对一“:将N个类别两两配对,从而产生N(N-1)/2 个分类任务,例如将$C_i,C_j$训练为一个分类器,该分类器把D中的$C_i$类样例作为正例,$C_j$类样例作为反例.在测试阶段,新样本将同时提交给所有分类器,于是我们将得到N(N-1)/2个分类结果,最终结果可通过投票产生,即把被预测得最多的类别作为最终分类结果。
  • ”一对多“:将其中一个类的样例作为正例,所有其他类的样例作为反例来训练N个分类器。在测试时若仅有一个分类器预测为正类,则通常考虑各
  • “多对多”

6.决策树

决策树基于"树"结构进行决策

  • 每一个内部结构 对应于某个属性上的”测试“
  • 每个分支对应于该测试的一种可能结果(即该属性的某个取值)
  • 每个叶节点对应于预测结果

学习过程:通过对训练样本的分析来确定”划分属性“

预测过程:将测试实例从根节点开始沿着划分属性所构成的”判定测试序列“下行2,知道叶节点。

决策树发展:
CLS-->ID3-->C4.5(最常用)-->CART(可回归)-->RF(森林,集成学习)

  1. 决策流程:
    自根至叶的递归过程
    在每个中间节点寻找一个划分属性

三种停止条件

  • 当前节点包含的样本属于同一类别,无需划分
  • 当前属性集为空,或是所有样本在所有属性上的取值相同,无法划分
  • 当前节点包含的样本集合为空,不能划分

//

  1. 基本算法
    输入:训练集$D={(x_1,y_1),(x_2,y_2),...,(x_m,y_m)};$
    属性集$A={a_1,a_,...a_d}$

过程:函数TreeGenerate(D,A)

  1. 生成结点node;
  2. if D中样本全属于同一类别C then
  3. $~~~~$将node标记为C类叶结点;return
  4. end if$~~~~$递归返回,情形(1)
  5. if A=$\varnothing$ OR D中样本在A上取值相同 then
  6. $~~~~$将node标记为叶结点,其类别标记为D中样本数最多的类;return
  7. end if$~~~~$递归返回情形(2)
  8. 从A中选择最优划分属性a;(决策树算法核心)
  9. for $a_$的每一个值$a_^v$ do
  10. $~~~~$为node生成一个分支;令$D_v$表示D中在$a_$上取值为$a_^v$的样本子集;
  11. if $D_v$为空 then
  12. $~~~~$将分支结点标记为叶结点,其类别标记为D中样本最多的类;return 递归返回,情形(3)
  13. else
  14. $~~~~$以TreeGenerate$(D_v,A{a_*})$为分支结点
  15. end if
  16. end for

过程中,最关键的就是第八行 --如何选择最优划分属性,一般而言,随着划分过程不断进行,我们希望决策树的分支结点所包含的样本尽可能属于同意类别,即结点”纯度“越来越高

6.2 信息量

信息量的两个特征:

  • 一个事件的信息量于这个事件发生概率是呈负相关的
  • 如果两个事件X,Y的发生没有相互影响的关系(两个事件不相关),****则信息量满足可能性:I(X,Y)=I(X)+I(Y)**

由于我们知道两个不相关事件X,Y发生的概率满足公式:P(X,Y)=P(X)+P(Y)

上诉联系对于事件X,Y而言,用log对数可以满足加法2与乘法联系
信息量与概率可能有此函数关系:$I(X)=log_2(P(X))$

又由于信息量的另一个特征:可有$I(X)=-log_2(P(X))$

$$I=-logP$$

6.3 信息熵

--平均信息量

信息熵表示:
假设一个事件D有n种可能情况记为:$(x_1,x_2,...,x_n)$

发生的概率记为:$(p_1,p_2,...p_n)$

D事件的信息熵,用info(D)表示,在由平均信息量表示为:
$$Info(D)=\sum^n_{i=1}P_iI_i$$

由$I=-logP$有:
$$Info(D)=-\sum^n_{i=1}P_ilog_2(P_i)$$

熵越小,数据的类别越纯

信息熵是度量样本集合“纯度”最常用的一种指标

假定当前样本集合D中第K类样本所占比例为$p_k$,则D的信息熵定义为:
$$Ent(D)=-\sum_{K=1}^{|y|}p_klog_2p_k$$

最纯的时候,只有$p(x_1)=1$ 是,信息熵(最小值)为0
当$x_1=x_2=..=x_n=1/n$是,信息熵最大,$log_2|n|$

6.4 信息增益

而信息增益直接以信息熵为基础,计算当前划分对信息熵所造成的变化

假设某一个离散属性a取值为:${a1,a2,...a^n}$
$D_v$:D中在a上的取值=$a_v$的样本集合

以属性a对数据集D进行划分所获得的信息增益为:
$$Gain(D,a)=Ent(D)-\sum_{v=1}^V \frac{|Dv|}{|D|}Ent(Dv)$$

  • Ent(D):是划分前的信息熵
  • $\sum_{v=1}^V \frac{|Dv|}{|D|}Ent(Dv)$ 划分后的信息熵
  • $\frac{|D^v|}{|D|}$:第v个分支的权重,样本越多越重要
  • V:是以属性a分类的种类数

计算信息增益实例:

  • 按A划分:
    //

信息增益本质:

  • 就是最原始的熵减去分类后各个部分加权的熵,我们的目的就是使得每个部分的熵最小,即每个部分尽可能属于同一类(越纯),则最后的信息增益越大。

所以我们可以用信息增益来进行决策树的划分属性选择,即上图决策树算法中第8行选择属性$a_*=argmaxGain(D,a)$,这就是ID3决策数学习算法--以信息增益为准则来选择划分属性

例子:
//
//
//
//

ID3(迭代二分器)

  1. 从根节点开始,对结点计算所有的特征信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子节点;
  2. 再对子节点递归调用以上方法,构建决策树
  3. 知道所有的特征的信息增益均很小(小于阈值)或没有特征可以选择为止。

sklen实现ID3决策树代码

'''
用ID3决策数,分类breast-cancer-wisconsin数据集
'''

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score,recall_score,roc_curve


#读数据  预处理
def preprocess(path):
    #读数据
    data=pd.read_csv(path)
    #去重
    data=data.drop_duplicates()
    #处理异常值(?)一般将?替换为NAN
    print(np.sum(data.isnull()))#判断数据集的NAN值,并计算个数

    data=data[data!="?"]#将?设置为NAN

    print(np.sum(data.isnull()))

    #将NAN值替换为真实值
    data=data.fillna(method="pad",axis=0)#用上一行的对应值填充(bfill:下一个非缺失值)
    print(np.sum(data.isnull()))


    #处理数据类型(强制转换为整型)
    data=data.astype(int)

    #取出因变量与自变量
    X=data.iloc[:,1:-1]
    Y=data.iloc[:,-1]

    #替换标签(2->0,4->1)
    Y[Y==2]=0
    Y[Y==4]=1

    #数据划分
    x_train,x_test,y_train,y_test=train_test_split(X,Y,train_size=0.8)
    return x_train,x_test,y_train,y_test

#评价指标
def score(y_predict,y_test):
    print("精确率评价指标:",precision_score(y_test,y_predict))
    print("召回率:",recall_score(y_test,y_predict))
    fpr,tpr,thresholds=roc_curve(y_test,y_predict)
    plt.xlim(0,1)
    plt.ylim(0,1)

    plt.plot(fpr,tpr,c="red")
    plt.show()

def show_plot(y_predict,y_test):
    plt.rcParams["font.sans-serif"]=['SimHei']
    plt.title("绘制真实值与预测值")
    plt.xlabel("数量编号")
    plt.ylim("类别")
    plt.plot(range(len(y_predict)),y_predict,c="blue")#预测值

    plt.plot(range(len(y_test)),y_test,c='green')#真实值
    plt.legend(["预测值","真实值"])
    plt.show()


#决策数算法
def desicionTree(x_train,x_test,y_train,y_test):
    clf=tree.DecisionTreeClassifier(criterion="entropy")#entropy:information gain
    clf.fit(x_train,y_train)
    y_predict=clf.predict(x_test)


    #正确率
    print(np.sum(y_predict==y_test)/len(y_predict))

    return y_predict



if __name__=="__main__":
    x_train,x_test,y_train,y_test=preprocess("breast-cancer-wisconsin.data")
    y_predict=desicionTree(x_train, x_test, y_train, y_test)
    score(y_predict, y_test)
    show_plot(y_predict,y_test)

6.5 连续值处理和C4.5决策树

连续属性的可取值时无限的,所以不能直接根据连续属性来对结点进行划分。但可将连续属性离散化,二分法对连续值处理,也是C4.5决策树算法中采用的机制

eg:
给定样本集D和连续属性a,属性a从小到大排序为${a1,a2...an}$.然后基于划分点t可将D分为子集$D_t-$和$D_t^+$.

  • $D_t^-$时那些在属性a上取值不大于t的样本。
  • $D_t^+$则包含在属性a上取值大于t的样本。

对于相邻的属性取值$ai与a$来说,t在区间$[ai,a]$中取任意值所产生的划分结果相同。因此,对于连续属性a,我们可考察包含n-1个元素的候选划分点集合
$$T_a={\frac{ai+a{i+1}}{2},1<=i<=n-1}$$

即把区间$[ai,a]$的中位点$\frac{ai+a{i+1}}{2}$作为候选划分点,然后,我们就可向离散属性值一样来考察这些划分点。选取最优的划分点进行样本集合的划分。例如,上式可变为:
$$Gain(D,a)=max_{t\in T_a} Gain(D,a,t)
=max_{t\in T_a}Ent(D)-\sum_{\lambda \in {-,+}} \frac{|D_t^\lambda|}{|D|} Ent(D_t^\lambda)$$

其中 Gain(D,a,t)是样本集D基于划分点t二分后的信息增益,于是,我们就可选择使Gain(D,a,t)最大化的划分点

例如在对一下西瓜的连续值用二分法做决策树:

//
//
//

再例如:
//

  1. ID3算法缺点:
    例如,对于以上使用的西瓜数据中,如果把表中编号这一列作为一个划分属性。则计算出的信息增益是0.998,远大于其他候选划分属性。所以编号为根节点产生17个分支。每个分支点仅包含一个样本,这些分支结点的纯度已达最大。然而这样的决策树不具有泛化能力,无法对新样本进行有效预测。

以信息增益划分准则的ID3决策树对可取值数据较多的属性有所偏好
$$Gain(D,a)=Ent(D)-\sum_{v=1}^V \frac{|D^v|}{|D|} Ent(D^v) \
=Ent(D)-\sum_{v=1}^V \frac{|Dv|}{|D|}(-\sum{k=1}p_klog_2p_k) \ =Ent(D)-\sum^V \frac{|Dv|}{|D|}(-\sum_{k=1}\frac{|D_kv|}{|Dv|}log_2\frac{|D_kv|}{|Dv|})$$

  • 其中$D_kv$样本集合D中在属性a上取值为$av$且类别为k的样本
  1. C4.5决策树---**是以信息增益率(类似于规范化)为准则来选择划分属性的决策树。
    信息增益率:
    $$Gain_raio(D,a)=\frac{Fain(D,a)}{IV(a)}$$
    其中
    $$IV(a)=-\sumV_{v=1}\frac{|Dv|}{|D|}log_2\frac{|D^v|}{|D|}$$

信息增益准则可对取值数目较多的属性有所偏好,为减少这种偏好可能带来的不利影响,著名的C4.5决策树算法不直接使用信息增益率,而是使用“增益率”来选择最优划分属性.

  1. $IV(a)=-\sumV_{v=1}\frac{|Dv|}{|D|}log_2\frac{|D^v|}{|D|}$称为属性a的”固有值“属性a的可能取值数目越多(即V越大)则IV(a)的值通常会越大,例如以上的西瓜数据集中:
    $IV(触感)=0.874(V=2),IV(色泽)=1.580(V=3),IV(编号)=4.088(V=17)$**观察有:编号的IV最大,但是增益率是把IV做分母成反比,则增益率越小。所以就避免了IB3决策树的缺点

C4.5例子:
//

6.6 CART决策树和基尼指数

CART决策树使用基尼指数来选择划分属性
则以数据集D的纯度可用基尼值来度量:
$$Gini(D)=\sum^{|y|}{k=1} \sum{k^\not= k}p_kp_{k^} \
=1-\sum{|y|}_{k=1}p_k2$$

直观来说,Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率。因此,Gini(D)越小,则数据集D的纯度越高。
基尼指数:
$$Gini_index(D,a)=\sumV_{v=1}\frac{|Dv|}{|D|}Gini(D^v)$$
于是,我们在候选属性集合A中,选择那个使得划分后的基尼指数最小的属性作为最优划分属性,即$a_*=argmin_{a\in A} Gini_index(D,a)$

CART决策树回归算法:

  1. 根据一下公式找出最优划分特征a和最优划分点a_^v:
    $$a_
    a_8v=argmin_{a_*,av}[ming_{c_1}\sum_{x_i \in D_1(a,av)}(y_i-c_1)2-min_{c_2}\sum_{x_i \in D_2(a,av)}(y_i-c_2)2]$$
    其中,$D_1(a,av)$表示在属性a上取值小于等于av的样本集合,$D_2(a,av)$表示在属性a上取值大于$av$的样本集合,$c_1$表示$D_1$的样本输出均值,$c_2$表示$D_2$的样本输均值

  2. 根据划分点$a_*^v$将集合D划分为$D_1和D_2$两个集合(结点)

  3. 对集合$D_1和D_2$重复步骤1和2,直至满足条件。

过程: 计算所有项的Gini值--->如果该节点本身得分最低,则没必要再分离,该节点就是叶子节点---->如果分离数据话可以改进,则选择不纯度最低的分离

eg:
1.

  • 看出是否胸痛中对应心脏病数量
    //

  • 各个属性中对应的心脏病树
    //

  • 胸痛中计算是否胸痛的对应基尼值
    //

  • 再将对应基尼值乘以权重,再求之和,得到总的基尼指数
    //

  • 照上面求出各个属性对应的总基尼指数,比较找出最小的就是最纯的,作为根节点
    //

  • 再根节点的分支中对饮的属性求基尼指数并比较找出最小的作为下一个根节点。
    //

  • 当基尼指数足够小时就可以停止划分(防止过拟合)作为叶结点。
    //

  • 按以上递归求出决策树
    //

  1. 对于连续值也可以求基尼指数:
    //

  2. 数据较小的连续值也可以这样求解:
    //

  3. 多个类别的离散数据处理
    //

6.7 剪枝,划分选择

  • 划分选择:基尼or增益,对泛化性能的影响有限。
    两者仅在2%的情况下不同。

  • 但是剪枝和程度对决策树泛化性能的影响更显著。剪枝是决策树解决过拟合的主要手段

决策树分类过细。可以通过主动去掉一些分支来降低过拟合风险

基本策略:

  • 预剪枝:提前之中某些分支的生长
  • 后剪枝:生成一个完全树,再“回头”剪枝

评估剪枝前后的优劣。---流出法

  • 有一下数据集:
    //

  • 对于验证集:
    脐部,划分前的验证集,准确率是42.9%
    //
    按一下决策树的分类标准,划分后的验证集,准确率是71.4%
    //

预剪枝:所以比较前后划分的准确率提高了,所以就可以画出该结点分支
//
在进行划分的话,同样计算划分前后的精度来判断是否划分。

后剪枝:先做出决策树,来从下到上计算剪枝前后的精度,来判断是否剪枝。
//

最后得到:
//

总结:

  1. 预剪枝:
  • 训练时间开销降低,测试时间开销降低
  • 过拟合风险降低,欠拟合风险增加
  1. 后剪枝:
  • 训练时间开销增加,测试时间开销降低
  • 过拟合风险降低,欠拟合风险基本不变
  1. 泛化性能:后剪枝>预剪枝

7聚类 k-means

7.1 聚类算法概述

  1. 有监督学习:
    • 有标签的训练集。(x属性有标签,例如男,女)
    • 根据标签拟合一个假设函数
    • 找到区分正负区间的决策边界

例如训练集:
$$TraningSet:{(x1,y1),(x2,y2)...(xn,yn)}$$
可以根据x-->y,有可以参考的y目标值

  1. 无监督学习
    • 没有任何标签
    • 没有任何标签y
    • 只有一个数据集

例如一个训练集:
$$TraningSet:{x1,x2...x^n}$$
只有一堆数据集,而没有目标值,需要做到就是对这写数据进行分类,贴标签

  1. 聚类算法概念
    是研究“物以类聚”的一种现代统计分析方法。
    也是数据挖掘,研究样品指标的分类方法。

分类原则:将较大相似性的对象归为一类,将差异较大的个体归为不同类。

如何确定数据的相似性?

  • 可以把每一个样本看作p维空间的一个点
  • 计算空间距离。将距离较近的归为一类,距离较远的归为一类

所以如何定义距离就是解决数据相似性的关键

  1. 欧式距离

最简单的距离计算方法。

  • eg: 两点距离公式
    $$d_{12}=\sqrt{(x_1-x_2)2+(y_1-y_2)2}$$

  • 可以将其推广为p维的两点距离公式$a(x_{11},x_{12},...x{1n})和b({x_{21},x_{22},...,x_{2n}})$
    $$d_{12}=\sqrt{(x_{11}-x_{21})2+(x_{12}-x_{22})2+...+(x_{1n}-x_{2n})^2}$$

    化简有:
    $$d12=\sqrt{\sum_{k=1}n(x_{1k}-x_{k})2}$$

    向量形式有:
    $$d_{12}=\sqrt{(a-b)(a-b)^T}$$

7.2 K-means算法

是一种快速聚类算法。将每个样品分给最近中心(均值)的类中。

  • k :聚类数量
  • 训练数据集:${x_1,x_2,...,x_n}$

K-maens步骤:

  1. 选择k个随机点,称为聚类中心
  2. 计算每一个数据距离k个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类
  3. 计算每一个组的平均值,将该组所关联的中心点移动到平均值的位置
  4. 循环2,3步骤直到中心点不在变化。

K-means伪代码

Repeat{
  for i=1 to m
  ci;//与第i个实例数据最近的聚类中心的索引

for k=1 to k
Uk:=聚类中心//对聚类中心更新

min||xi-Uk||^2
ci=k //计算最近距离并赋值非ci

K-means优化

  • k均值最小化问题,是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和

  • k-均值的代价函数(又称畸变函数):
    $$J(c,u)=\summ_{i=1}||xi-u_{ci}||2$$
    $u_k:与x^i$最近的聚类中心点

  • 优化目标
    $$min J(c1,...,cm,u_1...,u_k)$$

在运行k-均值算法的之前,首先要随机初始化所有的聚类中心点

  1. 我们应该选择$k<m$,即聚类中心点的个数要小于所有训练集实例的数量
  2. 随机选择k个训练实例,然后令k个聚类中心分别与这k个训练实例相等

局部最优问题:可能会停留在一个局部最小值处。需要多次运行k-均值算法,每一次都重新进行随机初始化。

聚类k的选择:在对一组数据集使用该算法时,需要先确定k的数量,即想要分为几类。

肘部法则-->来选择聚类数
//

scikit-learn中的K-means算法

KMeans()中的参数:

  • n_clusters:指定任意的质心数,就是k值
  • max_iter:迭代得到最终k的次数
  • n_init:初始化次数
  • init:k初始化方法:任意指定k值的选取用参数(random),默认的“k-means++"是一种特殊的初始化方法,可以提高收敛速度
  • algorithm
  • random_state:相当于随机数种子

K-means中的属性:

  • cluster-sent:array.[n_cluster.n_features]。聚类中心的坐标
  • labels:样本簇类别
  • inertia:float类型,样本到最邻近聚类中心的平方之和。

K-means中的方法:

  • fit(x[,y]):k-均值聚类计算 。return kMeans对象
  • fit_predict(x[,y]):计算聚类中心并预测每个样本的类别. return array.shape[n_samples,]
  • fit_transform(x[,y]):计算聚类并计算x到各个中心点的距离。return array.shape[n_samples,k]
  • predict(x):预测x中每个样本属于哪个类别。
  • return array.shape[n_samples,]
  • transfrom(x):计算x到各个中心点距离.return arrat.shape[n_samples,k]

算法实现sklearn

import random

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

#sklean中生成数据集的包
from sklearn.datasets import make_blobs
#x为生成的样本,y就是样本的类别。共1000个样本。每个样本2个特征。共4个簇。簇中心就在[-1,-1],[0,0],[1,1],[2,2]
x,y=make_blobs(n_samples=1000,centers=[[-1,-1],[0,0],[1,1],[2,2]],n_features=2,cluster_std=[0.4,0.2,0.2,0.1],random_state=0)

k=5
kmeans=KMeans(n_clusters=5,random_state=9)

#得到距离k的中心点的距离的矩阵
distance=kmeans.fit_transform(x)

#得到每个样本所属的类别列表,如:array(0,0,1,...)
y_pred=kmeans.fit_predict(x)

#聚类评价
from sklearn import metrics
score=metrics.calinski_harabasz_score(x,y_pred)
print(score)



#可视化
#在图标上显示文字的
plt.text(0.99,0.1,('k=%d,score:%0.2f'%(k,score)),transform=plt.gca().transAxes,size=20,horizontalalignment="right")

#在每个点上面显示文字
for a in range(50):
    plt.text(x[a,0]+0.001,x[a,1]-0.001,a+1)

#显示图标
plt.scatter(x[:,0],x[:,1],c=y_pred)

#取得每个k的中心点位置,并显示在图表上
centers=kmeans.cluster_centers_
plt.scatter(centers[:,0],centers[:,1],c="black",s=200,alpha=0.5)

plt.show()

但是如果时非球状的就无法分类:
//

8.集成学习

8.1集成学习概述

集成学习:把多个假设组合起来,得到一个更好的预测效果。

  • 简单的集成学习来说:
    • 分类:对于多个不同的分类器对同一个实例分类。可能得多多个不同的结果,则按把此实例划分为某一类的次数做多的一类为集成学习得到的一类。
    • 回归:则不同算法对某一个实例进行回归,按照他们所有的平均值处理得到的结果为集成学习的结果。
  1. 弱学习器:

    • 简单分类问题1:
      //

    如果只按照用一条直线分类,是达不到最佳分类效果的。
    //

    但是如果用以上图的组合方式就可达到最优。

通过不同的假设结合,得到更好的预测模型

  • 简单分类问题2:
  • //
    如果有多条满足条件的分类线.则要从其中找到一条最优线。(以投票的方式进行组合选择)

问题1:集成了所有的弱学习器(单学习器)。提高了预测模型能力。起到了特征转换的效果。

问题二:显示了集成学习的正则化的效果,让模型更加具有代表性。

弱学习器只能倾向于特征变换和正则化之一,集成学习是两者之间的权衡。

  1. 集成学习通过构建并结合多个学习器来完成学习任务,也称多分类器系统。

  2. 个体学习器被称为弱学习器,多个弱学习器可以按照如图的结构进行结合,形成强学习器。

几种常见集成结合方式:
//

根据分类器的生成方式划分,集成学习分为两大类:

  • 个体学习器之间存在着2很强大依赖关系,必须串行生成的方法,代表是Boosting.
  • 另一种不存在强大的依赖关系,可以同时生成并行化的方法,代表是Bagging和Random Forest

8.2 Boosting(演化)和adaBoosting

Boosting结构图:
//

基本流程:

  1. 首先给训练集一个初始权重训练出一个弱学习器1,根据弱学习器的学习误差率表现对训练样本分布(权重)进行调整。使得弱学习器1做错的训练样本在后续得到更多关注。
  2. 然后基于调整后的样本分布来训练弱学习器,如此重复进行,直到弱学习器数达到事先指定的数目T,最终将这个弱学习器进行加权结合,得到最终的强学习器。

Boosting族算法最著名的算法是:AdaBoost.AdaBoost就是 损失函数为指数损失的Boosting算法

AdaBoosting算法流程:

输入:训练数据集$T={(x_1,y_1),(x_2,y_2),...,(x_n,y_n)}$,其中$x_i \in X \subseteq R^n,y_i \in Y =-1,1$,迭代次数M(X:是特征集,x_i:某一个样本,)

  1. 初始化训练样本的权值分布$D_1=(\omega_{11},\omega_{12},\omega_{13}...,\omega_{1i}),\omega_{1n}=\frac {1}{N},i=1,2,...,N.$
    ($\omega_{1,i}$表示的是第一轮的第n个样本的权值)
  2. 对于m=1,2,...,M轮
  • 使用具有全职分布$D_m$的训练数据集进行学习,得到弱分类器$G_m(x)$(例如 第3轮,用$D_3=(\omega_{31},\omega_{32},\omega_{33}...,\omega_{3n})$这个权值取分布的训练集进行学习,得到弱分类器G_3)

具体详细计算公式如下:

  • 计算$G_m(x)$在训练数据集上的分类误差率(更新系数):
    $$ e_m=\sum ^N_{i=1} \omega_{m,i}I(G_m(x_i) \not =y_i)$$
    以上公式其中,$G_m(x_i)$使用弱学习器进行学习预测处的$y_pre$与真实值$y_i$进行判断如果相等返回0,不等返回1.
    不等就是把预测错误的实例的权值加起来得到$e_m$

  • 计算$G_m(x)$在强分类器中所占权重(每一轮弱分类器的权重所占比)
    $$a_m=\frac{1}{2}log\frac{1-e_m}{e_m}$$

  • 更新训练数据集的权值分布(这里,$z_m$是归一化因子,为了使样本的概率分布和为1):
    $$w_{m+1,i}=\frac{\omega_{m,i}}{z_m}e^{(-a_my_iG_m(x_i))},i=1,2,...,10$$
    $$z_m=\sum^N_{i=1}\omega_{m,i} e^{(-a_my_iG_m(x_i))}$$
    本质上:对于实例权值的更新是对误分类的点提升权重(权重$*e{a_m}/Z_m)$,正确分类的点降低权重(权重*$e/Z_m)$

详细解读:对于$e_x$函数而言,误分类可以看作$G_m(x_i)$为1$y_i$为-1(或者相反)反正乘积为-1,加上前面的负号,所以$e_x$的值是大于1的,而对于正确的分类则相反$e_x$是小于1的,所以权重乘以一个大于1的数,权重上升了,所以误分类的权重提升。反之正确分类的权重下降了。
$z_m$就是所有权重的和

  • 最终得到分类器
    $$F(x)=sign(\sum^N_{i=1}a_mG_m(x))$$
    就是对每一轮所训练用的弱分类乘以对应弱分类器所占权重的和再求sign

sign:符号运算,图如下:
//

以上使用的是0-1损失函数:非凸,非连续,数学性质差
除此自外还有:

  • hinge损失:$f_{hinge}(z)=max(0,1,-z)$
  • 指数损失:$f_{exp}(z)=exp(-z)$
  • 对率损失:$f_{log}(z)=log(1+exp(-z))
    图如下:
    //

指数损失函数是分类任务原本0/1损失函数的一致损失函数。且具有更好的数学性质,用它替代0/1损失函数作为优化目标。

AdaBoosting实例:

  • 有10个样本的二分类数据集D_1,D_1分布上的初始权重统一,每个点具有相同的权重均为1/10
    //

  • 第一轮(第一次迭代):

    • 根据弱分类器$h_1$分类出图二(中间的)。其中+分对了两个,分错了3个。-号全部分为一类。所以根据错误率计算公式$e_m=\sum ^N_{i=1} \omega_{m,i}I(G_m(x_i) \not =y_i)$算出e_1为0.3。再根据弱分类器在强分类器中所占比公式计算该轮弱分类器的权重$a_m=\frac{1}{2}log\frac{1-e_m}{e_m}$ $a_1$是$1/2ln((1-e_m)/e_m)=0.42$

    • 误分类的点提升权重(权重乘以$e{a_1}$除以$z_1$)。正确分类的点降低权重(权重乘以$e$除以$z_1$)$w_{m+1,i}=\frac{\omega_{m,i}}{z_m}e^{(-a_my_iG_m(x_i))},i=1,2,...,10$
      所以带入数据有:

    1. $z_1$:对的:7×0.1×$e{-0.42}$(对的个数乘上其中实例所占权重比乘上e的弱学习器所占权重次方的倒数)。错的:3×0.1×$e$(错的个数乘上其中实例所占权重比乘上弱学习器所占权重比次方)。在对其求和得到$z_m$=0.916
    2. 分母求了再求正确分类的分子和误分类的分子。误分类:0.1× $e{0.42}/z_1$=0.1659.正确分类的:0.1×$e/z_1$=0.07
    • 所以经过第一轮计算后,这时样本的权重发生了改变。在第一轮分正确的权重变为了0.07.在第二轮分错误的权重变为了0.1659。然后按照这个新的权重进行下一轮的学习
  • 第二轮(第二次迭代):
    //

    • 根据第二种弱学习器$h_2$分类出图二(中间的)。再通过第一轮的同样操作计算得出:$e_2=0.21,a_2=0.65,...$
    • 在又得出新的实例所在权重和弱学习器所占权重。
  • 第三轮(第三次迭代):

    • 用同样的操作计算出新的权重比。
  • 如果到此停止,进行了三次迭代和使用了三个分类器,在对其集成得到强分类器。
    三个弱分类器的分类图为:

  • //

集成得到的强分类器:
//

  • 最终分类器是所有带权重的弱分类器组合
  • 多个弱分类器组合成一个强的非线性分类器

总结:boosting:
训练过程为阶梯状,基模型的训练集按照某种策略每次都进行一定转化。对所有基模型预测的结果进行线性综合产生最终的预测结果。
//

总结:Adaboosing:

  • 欲得到泛化能力强的集成学习器,个体弱学习器应该尽可能相互独立
  • 但在现实任务中无法做到,可以设法使弱学习器尽可能具有较大的差异
  • 但在现实任务中无法做到,可以设法使若学习器尽可能具有较大差异
  • 给定一个训练集,最有可能的做法是对训练样本进行采样。产生若干个不同的子集,再从每个数据子集中训练出一个弱学习器,由于训练数据不同,获得的弱学习器可望具有较大差异。
    • 如果采样出的每个子集完全不同,每个弱学习器只能用到一小部分训练数据,显然无法保证产出比较好的弱学习器。
    • 为解决这个问题,可以考虑使用相互交叠的采样子集。这时可以用Bagging(袋装)解决这个问题

8.3AdaBoost实例预测乳腺癌数据

代码实例

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import AdaBoostClassifier
'''AdaBoostClassifier强学习器是将1多个弱学习器整合到一起的,所以也要导入弱学习器'''
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import precision_score,recall_score,roc_curve
import matplotlib.pyplot as plt

#预处理数据,读数据
def process_data():
    data=pd.read_csv("breast-cancer-wisconsin.data",delimiter=",")
    data = data.drop_duplicates()#去重
    data = data[data!="?"]#将?填充为缺失值
    data = data.fillna(method="pad",axis=0)#填充缺失值


    X=data.iloc[:,1:-1]
    y=data.iloc[:,-1]-3
    print(X)
    print(y)

    x_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.33)

    return x_train,x_test,y_train,y_test

#训练AdaBoost模型
def ada_model(x_train,x_test,y_train,y_test):

    ada = AdaBoostClassifier(DecisionTreeClassifier(max_depth=8),
                            n_estimators=50,
                           learning_rate=1,
                           algorithm='SAMME.R',
                            random_state=0
                            )
    '''
    n_estimators:弱分类器个数
    learning_rate:学习率
    algorithm:算法
    '''
    ada.fit(x_train,y_train)
    y_predict=ada.predict(x_test)

    print("准确率:",np.sum(y_predict==y_test)/len(y_test))

    return y_predict


#模型评价
def score(y_test,y_predict):
     print("精确率评价指标:",precision_score(y_test,y_predict))
     print("召回率评价指标:",recall_score(y_test,y_predict))

#可视化
def plot_show(y_test,y_predict):
    fpr,tpr,thresholds=roc_curve(y_test,y_predict)
    plt.xlim(0,1)
    plt.ylim(0,1)
    plt.plot(fpr,tpr,color='red')
    plt.show()

if __name__=="__main__":
    x_train, x_test, y_train, y_test=process_data()
    y_predict=ada_model(x_train, x_test, y_train, y_test)
    score(y_test,y_test)
    plot_show(y_test,y_predict)

上述例子中,使用决策树为弱分类器进行组合分类为强学习器。

9.4 Bagging(装袋)

使用Bagging的原因--****希望每个弱学习器个体相互独立有较大差异。**

Bagging原理:

  • 从原始训练集中随机采样(有放回)得到若干个子集,且每个子集都互不相干。
  • 弱学习器去训练的数据不一样,所训练的模型具有差异性。
  • 最后再合并多个弱学习器

实际过程

  1. bagging的个体弱学习器的训练集时通过随机采用得到的
  2. 通过T此随机采样,得到T个采样集
  3. 对于这T个采样集,分别独立的训练出T个弱学习器
  4. 在对这T个弱学习器通过几个策略来得到最终的强学习器

:弱学习器合并为强学习器的合并策略--

  1. 对回归任务使用简单平均法
  2. 对分类任务使用简单投票法

AdaBoosting与Bagging的差别:

  • Bagging是并联执行的,各个弱学习器之间没有关联:
    例图:
    //

  • AdaBoosting是串联执行的,有第一轮的弱学习器学习之后得到一个误差率,再调整训练集的权重,再在第二轮有调整的的训练集去训练第二个弱学习器再得到一个误差率并再次更新训练集权重。
    //

  • 并行与串行结构图
    //

Random Forest

  • 是Bagging的一个扩展变体,再RF以决策树为基学习器构建Bagging集成的基础上,进一步再决策树的训练过程中引入了随机属性选择

  • 具体来说,传统决策树再选择划分属性时再当前结点的属性集合(假定有d个属性)中选择一个最优属性

  • 在RF中,对决策树的每一个结点,先从该结点的属性集合中随机选择一个包含k个属性的子集,然后再从这个子集中选择一个最优属性用于划分

  • 图解:

//

  • 看图说话:
    首先从大的训练集D中随机选取包含k个属性的集合(例如:共有80个属性,随机选取50个子集(放回的)分别去用D1,D2,D3...训练。在合并决策树。

随机森林时根据决策树构建的
决策树优点:

  1. 易于解释
  2. 易于构建
  3. 易于使用

缺点:
预测准确率不高,无法称为预测学习的理想工具

随机森林例子:
随机森林结合了决策树的简单性和灵活性,大大提高准确性

  1. 步骤一:创建一个"bootstrapped"数据集

从大的数据集中去随机采样获取子集
//

  1. 步骤二:使用"bootstrapped"数据集创建决策树,但每步仅随机使用N个特征(或列)的子集
    //

  2. 重复步骤2得到由多棵采用不同数据集创建的决策树。

  3. 预测
    //。将待预测的数据带入到以上创建的多个决策树中分别预测。躲到多个结果。然后再投票(看决策树的结果中最多可能的结果就作为本次预测的结果)。
    //

总结:

bagging:从训练集从进行子抽样组成的每个及模型所需要的子训练集,对所有的基模型预测的结果进行综合产生最终的预测结果
//

注:每个子训练集时相互交叠的,有重复相交部分。每个模型是的独立并行的,独自运行独自的训练集互不相干,最后综合所有预测。

Bagging和Boosting的区别

  1. 从偏差-方差分解的角度看:
    • Boosting主要关注降低偏差,能基于泛化性能相当弱的学习器构建出很强大集合
    • Bagging主要关注降低方差,因此他在神经网络等易受样本扰动的学习器上效果更加明显
  2. 从训练集角度来看:
    • Bagging的训练集的选择是随机的,各轮训练集之间相互独立,采用均与取样
    • Boosting的各轮训练集的选择与前面各轮的学习结果有关,根据错误率取样
    • Boosting的分类精度要优于Bagging
  3. 从预测函数角度看:
    • Bagging的各个预测函数没有权重,而Boosting是有权重的。
    • Bagging的各个预测函数可以并行生成,而Boosting的各个预测函数只能顺序生成
  4. 从其他角度看:
    • 对于想神经网络这样极为耗时的学习方法,Bagging可通过并行训练节省大量时间开销
    • 两者都可以有效地提高分类的准确性,在大多数数据集中Boosting的准确性比Bagging高,但是有些数据集中,Boosting会导致过拟合

随机森林代码

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
from sklearn.metrics import precision_score,recall_score,roc_curve

#预处理包
from sklearn.preprocessing import LabelEncoder

#都数据,预处理数据
def process_data():
    data=pd.read_csv("bank-full.csv",delimiter=';')
    data.dropna()#删除空值
    keys=data.keys()
    keys=keys.drop(["day","month","pdays"])#删除不重要的特征

    #LabelEncoder().fit_transform()对一些文本进行编码
    data=data[keys].apply(LabelEncoder().fit_transform)

    X=data.iloc[:,:-1]
    Y=data.iloc[:,-1]
    x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.33)

    return x_train,x_test,y_train,y_test

#使用随机森林实现训练和测试
def forest_model(x_train,x_test,y_train,y_test):
     rfc=RandomForestClassifier(#给定一定的参数
         n_estimators=50,#弱学习器的个数
         criterion="gini",
         max_depth=8,#最大深度
         min_samples_leaf=2,
     )
     rfc.fit(x_train,y_train)
     y_preb=rfc.predict(x_test)

     print("准确率:",np.sum(y_preb==y_test)/len(y_test))
     return y_preb

#评价指标
def score(y_test,y_predict):
     print("精确率指标:",precision_score(y_test,y_predict))
     print("召回率指标:",recall_score(y_test,y_predict))

#可视化
def plt_show(y_test,y_predict):
    fpr,tpr,thresholds=roc_curve(y_test,y_predict)
    plt.xlim(0,1)
    plt.ylim(0,1)
    plt.plot(fpr,tpr)
    plt.show()

if __name__=="__main__":
    x_train, x_test, y_train, y_test =process_data()
    y_preb=forest_model(x_train,x_test,y_train,y_test)
    score(y_test,y_preb)
    plt_show(y_test,y_preb)

集成学习组合策略

三个好处:

  • 从统计方面来看,学习任务的假设空间很大,可能有多个假设在训练集上达到同等性能,若使用单学习器可能因误选而导致泛化性能不佳,结合多个学习器会减少这一风险
  • 从计算方面来看,学习算法往往会陷入局部最小,有的局部最小点对应的泛化性能可能很糟糕,通过多次运行后进行结合,可以降低陷入糟糕局部最小点的风险
  • 从表示方面看,某些学习任务的真是假设可能不在当前学习算法所考虑的假设空间中,若使用但学习器则肯定无效,通过结合多个学习器,由于相应的假设空间有所扩大,有可能学得更好的近似。

组合方式:

  • 投票法
    • 绝对多数投票
    • 相对多数投票
    • 加权投票法
  • 平均法
    • 简单平均法
    • 加权平均法

有${h_1,h_2,h_3...h_T},h_i$在示例x上的输出为$h_i(x)$,有如下几种常见组合策略:

  • 平均法,对于数值型输出$h_i(x)$,平均有:
    • 简单平均:
      $$H(x)=\frac{1}{T}\sum^Th_i(x)$$
    • 加权平均
      $$H(x)=\sum^T_{i=1}wh_i(x)$$

投票法:
//

  • 对于分类任务来说,学习器h_i将从类别标记集合${c_1,c_2..c_n}$中预测一个标记,我们将在h_i在样本x上预测值输出表示为一个N维向量$(h_i1(x),...,h_iN(x))$,其中$h_i^j$是h_i类别标记c_j上的输出

  • 投票方式有3种,分别是*绝对多数投票,相对多数投票和加权投票法

    1. 绝对多数投票:若标记得票超过一半,则预测为该标记,否则拒绝预测
    2. 相对多数投票:预测为得票最多的标记,同时多个标记得票最高则随机选取
    3. 加权投票:与加权平均类似
      $$H(x)=c_{argmax}\sumT_{i=1}w_ih_ij(x),w_i>=0,\sum^{i=1}_Tw_i=1$$

9.5 Xgboost算法

如何集成概述

  1. 基础模型:决策树模型
  2. 集成方法:并行构造多颗决策树?一个一个加!
  • 第一轮:$y_i^{0}=0$
  • 第二轮:$y_i1=f_1(x_i)=y_i0+f_1(x_i)$
  • 第三轮:$y_i2=f_1(x_i)+f+2(x_i)=y_i1+f_2(x_i)$
  • ...
  • 第t轮:$y_it=\sum_{k=1}tf_k(x_i)=y^{(t-1)}_i+f_t(x_i)$
  1. 一般的对于t轮模型预测,保留前面t-1轮的模型预测,并在此2基础上加上一个新函数$f_t(x_i)$.每一轮都是在之前一轮的基础上加上一个新函数。

  2. 关键问题在于,对于每一轮加入的函数到底是怎样的?

    • 目的:加入的新函数能够优化我的目标函数
      $$Objt=\sumn_{i=1}l(y_i,y_it)+\sumt_{i=1}\Omega(f_i) \
      =\sumn_{i=1}(y_i,y_i+f_t(x_i))+\Omega(f_t)+constant$$
    • 目标:找到$f_t$来优化这一目标
  3. 在4中的$\omega(f_t)$解释:对树模型的剪枝,加上了一个惩罚项(权重正则化),别让树模型太庞大
    $$\omega(f_t)=\gamma T+1/2\lambda \sumT_{j=1}w2_i$$

    • $\gamma$:限制叶子个数
    • $1/2\lambda \sumT_{j=1}w2_i$:w都L2模平方
      //
  4. 目标函数的求解:1. 保证预测值与真实值之间的差异最小。2.另一方面要让树模型更加精简(惩罚项更小)
    $$Objtt=\sumn_{i=1}(y_i-(y_i{(t-1)}+f_t(x_i)))2+\Omega(f_t)+constant \
    =\sumn_{i=1}[2(y_i-y_i)f_t(x_i)+f_t(x_i)^2]+\Omega(f_t)+constant$$

  • $2(y_i^{(t-1)}-y_i)$:一般为残差

总结:

  • 目标函数:
    $$\sumn_{i=1}(y_i,y_i+f_t(x_i))+\Omega(f_t)+constant$$

  • 用泰勒展开来近似我们原来的目标

    • 泰勒展开:$f(x+\Delta x) \cong f(x)+f'(x)\Delta x+1/2f''(x)\Delta x^2$
    • 定义:$g_i=\partial {\hat y^{(t-1)}}l(y_i,\hat y{(t-1)}),h_i=\partial2{\hat y^{(t-1)}}l(y_i,\hat y^{(t-1)})$
    • $g_i$:一阶导,$h_t$:二阶导
  • $$Objt^t \cong \sum^n_{i=1}[l(y_i,\hat y{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t2(x_i)]+\Omega (f_t)+constant$$

    • $l(y_i,\hat y^{(t-1)})$:原函数$f(x)$
    • $g_if_t(x_i)$:一阶导乘上derta X
    • $\frac{1}{2}h_if_t^2(x_i)$:二分之一二阶导乘上derta X
  • $$\sum^n_{i=1}[l(y_i,\hat y{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t2(x_i)]+\Omega (f_t)$$
    where $g_i=\partial_{\hat y^{(t-1)}}l(y_i,\hat y^{(t-1)}) ,h_i=\partial^2_{\hat y^{(t-1)}}l(y_i,\hat y^{(t-1)})$

xgboost安装

https://www.lfd.uci.edu/~gohlke/pythonlibs/

xgaboost实例:

基于残差的训练模型:

  1. 第一轮:模型一训练X以Y(y_true)为目标值,得到残差Y_1(y_true-y_prob):
    //
  2. 第二轮:模型二训练X以Y(y_true-y_prob)为目标值,得到残差(Y_1-y_prob)Y_2
    //
  3. 第三轮:模型三训练X以Y(Y_1-y_prob)为目标值,得到残差(Y_2-y_prob)Y_3
    //

最终得到3个预测模型
//

路劲 :
构造目标函数--->目标函数直接优化,近似--->把数结构引入到目标函数中--->仍然难优化,使用贪心算法

1.目标函数构建

使用多棵树进行构建:
//
构建最终的结果都是相加的。

假设已经训练了k棵树,则对于第i个样本的(最终)预测值为:
$$\hat y_i=\sum_{k=1}^k f_k(x_i),f_k \in F$$
最终的预测结果$\hat y_i$是所有预测结果的和。

目标函数:
$Obj=\sum_{i=1}^nl(y_i,\hat y_i)+\sum_{K=1}^k \Omega (f_k)$
其中

  • $y_i$是真实值
  • $\hat y_i$:预测值
  • $\sum_{i=1}^nl(y_i,\hat y_i)$:损失函数
  • $l$:weak learning
  • $\sum_{K=1}^k \Omega (f_k)$:正则化防止过拟合。第k棵树的复杂度(叶结点个数,数的深度,叶结点值等等)

2.训练方式,叠加式训练

给定一个样本$x_i$

  • 第一轮:$\hat y_i^{0}=0$
  • 第二轮:$\hat y_i^1=f_1(x_i)=\hat y_i^0+f_1(x_i)$
  • 第三轮:$\hat y_i^2=f_1(x_i)+f+2(x_i)=\hat y_i^1+f_2(x_i)$
  • ...
  • 第t轮:$\hat y_it=\sum_{k=1}tf_k(x_i)=\hat y^{(t-1)}_i+f_t(x_i)$
  • $\hat y^{(t-1)}$:前t-1棵树的预测值之和,$f_t(x_i)$:第t棵树的预测值

一般的对于第t棵树而言:我的预测值$\hat y_i^t$等于的是$\hat y^{(t-1)}_i+f_t(x_i)$。所以要使所预测的$\hat y_i^t$更精确,就要使他更接近于$y_i$真实值,则:loss($\hat y_i^t,y_i$)足够的小即可。

$$obj=\sum_{i=1}^n loss(y_i,\hat y_it)++\sum_{t=1}t\Omega (f_t)$$
简化(将$\hat y_i^t)$用上面公式替代,后面的复杂度拆为前面t-1棵树的复杂度加上最后一棵树的复杂度。):
$$obj=\sum_{i=1}^n loss(y_i,\hat y_i{(t-1)}+f_t(x_i))+\sum_{j=1} \Omega (f_j)+\Omega (f_t)$$
最后简化(当训练k棵树的时候,就只用解决上面公式的最小化。假设前k-1棵树已知)

min$obj=\sum_{i=1}^n loss(y_i,\hat y_i^{(t-1)}+f_t(x_i))+\Omega (f_t)$

近似简化,泰勒级数

泰勒展开:
$f(x+\Delta x) \cong f(x)+f'(x)\Delta x+1/2f''(x)\Delta x^2$

则原目标函数元素近似替换为:

$f(x)--loss(y_i,\hat y_i^{(t-1)})$

$f(x+\Delta x)--loss(y_i,\hat y_i^{(t-1)}+f_t(x_i))$

$\Delta x--f_t(x_i)$

$x--\hat y_i^{(t-1)}$

原目标函数近似为( $g_i$:一阶导,$h_t$:二阶导):

$$Objt^t \cong \sum^n_{i=1}[l(y_i,\hat y{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t2(x_i)]+\Omega (f_t)$$

对于上述目标函数,当训练第k棵树时,${h_i,g_i}$是已知的。且$l(y_i,\hat y^{(t-1)})$是已知的可以看作常数项,仅为了求$f_k(x_i)$.
简化为:
$$min \sumn_{i=1}[g_if_t(x_i)+\frac{1}{2}h_if_t2(x_i)]+\Omega (f_t)$$

把树结构引入到目标函数中。$f_k(x_i)$的参数化

//

  1. 目的,求出$f_k(x_i)$参数化得到叶结点w
  2. 设置函数$q(x)$:表示样本x的位置
    eg:$q(x_1)$:就是第一个$x_1$样本所在位置
  3. 设置函数$I_i{I|q(x_i)=j}$:表示一个结点的样本数
    eg:$I_1={1,3}$有两个样本
  4. 在$f_k(x_i)=w_{q(x_i)}$

每棵树的复杂度

叶结点个数+叶结点值之和

$$\omega(f_t)=\gamma T+1/2\lambda \sumT_{j=1}w2_i$$

  • T:叶结点个数
  • $\sumT_{j=1}w2_i$:叶结点值之和
  • $\gamma,1/2\lambda$:超参数。

所以通过以上得出新的目标函数(假设,树的形状已知)

$$\sumn_{i=1}[g_if_t(x_i)+\frac{1}{2}h_if_t2(x_i)]+\Omega(f_t) \
=\sumn_{i=1}[g_i*w_{q(x_i)}+\frac{1}{2}h_i*w_{q(x_i)}2]+\gamma T+1/2\lambda \sumT_{j=1}w2_i$$

引入$I_i{I|q(x_i)=j}$:
//
简化公式
$$\sum_{j=1}^T[(\sum_{i \in I_j}g_i)w_j+1/2(\sum_{i \in I_j }h_i+\lambda)*w_j^2]\gamma T$$

  • $\sum_{i \in I_j}g_i,\sum_{i \in I_j }h_i+\lambda$在求第K棵树时已经是已知的了。
  • 通过这些,上述函数已经化为了一个二次函数:$y=ax+bx^2+c$其中 $x=w_j$.然后就是一个二次函数的的最值解
  • 然后二次函数的最值解为-2a/b,所以上述目标函数的最值解为:$-\frac{\sum_{i \in I_j}g_i}{\sum_{i \in I_j }h_i+\lambda}=w_j^*$

所以综上:目标函数值为
$$Obj*=1/2\sumT_{j=1}\frac{(\sum_{i \in I_j}g_i)^2}{\sum_{i \in I_j }h_i+\lambda}+\gamma T$$

所以已知树的形状就可以算出这个Obj的最优解:

//
并在众多树的obj值中算出最小值

寻找树的形状

在已知树的形状就可以求得obj,问题在于如何找到这棵树。

  1. Brufe-Farce Search.列出所有可能的树的形状,并计算所有树的obj值,再找出最小的值的对应的树。就是作为该数形状。

  2. 用信息增益或者基尼指数求的分类:原(不确定)-之后(不确定)。也类似的对于不确定因素下降。可与信息增益使用entroupy前后的差值来衡量不确定因素的变化,而对于xgboost:则是用obj前后的差异来衡量变化是否继续拆分决策树。

//

用那种特征看前后obj的变化差异最大。

//

整理

寻找最好的Split
例子:
//

  • Obj_old:是图中再特征一划分前的树的obj计算
  • Obj_new:是图中云哥该特征一划分后的树的obj计算
  • g_i,h_i:分别是$l(y_i,\hat y^{(t-1)})$的一阶导和二阶导。
  • 则例如g_1,h_1:就是划分样本1的损失函数的一阶导和二阶导。

10降维

10.1 降维概述

  1. 冗余数据,数组之间可以相互转化。则需要剃掉其中一份数据。eg:千米A/小时的数据集和英里/小时的数据集
  2. 样本的特征值应该具有一定的区分度,如果全部一样就应该剔除。
  3. 维度太大,eg:50维数据。数据过大时就无法进行可视化,则需要进行部分降维

概念:将多维数据降为更低维度。
方法:

  • 特征选取:从高纬度的特征中选择其中一个子集来作为新的特征(不能反映全部数据)
  • 特征抽取:将高纬度的特征经过某个函数映射到低纬度作为新的特征,eg:PCA

10.2 PCA(主成分分析)

通过降维技术把多个变量化为少数几个主成分的方法,这些主成分保留原始变量的绝大部分信息,他们通常表示为原始变量的线性组合。

PCA:

  • 机器学习的特征选择问题,其实就是要剔除的特征主要是和类标签无关的特征。而这里的特征很多适合类标签有关的,但里面存在噪声或者冗余。让后通过特征降维来减少特征数,减少噪音和冗余,减少过度拟合的可能性
  • 核心思想是将n维特征映射到k维上,这k维是全新的正交特征。这k维特征称为主成分(它是重新构造出来的k维特征,而不是简单地从n维特征中去除其余n-k维特征),这些主成分信息保留了就大部分重要的原始特征信息。

11 sklean 决策树参数学习

  1. criterion,表示划分属性时选用的准则,可选,默认设置是“gini”或“mse”
    1)在决策树分类时,可选择“gini”,表示采用基尼系数,即CART算法;选择“entropy”,表示采用信息增益。
    2)在决策树回归时,可选择“mse”,表示采用均方差;选择“mae”,表示采用与均值之差的绝对值的和。推荐使用默认的"mse"。一般来说"mse"比"mae"更加精确。除非你想比较二个参数的效果的不同之处。

  2. splitter,表示特征划分点选择策略,可选,默认设置是“best”。
      可以使用"best"或者"random"。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random" 。

  3. max_depth,表示决策树的最大深度,可选,默认设置为None。
      可以选择是int值或None,None时表示不限制决策树的深度,一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,即输入一个int值,具体的取值取决于数据的分布。常用的可以取值10-100之间。

  4. min_samples_split,表示结点再划分所需最小样本数,可选,默认设置为2
      可以选择int或者float,这个值限制了结点继续划分的条件,如果某结点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2;如果样本量不大,不需要管这个值;如果样本量数量级非常大,则推荐增大这个值

  5. min_samples_leaf,表示叶结点所需的最少样本数,可选,默认值为1。
      这个值限制了叶结点最少样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。

  6. min_weight_fraction_leaf,表示叶结点中所需的样本的权重和的最小值,默认为0。
      可为float型,这个值限制了叶结点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

  7. max_features,表示在进行划分时,可以考虑的最大的特征数,可选,默认为None
      可以选择int、float、auto、sqrt、log2、None。默认是"None",意味着划分时考虑所有的特征数;如果是"log2"意味着划分时最多考虑log2N个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑N的二次方根个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。
      一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。

  8. random_state,表示随机数的生成方法,可选,默认为None。
      可选int, RandomState instance或者None。如果是int,random_state是随机数发生器使用的种子; 如果RandomState实例,random_state是随机数生成器; 如果为None,则随机数生成器是np.random使用的RandomState实例。

  9. max_leaf_nodes,表示最大叶结点数,可选,默认为None。
      通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。

  10. min_impurity_decrease,表示结点减少的最小不纯度,也是一种阀值,可选,默认为0.0。
      可选float。意思,如果加权的不纯度减少量(基尼系数,信息增益,均方差,绝对差)超过阀值,则该结点将会被继续分割 。

  11. min_impurity_split,表示结点划分的最小不纯度,也是一种阀值,默认为None。
      可选float。这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶结点 。

  12. class_weight,表示结点划分的最小不纯度,也是一种阀值,默认为None。
      可选dict, list of dicts, “balanced” or None;指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的"None"。
      不适用于决策树回归。

  13. presort,表示结点划分的最小不纯度,也是一种阀值,默认为False。
      可选Ture或False,一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。

决策树随机性的控制

剪枝:对决策树影响巨大,正确剪枝策略时最优化决策树算法的核心。
剪枝参数:
max_depth,min_samples_leaf OR min_samples_split
max_features OR min_impurity_decrease

from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import graphviz

wine=load_wine()
data=wine.data
target=wine.target

#将数据集转为pandas
data=pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)


feature_name=wine.feature_names
target_name=wine.target_names


#测试机训练集划分
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)

#建立模型
clf=tree.DecisionTreeClassifier(criterion='gini',random_state=30,splitter="random",
                                max_depth=3,
                                # min_samples_leaf=10,
                                # min_samples_split=10

                                )
'''sklearn决策树的随机性, 对于红酒数据集来说,所使用的特征其实并没有完全使用,而是随机选取了所有特征中的部分特征来进行划分,
这就是sklearn中的决策树的随机性--目的是为了能更长出各种不同的树,而从众多不同的树中找出最佳的决策树。'''

#rando_state:随机数种子,可以控制上述所说的随机性(在高纬度数据中的随机特征选取)
#splitter:参数选择:best-->决策树在分支时虽然时随机的,但还是会优先选择更重要的特征进行分支。randomm-->分支时会更加随机,树会更深,对训练集的拟合将会降低。可以防过拟合

#min_samples_leaf RO min_samples_split:搭配使用,使决策树更加平滑,如果太小就可能过拟合,如果太大就会缺失部分数据,
#例如当叶子结点的分支的样本个数小于所设定的值就不会在继续进行分支(即使在该节点中存在不同种类的样本,不纯),
#也可以是设置小数值,这样划分使按照样本特征的比例划分的。

#max_features:限制分支时所考虑的特征个数,超过限制个数的特征都会被舍弃,方法比较暴力,对于这种降维防止过拟合的操作建议用PCA

#min_impurity_decrease:限制信息增益的大,信息增益小于设定数值的分支不会发生



clf=clf.fit(Xtrain,Ytrain)
scroe=clf.score(Xtest,Ytest)

print(scroe)

#画出树
dot_data=tree.export_graphviz(clf,
                              feature_names=feature_name,
                              class_names=target_name,
                              filled=True,#颜色填充
                              rounded=True
                              )
graph=graphviz.Source(dot_data)
print(graph)

print(clf.feature_importances_)#显示不同特征在决策树的使用的重要程度

超参数验证:

#超参数验证
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import matplotlib.pyplot as plt
import graphviz

wine=load_wine()
data=wine.data
target=wine.target

#将数据集转为pandas
data=pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)


feature_name=wine.feature_names
target_name=wine.target_names


#测试机训练集划分
Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)

test=[]
for i in range(10):
    clf=tree.DecisionTreeClassifier(criterion='gini',random_state=30,splitter="random",
                                    max_depth=i+1,
                                    # min_samples_leaf=10,
                                    # min_samples_split=10

                                    )
    clf=clf.fit(Xtrain,Ytrain)
    score=clf.score(Xtest,Ytest)
    test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()

目标权重参数

class_weight OR min_weight_fraction_leaf

  • 完成样本标签平衡的参数,样本不平衡是指在一组数据集中,标签的一类天生占有很大比例。比如说:在银行要判断一个办了信用卡的人是否会违约的比例,即使模型什么也不做,全吧结果预测成否,正确率也很高。

    因此我们要使用class_weight对样本标间进行一定均衡,给少量的标签更多的权重,让模型更偏向于少数类,想捕获少数类的方向建模。默认为None时会表示自动给与数据集中的所有标签相同的权重

  • 有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,就需要搭配min_weight_fraction_leaf这个基于权重的剪枝参数来使用。

部分属性和接口

clf.apply(Xtest)#返回每个测试样本所在叶子节点的索引

clf.predict(Xtest)#返回每个测试样本的分类/回归的结果

//

决策树对于环形数据的分类效果天生有缺陷。

sklearn 随即森林学习

GBDT参数学习(梯度提升树)

xgboos是集成算法中提升法的代表算法。集成算法通过在数据上构建多个弱评估器,汇总所有弱评估器的建模结果,以获取比单个模型更好的回归或分类表现。

xgboost实际是CART树,意味着xgboost中所有的树都是二叉的.

  • Boosting三要素:
    • 损失函数L(x,y):用以衡量模型预测结果与真实结果的差异
    • 弱评估器f(x):决策树,不同的boosting算法使用不同的建树过程。
    • 综合集成结果H(x):即集成算法具体如何输出集成结果

同时,GBDT也遵循boosting算法的基本流程进行建模:

  1. 依据上一个弱评估器f(x)_t-1的结果,计算损失函数L(x,y),
  2. 并使用L(x,y)自适应地影响下一个弱评估器f(x)_t的构建
    集成模型输出的结果,受到整体所有弱评估器f(x)_0~f(x)_t的影响.

GTBD与AdaBoost的不同:

  1. GBDT的弱评估器输出类型不再与整体集成算法输出类型一致。(即对于AdaBoost或者随机森林来说,如果你的弱评估器所用的是回归算法(分类)那么你的集成算法也是回归(分类)算法。)对于GBDT而言,无论GBDT整体执行回归/分类/排序/任务,弱评估器一定是回归器。GBDT通过sigmoid或者softmax函数来输出具体的分类结果,但实际弱评估器一定是回归器

  2. 损失函数L(x,y):GBDT损失函数范围不在局限于固定或单一的某个损失函数,而从数学原理上推广到了任意可微的函数。因此GBDT算法中可选的损失函数很多。(GBDT实际计算的过程与损失函数表达式无关)

  3. 拟合残差:AdaBoost的弱评估器需要根据前面建立的弱评估器来自适应的调整。(通过调整数据分布来间接影响后续弱评估器)。而GBDT是通过修改弱评估器的拟合目标来直接影响后续弱评估器的结构。

  • 具体来说,AdaBoost是每次建立弱评估器之前需要修改样本权重。GBDT中不修改样本权重,但每次用于建立弱评估器的是样本x以及当下集成输出H(x_i)与真实标签y的差异(y-H(x_i)).这个差异就是残差。GBDT是通过拟合残差来影响后续弱评估器
  1. 抽象构思:GBDT加入了随机森林,在每次建树之前,允许对样本和特征进行抽样来增大弱评估器的独立性(也因此可以有袋外数据集)。虽然Boosting算法不会大规模地依赖于类似于Bagging的方式来降低方差,但由于Boosting算法的输出结果是弱评估器结果的加权求和,因此Boosting原则上可以获得由"平均"带来的小方差红利。当弱评估器表现不太稳定,采用随机森林相似的方式可以进一步增加Boosting算法的稳定性。

测试代码

C:\Users\Administrator\ensenmble\GBDT

//

  • 根据交叉验证结果比较:当不进行调参,随机森林运行时间最长,AdaBoost最快,GBDT居中,但考虑到AdaBoost的n_estimators参数的默认值为50,而GBDT和随机森林的n_estimators默认值都为100,可以认为AdaBoost的运行速度与GBDT相差不多。从结果来看,未调参状态下GBDT的结果是最好的,其结果甚至与经过TPE精密调参后的随机森林相差不多,而AdaBoost经过调参没有改变太多,可以说AdaBoost极其缺乏调参空间,且学习能力不足。

Keras

图片基本知识

一张图片特征值时所有的像素值,有三个维度:图片要素,图片宽度,图片通道数。

而对于图片通道数:如果时灰度图,那么就只需要一个数值来描述它,就是单通道。如果有RGB三种颜色来描述就是三通道。

  • 灰度图:单通道
  • 彩色图:三通道

eg:灰度图:(200,200,1)像素点是:200200
彩色图:(200,200.3)像素点数是:200
200*3

每一张表示一种颜色
//

张量形状

TensorFlow表示一张图片用3D张量:[height,width,channel]
多个图片表示:[batch,height,width,channel],batch:表示一次批处理的张量数。

keras

//

图片读取处理

import keras_preprocessing from image
img=image.load_img("...")#加载图片
img_list=image.list_pictures(img_directory)#将文件夹下的所有图片以列表形式返回

def save_img(path,
             x,
             data_format='channels_last',
             file_format=None,
             scale=True,
             **kwargs):
    '''将一个numpy数组保存为图像.
    # 参数
        path: Path or file object.
        x: Numpy array.
        data_format: Image data format,
                either "channels_first" or "channels_last".
        file_format: 图像文件的格式. 如果是默认值None, 图片格式就是图片拓展名默认的格式.
            如果想要重新指定格式,则需要使用该参数;
        scale: 是否需要将像素的值缩放到 `[0, 255]`之间.默认是True,即进行缩放
        **kwargs: Additional keyword arguments passed to `PIL.Image.save()`.
        '''
def img_to_array(img, data_format='channels_last', dtype='float32'):
    '''将PIL.Image图像对象转化为numpy数组
    # 参数
        img: PIL.Image 类的实例
        data_format: Image data format,
            either "channels_first" or "channels_last".
        dtype: Dtype to use for the returned array.
    # 返回值
        A 3D Numpy array.
        '''

def array_to_img(x, data_format='channels_last', scale=True, dtype='float32'):
    '''将一个3-D的numpy数组转化为一个 PIL.Image对象
    # Arguments
        x: Input Numpy array.
        data_format: Image data format.
            either "channels_first" or "channels_last".
        scale: Whether to rescale image values
            to be within `[0, 255]`.
        dtype: Dtype to use.
    # 返回值
        A PIL Image instance(一个PIL.Image的实例对象).
    '''

//
就有5005003个数值。

图片大小处理(缩放)

  • 每个图片的特征数量要保持一样。再用于模型处理。
  • 减少特征数量也可以增加计算效率
image=load_img("..",traget_size=(200,200))#target_size就可处理图片大小缩放

图片读取后需要转换为数组处理。

image.img_to_array(...)#将image_load加载的图片转换为数组

每个像素点的值都是再0-255之间

NHWC和NCHW

再设置图片形状的时候有两种格式“channels_first"or"channels_last":

  • 设置"NHWC"时,排列顺序为[batch,height,width,channels];
  • 设置"NCHW"时,排列顺序为[batch,channels,height,width].

实例
对于NCHW:
//
对于NHWC
//
转化使用的tf.transpose(ming,[1,2,0]).eval()这里的[1,2,0]就是上述NCHW中的维度位置的互换。

tf.keras数据集

  • CIFAR0小图片分类数据:5万张,总过100个类别。
    from keras.datasets import cifar100
    (x_train,y_train),(x_test,y_test)=cifar100.load_data()
    
    '''x:(num_samples,3,32,32)或(num_samples,32,32,3)基于image_data_format
    y:uint数组表示类别标签。
    

$$\sum^n_{n=1} y_i log(y_{iprob})$$
y_i:真实值,y_{iprob}:真实值的预测值

  • 要想这个损失越小,对应全连接层神经元位置输出概率越大。
    //

tf.keras API介绍

  1. 获取数据集

  2. 构建模型

    1. 再Keras中,你可以通过组合层来构建模型。通常由层构成图。最常见的模型类型是层堆叠,keras.layers中就有很多模型。
    2. tf.keras.Sequential模型(layers如下):
      //
    3. Flatten:将输入数据进行形状改变展开
    4. Dense:添加一层神经元
      1. Dense(units,activation=None,**kwargs)
        1. units:神经元个数
        2. activation:激活函数,参考tf.nn.relu,tf.nn.softmax,tf.nn.sigmodi,tf.nn.tanh
        3. **kwargs:输入上层输入的形状,input_shape=()
    5. tf.keras.Sequential构建类似管道模型
    model=keras.Sequential([
      keras.layers.Flatten(input_shape=(28,28)),
      keras.layers.Dense(128,activation='relu'),
      keras.layers.Dense(10,activation='softmax')
    ])
    
    1. Model类型:
    2. from keras.models import Model
    3. Model(inputs=1,outputs=b)
      1. input:定义模型输入,input类型
      2. output:定义模型输出
      3. def call(self,inputs):接收来自上层的输入
      from keras.models import Model 
      from keras.layers import Input,Dense
      
      data=Input(shap=(784,))
      out=Dense(32)(date)
      model=Model(input=data,output=out)
      
  3. 训练与评估

    1. 通过调用model的 compile方法去配置该模型所需要的训练参数以及评估方法。
    2. model.compile(optimizer,loss=None,metrics=None,准确率衡):配置训练相关参数
      1. optimizer:梯度下降优化器(keras.optimizers):
        //
      2. loss=None:损失函数类型,类型可以是字符串或者function名字参考:
        //
      3. metrics=None,
posted @ 2023-05-21 22:20  天坑一代  阅读(159)  评论(0)    收藏  举报