构建完整的分类项目

构建完整的分类项目

  1. 收集数据集并选择合适的特征
  2. 选择度量模型性能的指标
  3. 选择具体的模型进行训练
  4. 评估模型性能并调参

基于概率的分类模型

线性判别分析

基于贝叶斯公式

通过贝叶斯定理计算贝叶斯公式的分子,比较分子最大的那个类别就是最终类别。
{ δ k ( x ) = l n ( g k ( x ) ) = l n π k + μ σ 2 x − μ 2 2 σ 2 μ ^ k = 1 n k ∑ i : y i = k x i σ ^ 2 = 1 n − K ∑ k = 1 K ∑ i : y i = k ( x i − μ ^ k ) 2 {\begin{cases}\delta_k(x) = ln(g_k(x))=ln\pi_k+\dfrac{\mu}{\sigma^2}x-\dfrac{\mu^2}{2\sigma^2}\\{\hat{\mu}_k =\dfrac{1}{n_k}\sum\limits_{i:y_i=k}x_i}\\{\hat{\sigma}^2 =\dfrac{1}{n-K}\sum\limits_{k=1}^K\sum\limits_{i:y_i=k}(x_i-\hat{\mu}_k)^2}\end{cases}} δk(x)=ln(gk(x))=lnπk+σ2μx2σ2μ2μ^k=nk1i:yi=kxiσ^2=nK1k=1Ki:yi=k(xiμ^k)2

基于降维分类

类内方差小,类间方差大
J ( w ) = ( z ˉ 1 − z ˉ 2 ) 2 s 1 + s 2 = w T ( x ˉ c 1 − x ˉ c 2 ) ( x ˉ c 1 − x ˉ c 2 ) T w w T ( s c 1 + s c 2 ) w        w ^ = a r g m a x w    J ( w ) J(w) = \frac{(\bar{z}_1-\bar{z}_2)^2}{s_1+s_2} = \frac{w^T(\bar{x}_{c_1}-\bar{x}_{c_2})(\bar{x}_{c_1}-\bar{x}_{c_2})^Tw}{w^T(s_{c_1}+s_{c_2})w}\\ \;\;\; \hat{w} = argmax_w\;J(w) J(w)=s1+s2(zˉ1zˉ2)2=wT(sc1+sc2)wwT(xˉc1xˉc2)(xˉc1xˉc2)Tww^=argmaxwJ(w)
记: S b = ( x ˉ c 1 − x ˉ c 2 ) ( x ˉ c 1 − x ˉ c 2 ) T ,    S w = ( s c 1 + s c 2 ) S_b = (\bar{x}_{c_1}-\bar{x}_{c_2})(\bar{x}_{c_1}-\bar{x}_{c_2})^T,\;S_w = (s_{c_1}+s_{c_2}) Sb=(xˉc1xˉc2)(xˉc1xˉc2)T,Sw=(sc1+sc2),因此 J ( w ) = w T S b w w T S w w J(w) = \frac{w^TS_bw}{w^TS_ww} J(w)=wTSwwwTSbw
w = S w − 1 ( x ˉ c 1 − x ˉ c 2 ) w = S_w^{-1}(\bar{x}_{c_1}-\bar{x}_{c_2}) w=Sw1(xˉc1xˉc2)

决策树

基尼系数

G = ∑ k = 1 K p ^ m k ( 1 − p ^ m k ) G = \sum\limits_{k=1}^{K} \hat{p}_{mk}(1-\hat{p}_{mk}) G=k=1Kp^mk(1p^mk)

衡量节点纯度,节点纯度越高,基尼系数越小

交叉熵

D = − ∑ k = 1 K p ^ m k l o g    p ^ m k D = -\sum\limits_{k=1}^{K} \hat{p}_{mk}log\;\hat{p}_{mk} D=k=1Kp^mklogp^mk

节点纯度越高,交叉熵越小

决策树分类算法

a. 选择最优切分特征j以及该特征上的最优点s:
遍历特征j以及固定j后遍历切分点s,选择使得基尼系数或者交叉熵最小的(j,s)
b.按照(j,s)分裂特征空间,每个区域内的类别为该区域内样本比例最多的类别。
c. 继续调用步骤1,2直到满足停止条件,就是每个区域的样本数小于等于5。
d. 将特征空间划分为J个不同的区域,生成分类树。

支持向量机SVM

min ⁡ w , b 1 2 ∥ w ∥ 2  s.t.  y ( i ) ( w T x ( i ) + b ) ≥ 1 , i = 1 , … , n \begin{aligned} \min _{w, b} & \frac{1}{2}\|w\|^{2} \\ \text { s.t. } & y^{(i)}\left(w^{T} x^{(i)}+b\right) \geq 1, \quad i=1, \ldots, n \end{aligned} w,bmin s.t. 21w2y(i)(wTx(i)+b)1,i=1,,n

非线性支持向量机

将数据投影到更高的维度、

核函数

假设 ϕ \phi ϕ是一个从低维的输入空间 χ \chi χ(欧式空间的子集或者离散集合)到高维的希尔伯特空间的 H \mathcal{H} H映射。那么如果存在函数 K ( x , z ) K(x,z) K(x,z),对于任意 x , z ∈ χ x, z \in \chi x,zχ,都有:
K ( x , z ) = ϕ ( x ) ∙ ϕ ( z ) K(x, z) = \phi(x) \bullet \phi(z) K(x,z)=ϕ(x)ϕ(z)
那么我们就称 K ( x , z ) K(x, z) K(x,z)为核函数。

多项式核函数

Polynomial Kernel是线性不可分SVM常用的核函数之一
K ( x i , x j ) = ( ⟨ x i , x j ⟩ + c ) d K\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=\left(\left\langle\mathbf{x}_{i}, \mathbf{x}_{j}\right\rangle+c\right)^{d} K(xi,xj)=(xi,xj+c)d

高斯核函数

Gaussian Kernel,在SVM中也称为径向基核函数(Radial Basis Function,RBF),它是非线性分类SVM最主流的核函数
K ( x i , x j ) = exp ⁡ ( − ∥ x i − x j ∥ 2 2 2 σ 2 ) K\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=\exp \left(-\frac{\left\|\mathbf{x}_{i}-\mathbf{x}_{j}\right\|_{2}^{2}}{2 \sigma^{2}}\right) K(xi,xj)=exp(2σ2xixj22)
使用高斯核函数之前需要将特征标准化

Sigmoid核函数

Sigmoid Kernel是线性不可分SVM常用的核函数之一
K ( x i , x j ) = tanh ⁡ ( α x i ⊤ x j + c ) K\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=\tanh \left(\alpha \mathbf{x}_{i}^{\top} \mathbf{x}_{j}+c\right) K(xi,xj)=tanh(αxixj+c)

余弦相似度核

常用于衡量两段文字的余弦相似度
K ( x i , x j ) = x i ⊤ x j ∥ x i ∥ ∥ x j ∥ K\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=\frac{\mathbf{x}_{i}^{\top} \mathbf{x}_{j}}{\left\|\mathbf{x}_{i}\right\|\left\|\mathbf{x}_{j}\right\|} K(xi,xj)=xixjxixj

作业

1.回归问题和分类问题的区别和联系

回归问题和分类问题需要预测的因变量不一样,回归问题的因变量是连续性变量,但是分类问题预测的因变量往往是离散集合中的某个元素。但是我们可以通过构造函数将回归问题的结果转化为分类问题的类别,logistics回归就是这样的模型,将自变量通过logistics函数转化为0到1的连续值,将0.5作为分类的界限。

2.为什么分类问题的损失函数是交叉熵而不是均方误差

在分类问题中,因变量是类别变量不是连续变量,以逻辑回归为例,使用均方误差时模型参数w会学习得非常慢,而使用交叉熵则有更快的学习速度

3.线性判别分析与逻辑回归在估计参数方面的异同点

逻辑回归的线性函数的系数是通过极大似然估计得到的,而线性回归分析的系数是类均值、方差的韩束,是通过估计训练样本的类均值和方差得到的

4.实现逻辑回归

逻辑回归

推荐运行环境:python 3.6

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# import seaborn as sns
# plt.style.use('fivethirtyeight') #样式美化
import matplotlib.pyplot as plt
# import tensorflow as tf
from sklearn.metrics import classification_report  # 这个包是评价报告

准备数据

读取数据

data = pd.read_csv('ex2data1.txt', names=['exam1', 'exam2', 'admitted'])
data.head()  # 看前五行
exam1exam2admitted
034.62366078.0246930
130.28671143.8949980
235.84740972.9021980
360.18259986.3085521
479.03273675.3443761
data.describe()
exam1exam2admitted
count100.000000100.000000100.000000
mean65.64427466.2219980.600000
std19.45822218.5827830.492366
min30.05882230.6032630.000000
25%50.91951148.1792050.000000
50%67.03298867.6823811.000000
75%80.21252979.3606051.000000
max99.82785898.8694361.000000

处理数据

# x1 = data["exam1"]
data_0 = data[data["admitted"] == 0]
# data_0
data_1 = data[data["admitted"] == 1]

数据可视化

fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(data_0["exam1"], data_0["exam2"], color="red", label="0")
ax.scatter(data_1["exam1"], data_1["exam2"],
           color="green", alpha=0.5, label="1")
ax.set_title('data')
ax.set_xlabel('exam1')
ax.set_ylabel('exam2')
# ax.grid(True)
plt.legend()
plt.show()


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6SMuiL0C-1626794545976)(D:/学习/计算机/机器学习/吴恩达机器学习/作业代码资料/编程作业-自写/exerise2_own/ML2logistic_regression/output_11_0.png)]

# sns.set(context="notebook", style="darkgrid", palette=sns.color_palette("RdBu", 2))

# sns.lmplot('exam1', 'exam2', hue='admitted', data=data,
#            size=6,
#            fit_reg=False,
#            scatter_kws={"s": 50}
#           )
# plt.show()#看下数据的样子
# exam1 = plt.plot(x1)
# exam2 = plt.plot(x2)
# plt.legend

定义数据处理函数

X = ( x 11 x 12 x 21 x 22 ⋮ ⋮ x m 1 x m 2 ) = ( x 1 T x 2 T x 3 T x 4 T ) X=\left( \begin{matrix} x_{11}& x_{12}\\ x_{21}& x_{22}\\ \vdots& \vdots\\ x_{m1}& x_{m2}\\ \end{matrix} \right) =\left( \begin{array}{c} \boldsymbol{x}_1^{\text{T}}\\ \boldsymbol{x}_{2}^{\text{T}}\\ \boldsymbol{x}_{3}^{\text{T}}\\ \boldsymbol{x}_{4}^{\text{T}}\\ \end{array} \right) X=x11x21xm1x12x22xm2=x1Tx2Tx3Tx4T

y    =    ( y 1 y 2 ⋮ y m ) \boldsymbol{y\,\,}=\,\,\left( \begin{array}{l} y_1\\ y_2\\ \vdots\\ y_m\\ \end{array} \right) y=y1y2ym

将 X 扩展为 X ^ = ( X ; 1 ) , 即 X ^ = ( x 1 T 1 x 2 T 1 ⋮ ⋮ x 4 T 1 ) \text{将}X\text{扩展为}\hat{X}=\left( X;1 \right) ,\text{即}\hat{X}=\left( \begin{matrix} \boldsymbol{x}_{1}^{\text{T}}& 1\\ \boldsymbol{x}_{2}^{\text{T}}& 1\\ \vdots& \vdots\\ \boldsymbol{x}_{4}^{\text{T}}& 1\\ \end{matrix} \right) X扩展为X^=(X;1),X^=x1Tx2Tx4T111

将 w 扩展为 w ^ = ( w b ) \text{将}\boldsymbol{w}\text{扩展为}\boldsymbol{\hat{w}}=\left( \begin{array}{c} \boldsymbol{w}\\ b\\ \end{array} \right) w扩展为w^=(wb)

因此 z = X w + b ⇒ z = X ^ w ( z 是所有的数据样本经过线性转化组成的向量 ) \text{因此}\mathbf{z}=X\boldsymbol{w}+b\Rightarrow \mathbf{z}=\hat{X}\boldsymbol{w}\left( \mathbf{z}\text{是所有的数据样本经过线性转化组成的向量} \right) 因此z=Xw+bz=X^w(z是所有的数据样本经过线性转化组成的向量)

# 从整个数据中读取X
def get_X(df):  
    #     """
    #     use concat to add intersect feature to avoid side effect
    #     not efficient for big dataset though
    #     """
    #     ones = pd.DataFrame({'ones': np.ones(len(df))})#ones是m行1列的dataframe
    #     data = pd.concat([ones, df], axis=1)  # 合并数据,根据列合并
    #     return data.iloc[:, :-1].as_matrix()  # 这个操作返回 ndarray,不是矩阵
    df_X = df.iloc[:, :-1]  # 取走除去y的一列作为原始的X
    df_X["ones"] = 1  # 对X进行扩展
    return df_X  # 返回X
# 从整个数据中
def get_y(df):  
    #     '''assume the last column is the target'''
    return df.iloc[:, -1] # df.iloc[:, -1]是指df的最后一列,即y
特征归一化
def normalize_feature(df):
    #     """Applies function along input axis(default 0) of DataFrame."""
    #     return df.apply(lambda column: (column - column.mean()) / column.std())#特征缩放
    df = (df - df.mean()) / df.std()
    return df

变量赋值

X = get_X(data)
# X.head()
# print(X.shape)
X = np.array(X)#将X转换为NumPy形式
y = get_y(data)
# y.head()
print(y.shape)
y = np.array(y)#将y转换为NumPy形式
(100,)
# w = np.ones(3)  # X(m*n) so theta is n*1
# np.matmul(X,w)

sigmoid 函数

σ ( z ) = 1 1 + e − z → z = w T x + b f w , b ( x ) = 1 1 + e − ( w T x + b ) { x 是一个数据样本 } \sigma \left( \text{z} \right) =\frac{1}{1+e^{-\text{z}}}\xrightarrow{\text{z}=\boldsymbol{w}^{\text{T}}\boldsymbol{x}+b}f_{w,b}\left( \boldsymbol{x} \right) =\frac{1}{1+e^{-\left( \boldsymbol{w}^{\text{T}}\boldsymbol{x}+b \right)}}\left\{ \boldsymbol{x}\text{是一个数据样本} \right\} σ(z)=1+ez1z=wTx+b fw,b(x)=1+e(wTx+b)1{x是一个数据样本}

def sigmoid(z):
    # your code here  (appro ~ 1 lines)
    gz = 1/(1+np.exp(-z))
    return gz
#调试sigmoid函数
# sigmoid(np.matmul(X,w))
# sigmoid(113.64835244)

下面程序会调用上面你写好的函数,并画出sigmoid函数图像。如果你的程序正确,你应该能在下方看到函数图像。

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(np.arange(-10, 10, step=0.01),
        sigmoid(np.arange(-10, 10, step=0.01)))
ax.set_ylim((-0.1, 1.1))
ax.set_xlabel('z', fontsize=18)
ax.set_ylabel('g(z)', fontsize=18)
ax.set_title('sigmoid function', fontsize=18)
plt.show()


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFsEoTkH-1626794545979)(D:/学习/计算机/机器学习/吴恩达机器学习/作业代码资料/编程作业-自写/exerise2_own/ML2logistic_regression/output_28_0.png)]

cost function(代价函数)

  • m a x ( ℓ ( θ ) ) = m i n ( − ℓ ( θ ) ) max(\ell(\theta)) = min(-\ell(\theta)) max((θ))=min((θ))
  • choose − ℓ ( θ ) -\ell(\theta) (θ) as the cost function

− ln ⁡ L ( w , b ) = 1 m ∑ i = 1 n − [ y ^ i ln ⁡ f ( x i ) + ( 1 − y ^ i ) ln ⁡ ( 1 − f ( x i ) ) ] -\ln L\left( w,b \right) =\frac{1}{m}\sum_{i=1}^n{-\left[ \hat{y}_i\ln f\left( x_i \right) +\left( 1-\hat{y}_i \right) \ln \left( 1-f\left( x_i \right) \right) \right]} lnL(w,b)=m1i=1n[y^ilnf(xi)+(1y^i)ln(1f(xi))]

w = np.zeros(3)  # X(m*n) so theta is n*1
w
array([0., 0., 0.])
def cost(w, X, y):
    costf = np.mean(-(y * np.log(sigmoid(np.matmul(X,w))) + (1 - y) * np.log(1 - sigmoid(np.matmul(X,w)))))
    return costf
cost(w, X, y)
0.6931471805599453

如果你写的代码正确,这里的输出应该是0.6931471805599453

gradient descent(梯度下降)

求偏导

  • 这是批量梯度下降(batch gradient descent)
    ∂ ( − ln ⁡ L ( w , b ) ) ∂ w = ∑ i = 1 n − ( y ^ i − f ( x i ) ) x i \frac{\partial \left( -\ln L\left( w,b \right) \right)}{\partial w}=\sum_{i=1}^n{-\left( \hat{y}_i-f\left( x_i \right) \right) x_i} w(lnL(w,b))=i=1n(y^if(xi))xi
  • 转化为向量化计算:

∂ ( − ln ⁡ L ) ∂ w = 1 m X ^ T ( S i g m o i d ( X ^ w ) − y ) \frac{\partial \left( -\ln L \right)}{\partial \boldsymbol{w}}=\frac{1}{m}\hat{X}^{\text{T}}\left( Sigmoid\left( \hat{X}\boldsymbol{w} \right) -\boldsymbol{y} \right) w(lnL)=m1X^T(Sigmoid(X^w)y)

def gradient(w, X, y):
    grad = 1/len(y)*np.matmul(X.T,sigmoid(np.matmul(X,w))-y)
    return grad
gradient(w, X, y)
array([-12.00921659, -11.26284221,  -0.1       ])

优化参数

import scipy.optimize as opt
res = opt.minimize(fun=cost, x0=w, args=(
    X, y), method='Newton-CG', jac=gradient)
print(res)
     fun: 0.20349770360438074
     jac: array([-1.10543682e-04,  3.78579856e-04,  1.08434639e-06])
 message: 'Optimization terminated successfully.'
    nfev: 74
    nhev: 0
     nit: 30
    njev: 246
  status: 0
 success: True
       x: array([  0.20626116,   0.20150139, -25.1650148 ])

用训练集预测和验证

预测函数

  • 预测方法:

根据优化后的参数 w ,求得 f w , b ( x ) { ≥ 0.5 → 1 < 0.5 → 0 \text{根据优化后的参数}\boldsymbol{w}\text{,求得}f_{w,b}\left( \boldsymbol{x} \right) \left\{ \begin{array}{l} \ge 0.5\rightarrow 1\\ <0.5\rightarrow 0\\ \end{array} \right. 根据优化后的参数w,求得fw,b(x){0.51<0.50

def predict(x, w):
    y_pred = sigmoid(np.matmul(X,w))
    return (y_pred >= 0.5).astype(int)
final_w = res.x
y_pred = predict(X, final_w)

print(classification_report(y, y_pred))
              precision    recall  f1-score   support

           0       0.87      0.85      0.86        40
           1       0.90      0.92      0.91        60

    accuracy                           0.89       100
   macro avg       0.89      0.88      0.88       100
weighted avg       0.89      0.89      0.89       100

寻找决策边界

http://stats.stackexchange.com/questions/93569/why-is-logistic-regression-a-linear-classifier
w ^ T x = 0 \boldsymbol{\hat{w}}^{\text{T}}\boldsymbol{x}=0 w^Tx=0

y = − w 1 w 2 x − b w 2 y=-\frac{w_1}{w_2}x-\frac{b}{w_2} y=w2w1xw2b

w ^ = ( w 1 w 2 b ) \boldsymbol{\hat{w}}=\left( \begin{array}{c} \boldsymbol{w}_1\\ \boldsymbol{w}_2\\ b\\ \end{array} \right) w^=w1w2b

print(res.x)  # this is final theta
[  0.20626116   0.20150139 -25.1650148 ]
# w_hat = -(res.x / res.x[1])  # find the equation
# print(coef)
#y=kx+b
w_hat = res.x
k=-(w_hat[0]/w_hat[1])
b=-(w_hat[2]/w_hat[1])
x = np.arange(130, step=0.1)
y = k*x + b
data.describe()  # find the range of x and y
exam1exam2admitted
count100.000000100.000000100.000000
mean65.64427466.2219980.600000
std19.45822218.5827830.492366
min30.05882230.6032630.000000
25%50.91951148.1792050.000000
50%67.03298867.6823811.000000
75%80.21252979.3606051.000000
max99.82785898.8694361.000000
# sns.set(context="notebook", style="ticks", font_scale=1.5)

# sns.lmplot('exam1', 'exam2', hue='admitted', data=data,
#            size=6,
#            fit_reg=False,
#            scatter_kws={"s": 25}
#            )

# plt.plot(x, y, 'grey')
# plt.xlim(0, 130)
# plt.ylim(0, 130)
# plt.title('Decision Boundary')
# plt.show()
fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(data_0["exam1"], data_0["exam2"], color="red", label="0")
ax.scatter(data_1["exam1"], data_1["exam2"],
           color="green", alpha=0.5, label="1")
ax.set_title('data')
ax.set_xlabel('exam1')
ax.set_ylabel('exam2')
# ax.grid(True)
plt.plot(x,y,'r', label='Prediction')
plt.legend()
plt.show()


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MphZ4LZp-1626794545982)(D:/学习/计算机/机器学习/吴恩达机器学习/作业代码资料/编程作业-自写/exerise2_own/ML2logistic_regression/output_51_0.png)]

# sns.set(context="notebook", style="ticks", font_scale=1.5)

# sns.lmplot('exam1', 'exam2', hue='admitted', data=data,
#            size=6,
#            fit_reg=False,
#            scatter_kws={"s": 25}
#            )

# plt.plot(x, y, 'grey')
# plt.xlim(0, 130)
# plt.ylim(0, 130)
# plt.title('Decision Boundary')
# plt.show()
fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(data_0["exam1"], data_0["exam2"], color="red", label="0")
ax.scatter(data_1["exam1"], data_1["exam2"],
           color="green", alpha=0.5, label="1")
ax.set_title('data')
ax.set_xlabel('exam1')
ax.set_ylabel('exam2')
# ax.grid(True)
plt.plot(x,y,'r', label='Prediction')
plt.legend()
plt.show()


[外链图片转存中…(img-MphZ4LZp-1626794545982)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值