精华内容
下载资源
问答
  • 在上一次多类别分类器练习中,通过多类别逻辑回归算法实现了识别数字笔迹。 但是,逻辑回归算法不能得到一个更为复杂的假设函数,因为它仅仅只是一个线性分类。 一,神经网络模型建立 建立模型示意图: 上图所...

    在上一次多类别分类器练习中,通过多类别逻辑回归算法实现了识别数字笔迹。
    但是,逻辑回归算法不能得到一个更为复杂的假设函数,因为它仅仅只是一个线性分类,而神经网络能很好地实现这一点。
    神经网路中最基本的成分是“神经元”模型,在生物神经网络中,每个神经元与其他神经元相连,当他“兴奋”时,就会向相连的神经元发送化学物质,从而改变这些神经元类的电位;如果某神经元的电位超过一个“阈值”,那么他就会被激活。神经元接收来自n个神经元传递过来的输入信号,这些输入信号通过带权重的连接进行传输,将神经元接收到的总输入值与神经元的自身的阈值进行比较,然后通过“激活函数”处理产生神经元的输出。理想中的激活函数是阶跃函数,但是它不连续,通常用sigmoid函数作为激活函数。

    一,基于神经网络的多类别分类器

    1.1模型建立

    建立模型示意图:
    在这里插入图片描述
    上图所示神经网络一共有三个层,分别是输入层(input layer),隐藏层(hidden layer),输出层(output layer)。
    特点如下:
    1、每层由单元(units)组成
    2、输入层是有训练集的实例特征向量传入
    3、经过连接接点的权重(weight)传入下一层,一层的输出是下一层的输入
    4、隐藏层的个数可以是任意的,输入层有一层,输出层有一层
    5、每个单元也可以称之为神经结点,根据生物学来源定义
    6、以上成为两层的神经网络,输入层是不算在里面的
    7、一层中加权求和,然后根据非线性方程转化输出
    8、作为多层向前神经网络,理论上,如果有足够的隐藏层,和足够的训练集,可以模拟出任何方程

    1.2前馈传播及多类别分类器的实现

    练习的数据集给出了实现数字字迹识别算法中需要的θ\theta值,这里只需要运用神经网络前馈算法,利用已知的θ\theta便可以轻松完成多类别分类器的实现。
    在这里插入图片描述
    上图的计算过程简写:
    ai(j)=a_i^{(j)}=第J层第i单元的“激活项”
    θ(j)=\theta^{(j)}=控制函数从第J层映射到第J+1层的权重矩阵
    a1(2)=g(θ10(1)x0+θ11(1)x1+θ12(1)x2+θ13(1)x3)a_1^{(2)}=g({\theta_{10}}^{(1)}x_0+{\theta_{11}}^{(1)}x_1+{\theta_{12}}^{(1)}x_2+{\theta_{13}}^{(1)}x_3)
    a2(2)=g(θ20(1)x0+θ21(1)x1+θ22(1)x2+θ23(1)x3)a_2^{(2)}=g({\theta_{20}}^{(1)}x_0+{\theta_{21}}^{(1)}x_1+{\theta_{22}}^{(1)}x_2+{\theta_{23}}^{(1)}x_3)
    a3(2)=g(θ30(1)x0+θ31(1)x1+θ32(1)x2+θ33(1)x3)a_3^{(2)}=g({\theta_{30}}^{(1)}x_0+{\theta_{31}}^{(1)}x_1+{\theta_{32}}^{(1)}x_2+{\theta_{33}}^{(1)}x_3)

    hθ(x)=a(3)=g(θ(2)x0+θ(2)x1+θ(2)x2+θ(2)x3)h_\theta(x)=a^{(3)}=g({\theta}^{(2)}x_0+{\theta}^{(2)}x_1+{\theta}^{(2)}x_2+{\theta}^{(2)}x_3)


    z1(2)=θ10(1)x0+θ11(1)x1+θ12(1)x2+θ13(1)x3z_1^{(2)}={\theta_{10}}^{(1)}x_0+{\theta_{11}}^{(1)}x_1+{\theta_{12}}^{(1)}x_2+{\theta_{13}}^{(1)}x_3
    z2(2)=θ20(1)x0+θ21(1)x1+θ22(1)x2+θ23(1)x3z_2^{(2)}={\theta_{20}}^{(1)}x_0+{\theta_{21}}^{(1)}x_1+{\theta_{22}}^{(1)}x_2+{\theta_{23}}^{(1)}x_3

    其中g(z)是sigmoid函数

    前向传播中“激活项”相关的代码实现

     def feed_forward(theta, X,):
        '''得到每层的输入和输出'''
        t1, t2 = deserialize(theta)
        
        a1 = X
        z2 = a1 @ t1.T
        a2 = np.insert(sigmoid(z2), 0, 1, axis=1)
        z3 = a2 @ t2.T
        a3 = sigmoid(z3)
        
        return a1, z2, a2, z3, a3 
    

    通过θ\theta矩阵,可以由输入通过神经网络前向传播得到输出,即多类别分类器的代码实现:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from scipy.io import loadmat
    from scipy.optimize import minimize
    
    def load_weight(path):
        data = loadmat(path)
        return data['Theta1'], data['Theta2']
    
    def sigmoid(z):
        return 1 / (1 + np.exp(-z))
    
    def load_data(path):
        data = loadmat(path)
        X = data['X']
        y = data['y']
        return X,y
    
    theta1, theta2 = load_weight('ex3weights.mat')
    
    theta1.shape, theta2.shape
    
    X, y = load_data('ex3data1.mat')
    y = y.flatten()
    X = np.insert(X, 0, values=np.ones(X.shape[0]), axis=1)  # intercept
    
    X.shape, y.shape
    a1 = X
    z2 = a1 @ theta1.T
    z2.shape
    z2 = np.insert(z2, 0, 1, axis=1)
    a2 = sigmoid(z2)
    a2.shape
    z3 = a2 @ theta2.T
    z3.shape
    a3 = sigmoid(z3)
    a3.shape
    y_pred = np.argmax(a3, axis=1) + 1
    accuracy = np.mean(y_pred == y)
    print ('accuracy = {0}%'.format(accuracy * 100))  
    
    

    在这里插入图片描述
    可以看出基于神经网络的多类别分类器的准确率为0.9752。与上一篇博客中运用逻辑回归算法的效果要好。(逻辑回归算法得到的准确率为0.9446。

    1.3代价函数

    已知逻辑回归的代价函数为:
    J(θ)=1m[i=1my(i)log(hθ(x(i))(1y(i))log(1hθ(x(i)))]+λ2mj=1nθj2J(\theta)=-\frac{1}{m}[\sum_{i=1}^{m}y^{(i)}\log(h_\theta(x^{(i)})-(1-y^{(i)})\log(1-h_\theta(x^{(i)}))]+\frac{\lambda}{2m}\sum_{j=1}^{n}\theta_j^2
    而神经网络的代价函数也是这个式子的一般形式,但这里不再仅有一个逻辑回归输出单元,取而代之的是存在K个。
    所以,有神经网络的代价函数为:
    J(θ)=1mi=1mk=1K[yk(i)log(hθ(xk(i))(1yk(i))(log(1hθ(x(i)))k)]+λ2ml=1L1i=1Slj=1S(l+1)(θ(ji)(l))2J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{K}[-y_k^{(i)}\log(h_\theta(x_k^{(i)})-(1-y_k^{(i)})(\log(1-h_\theta(x^{(i)}))_k)]+\frac{\lambda}{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{S_l}\sum_{j=1}^{S_{(l+1)}}(\theta_{(ji)}^{(l)})^2
    其中上图表示了hθ(x(i))h_\theta(x^{(i)})的计算过程,K=10是可能的标签总数。注意,hθ(x(i))=ak(3)h_\theta(x^{(i)})=a_k^{(3)}是第k个输出单元的激活(输出值)。此外,r 既然原来的标签(在变量y中)是1,2,…,10,为了训练神经网络,我们需要将标签重新编码为只包含值0或1的向量,即
    在这里插入图片描述
    例如,如果x(i)x^{(i)}是数字5的图像,最终得到的输出结果y(i)y^{(i)}应该是一个十维向量,其中元素y5=1y_5=1,并且其它元素的值为0。

    def cost(theta, X, y):
        a1, z2, a2, z3, h = feed_forward(theta, X)
        J = 0
        for i in range(len(X)):
            first = - y[i] * np.log(h[i])
            second = (1 - y[i]) * np.log(1 - h[i])
            J = J + np.sum(first - second)
        J = J / len(X)
        return J
    '''
         # or just use verctorization
         J = - y * np.log(h) - (1 - y) * np.log(1 - h)
         return J.sum() / len(X)
    '''
    def regularized_cost(theta, X, y, l=1):
        '''正则化时忽略每层的偏置项,也就是参数矩阵的第一列'''
        t1, t2 = deserialize(theta)
        reg = np.sum(t1[:,1:] ** 2) + np.sum(t2[:,1:] ** 2)  # or use np.power(a, 2)
        return l / (2 * len(X)) * reg + cost(theta, X, y)
    
    

    二、神经网络反向传播

    在多类别分类器中,权重θ\theta矩阵是给定的,能够轻松构建分类器。在线性回归,逻辑回归中可以用梯度下降法,或者其他优化算法得到代价函数收敛后的θ\theta值。而在神经网络中,得到前馈传播权重的方法是反向传播。

    2.1sigmoid函数梯度

    sigmoid函数:
    sigmoid(z)=g(z)=11+ezsigmoid(z)=g(z)=\frac{1}{1+{e}^{-z}}
    它的导数
    g(z)=ddzg(z)=g(z)(1g(z)){g}'(z)=\frac{d}{dz}g(z)=g(z)(1-g(z))
    公式用代码实现

    def sigmoid_gradient(z):
        return sigmoid(z) * (1 - sigmoid(z))
    

    2.2随机初始化

    当训练神经网络时,初始化参数的设置很重要。当设置的权重相同时,每层传播后得到的各个单元的数值相同,最后得到的y没有任何意义。所以需要随机初始化参数,破坏对称。
    随机初始化的一种有效策略是在[ε,ε][-\varepsilon,\varepsilon]范围内均匀地为Θ(l)\Theta^{(l)}选择值。其中应该使用ε=0.12\varepsilon=0.12。这个范围使得参数足够小,训练更有效率

    def random_init(size):
        '''从服从的均匀分布的范围中随机返回size大小的值'''
        return np.random.uniform(-0.12, 0.12, size)
    

    2.3反向传播算法

    在这里插入图片描述
    根据已知训练集(x(t),y(t))(x^{(t)},y^{(t)}),我们将利用神经网络前向传播,计算出整个网络中的“激活项”,以及最后的hΘ(x)h_\Theta(x).然后对于第ll层的第jj个节点,将计算出一个“误差项”δj(l)\delta_j^{(l)},这衡量了该节点对我们输出中的任何错误“负责”的程度。
    对于输出节点,我们可以直接测量网络的激活与真实目标值之间的差异,并且使用该差值来定义一个J(3)(因为层3是输出层)。对于隐藏层的 N个单位,将根据层(L+1)中节点的误差项的加权平均值来计算J(L)。
    具体地,这里有反向传播算法(也在上图中示出)。
    步骤: 1,将输入层的值(a(1))设置为第t个训练例x(t)。进行前向传播,计算第二层,第三层的“激活项”(z(2),a(2),z(3),a(3))(z^{(2)},a^{(2)},z^{(3)},a^{(3)})。需要注意的是,需要添加一个1项,以确保层a(1)和a(2)的激活向量也包括偏置单元。

    步骤: 2,对每一个输出层(第三层)的输出单元,设置
    δk(3)=(ak(3)yk)\delta_k^{(3)}=(a_k^{(3)}-y_k),
    其中,yk0,1y_k\in{0,1},表示当前训练样本是否属于第K类(yk=1y_k=1),或者属于其他类(yk=0y_k=0)。

    步骤: 3,对于隐藏层l=2(l=2),设置
    δ(2)=(Θ(2))Tδ(3).g(z(2))\delta^{(2)}=(\Theta^{(2)})^T\delta^{(3)}.*g^{'}(z^{(2)})

    步骤: 4,计算Δ\Delta
    对于训练集{(x(1),y(1)),...,(x(m),y(m))(x^{(1)},y^{(1)}),...,(x^{(m)},y^{(m)})}
    初始化设置Δij=0\Delta_{ij}=0 (for all l,i,j)(for\space all \space l,i,j)
    Δij:=Δij+aj(l)δi(l+1)\Delta_{ij}:=\Delta_{ij}+a_j^{(l)}\delta_i^{(l+1)}

    步骤: 5,计算代价函数的梯度
    Dij(l):=1/mΔij(l)+λΘij(l)   if  j0D_{ij}^{(l)}:=1/m\Delta_{ij}^{(l)}+\lambda\Theta_{ij^{(l)}}\space\space\space if\space\space j\neq0
    Dij(l):=1/mΔij(l)   if  j=0D_{ij}^{(l)}:=1/m\Delta_{ij}^{(l)}\space\space\space if\space\space j=0
    θij(l)J(θ)=Dij(l)\frac{\partial }{\partial \theta_{ij}^{(l)}}J(\theta)=D_{ij}^{(l)}

    循环步骤1到4,最终得到代价函数的偏导数。
    代码实现

    def gradient(theta, X, y):
        '''
        unregularized gradient, notice no d1 since the input layer has no error 
        return 所有参数theta的梯度,故梯度D(i)和参数theta(i)同shape,重要。
        '''
        t1, t2 = deserialize(theta)
        a1, z2, a2, z3, h = feed_forward(theta, X)
        d3 = h - y # (5000, 10)
        d2 = d3 @ t2[:,1:] * sigmoid_gradient(z2)  # (5000, 25)
        D2 = d3.T @ a2  # (10, 26)
        D1 = d2.T @ a1 # (25, 401)
        D = (1 / len(X)) * serialize(D1, D2)  # (10285,)
        
        return D
    

    正则化

    def regularized_cost(theta, X, y, l=1):
        '''正则化时忽略每层的偏置项,也就是参数矩阵的第一列'''
        t1, t2 = deserialize(theta)
        reg = np.sum(t1[:,1:] ** 2) + np.sum(t2[:,1:] ** 2)  # or use np.power(a, 2)
        return l / (2 * len(X)) * reg + cost(theta, X, y)
    
    

    其中,deserialize函数功能是提取参数
    当我们使用高级优化方法来优化神经网络时,我们需要将多个参数矩阵展开,才能传入优化函数,然后再恢复形状。

    def serialize(a, b):
        '''展开参数'''
        return np.r_[a.flatten(),b.flatten()]
      
    def deserialize(seq):
        '''提取参数'''
        return seq[:25*401].reshape(25, 401), seq[25*401:].reshape(10, 26)
    

    2.4梯度检测

    在神经网络算法中,希望得到最小的代价函数J(θ)J(\theta)。要对参数执行梯度检查,可以想象将参数Θ(1)、Θ(2)“展开”为长向量θ。通过这样做,可以考虑代价函数为J(θ),并使用以下梯度检查过程。
    假设有一个函数fi(θ),该函数旨在计算θiJ(θ)\frac{\partial }{\partial \theta_{i}}J(\theta);希望检查fi是否输出正确的导数值。
    在这里插入图片描述

    在这里插入图片描述
    这两个值的近似程度取决于J的细节,通过上式得到的结果去检测通过反向传播算法得到梯度。
    代码实现

    def gradient_checking(theta, X, y, e):
        def a_numeric_grad(plus, minus):
            """
            对每个参数theta_i计算数值梯度,即理论梯度。
            """
            return (regularized_cost(plus, X, y) - regularized_cost(minus, X, y)) / (e * 2)
       
        numeric_grad = [] 
        for i in range(len(theta)):
            plus = theta.copy()  # deep copy otherwise you will change the raw theta
            minus = theta.copy()
            plus[i] = plus[i] + e
            minus[i] = minus[i] - e
            grad_i = a_numeric_grad(plus, minus)
            numeric_grad.append(grad_i)
        
        numeric_grad = np.array(numeric_grad)
        analytic_grad = regularized_gradient(theta, X, y)
        diff = np.linalg.norm(numeric_grad - analytic_grad) / np.linalg.norm(numeric_grad + analytic_grad)
    
        print('If your backpropagation implementation is correct,\nthe relative difference will be smaller than 10e-9 (assume epsilon=0.0001).\nRelative Difference: {}\n'.format(diff))
    

    三、优化参数

    使用minimize函数优化参数
    当隐藏层变多的时候我们的损失函数就变成了一个非凸函数如下图所示
    在这里插入图片描述
    这是考虑使用minimize进行非线性规划

    scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
    

    fun: 求最小值的目标函数

    x0: 变量的初始猜测值,如果有多个变量,需要给每个变量一个初始猜测值。minimize是局部最优的解法,所以

    args: 常数值,后面demo会讲解,fun中没有数字,都以变量的形式表示,对于常数项,需要在这里给值

    method: 求极值的方法,官方文档给了很多种。一般使用默认。每种方法我理解是计算误差,反向传播的方式不同而已,这块有很大理论研究空间

    constraints: 约束条件,针对fun中为参数的部分进行约束限制

    def nn_training(X, y):
        init_theta = random_init(10285)  # 25*401 + 10*26
    
        res = opt.minimize(fun=regularized_cost,
                           x0=init_theta,
                           args=(X, y, 1),
                           method='TNC',
                           jac=regularized_gradient,
                           options={'maxiter': 400})
        return res
    
    res = nn_training(X, y)#慢
    res
    '''
         fun: 0.5156784004838036
         jac: array([-2.51032294e-04, -2.11248326e-12,  4.38829369e-13, ...,
            9.88299811e-05, -2.59923586e-03, -8.52351187e-04])
     message: 'Converged (|f_n-f_(n-1)| ~= 0)'
        nfev: 271
         nit: 17
      status: 1
     success: True
           x: array([ 0.58440213, -0.02013683,  0.1118854 , ..., -2.8959637 ,
            1.85893941, -2.78756836])
    '''
    
    def accuracy(theta, X, y):
        _, _, _, _, h = feed_forward(res.x, X)
        y_pred = np.argmax(h, axis=1) + 1
        print(classification_report(y, y_pred))
    
    accuracy(res.x, X, raw_y)
    '''
                 precision    recall  f1-score   support
    
              1       0.97      0.99      0.98       500
              2       0.98      0.97      0.98       500
              3       0.98      0.95      0.96       500
              4       0.98      0.97      0.97       500
              5       0.97      0.98      0.97       500
              6       0.99      0.98      0.98       500
              7       0.99      0.97      0.98       500
              8       0.96      0.98      0.97       500
              9       0.97      0.98      0.97       500
             10       0.99      0.99      0.99       500
    
    avg / total       0.98      0.98      0.98      5000
    '''
    
    
    展开全文
  • 对于二元分类,上一篇博课已经给出分析:二元分类原理分析,及代码实现过程 运用逻辑回归,很好地实现了分类的功能。 对于一个多分类问题,以三元分类为例,建立数据模型如下, 使用三种符号,...

    一、模型建立

    对于二元分类的数据模型如下;
    在这里插入图片描述
    使用两种符号表示两个不同的数据集。
    对于二元分类,上一篇博客已经给出分析:二元分类原理分析,及代码实现过程
    运用逻辑回归,很好地实现了分类的功能。
    对于一个多分类问题,以三元分类为例,建立数据模型如下,
    在这里插入图片描述
    使用三种符号,表示三种不同类别的数据集

    现在已经知道如何进行二元分类,可以使用逻辑回归,对于直线,同时可以将数据集一分为二为正类和负类。用一对多的分类思想,我们可以将其用在多类分类问题上。有时这个方法也被称为"一对余"(one-vs-rest)方法。

    二、一对多分类方法(one-vs-all)

    在这里插入图片描述
    以三元分类为例,有一个训练集,好比上图表示的有3 个类别,我们用三角形表示 ? = 1,方框表示? = 2,叉叉表示 ? = 3。通过使用一个训练集,将其分成3 个二元分类问题。
      先从用三角形代表的类别1 开始,实际上可以创建一个,新的"伪"训练集,类型2 和类型3 定为负类,类型1 设定为正类,创建一个新的训练集,如下图所示的那样,要拟合出一个合适的分类器。
      在这里插入图片描述
      这里的三角形是正样本,而圆形代表负样本。可以这样想,设置三角形的值为1,圆形的值为0,下面来训练一个标准的逻辑回归分类器,这样我们就得到一个正边界。为了能实现这样的转变,我们将多个类中的一个类标记为正向类(? = 1),然后将其他所有类都标记为负向类,这个模型记作hθ1(x)h_{\theta1}(x);接着,类似地选择另一个类标记为正向类(? = 2),再将其它类都标记为负向类,将这个模型记作hθ2(x)h_{\theta2}(x);依此类推。
      最后得到一系列的模型简记为:
      在这里插入图片描述
    在这里插入图片描述
    最后,在需要做预测时,将所有的分类机都运行一遍,然后对每一个输入变量,都选择最高可能性的输出变量。

    三、分类器实现

    以数字字迹识别为例,讨论多类别分类问题。

    1,加载数据集(Dateset),可视化

    首先,加载数据集。这里的数据为MATLAB的格式,所以要使用SciPy.io的loadmat函数。

    def load_data(path):
        data = loadmat(path)
        X = data['X']
        y = data['y']
        return X,y
    
    
    X, y = load_data('ex3data1.mat')
    print(np.unique(y))  # 看下有几类标签
    # [ 1  2  3  4  5  6  7  8  9 10]
    X.shape, y.shape
    # ((5000, 400), (5000, 1))
    
    

    控制台输出数据中的类别
    在这里插入图片描述
    其中有5000个训练样本,每个样本是20*20像素的数字的灰度图像。每个像素代表一个浮点数,表示该位置的灰度强度。20×20的像素网格被展开成一个400维的向量。在我们的数据矩阵X中,每一个样本都变成了一行,这给了我们一个5000×400矩阵X,每一行都是一个手写数字图像的训练样本。
    由Y数组,查看得到数据集分为,[1,2,3,4,5,6,7,8,9,10]十个类别。
    随机查看1个训练样本,查看100个训练样本。

    def plot_an_image(X):
        """
        随机打印一个数字
        """
        pick_one = np.random.randint(0, 5000)
        image = X[pick_one, :]
        fig, ax = plt.subplots(figsize=(1, 1))
        ax.matshow(image.reshape((20, 20)), cmap='gray_r')
        plt.xticks([])  # 去除刻度,美观
        plt.yticks([])
        plt.show()
        print('this should be {}'.format(y[pick_one]))
    
    
    def plot_100_image(X):
        """ 
        随机画100个数字
        """
        sample_idx = np.random.choice(np.arange(X.shape[0]), 100)  # 随机选100个样本
        sample_images = X[sample_idx, :]  # (100,400)
        
        fig, ax_array = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True, figsize=(8, 8))
    
        for row in range(10):
            for column in range(10):
                ax_array[row, column].matshow(sample_images[10 * row + column].reshape((20, 20)),
                                       cmap='gray_r')
        plt.xticks([])
        plt.yticks([])        
        plt.show()
    
    
    

    在这里插入图片描述
    在这里插入图片描述

    2,向量化逻辑回归

    使用多个one-vs-all(一对多)logistic回归模型来构建一个多类别分类器。由于有10个类,需要训练10个独立的分类器。为了提高训练效率,重要的是向量化

    2.1向量化正则化的代价函数

    正则化的logistic回归的代价函数是:
    J(θ)=1m[i=1my(i)log(hθ(x(i))(1y(i))log(1hθ(x(i)))]+λ2mj=1nθj2J(\theta)=-\frac{1}{m}[\sum_{i=1}^{m}y^{(i)}\log(h_\theta(x^{(i)})-(1-y^{(i)})\log(1-h_\theta(x^{(i)}))]+\frac{\lambda}{2m}\sum_{j=1}^{n}\theta_j^2
    对于每个样本ii要计算,hθ(x(i))h_\theta(x^{(i)}),hθ(x(i))=g(θTx(i))h_\theta(x^{(i)})=g(\theta^Tx^{(i)}),g(z)g(z)是sigmoid函数
    事实上我们可以对所有的样本用矩阵乘法来快速的计算。
    定义X,与θ\theta
    在这里插入图片描述
    通过计算Xθ\theta
    在这里插入图片描述
    在最后一个等式中,我们用到了一个定理,如果aabb都是向量,那么aTb=bTaa^Tb=b^Ta 这样我们就可以用一行代码计算出所有的样本。

    def sigmoid(z):
        return 1 / (1 + np.exp(-z))
    
    def regularized_cost(theta, X, y, l):
        """
        don't penalize theta_0
        args:
            X: feature matrix, (m, n+1) # 插入了x0=1
            y: target vector, (m, )
            l: lambda constant for regularization
        """
        thetaReg = theta[1:]
        first = (-y*np.log(sigmoid(X@theta))) + (y-1)*np.log(1-sigmoid(X@theta))
        reg = (thetaReg@thetaReg)*l / (2*len(X))
        return np.mean(first) + reg
    
    

    2.2向量化梯度

    未正则化逻辑回归代价函数的梯度为:
    /θjJ(θ)=1mi=1m(hθ(x(i))y(i))xj(i)\frac{\partial }{\partial /\theta_j}J(\theta)=-\frac{1}{m}\sum_{i=1}^{m} (h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}
    使用向量化的方法表示
    在这里插入图片描述
    其中,在这里插入图片描述
    注意,hθ(x(i))y(i)h_\theta(x^{(i)})-y^{(i)}是一个标量,令βi=hθ(x(i))y(i)\beta_i=h_\theta(x^{(i)})-y^{(i)}
    得到:
    在这里插入图片描述
    正则化后的梯度下降算法表示如下,不惩罚θ0\theta_0
    在这里插入图片描述
    代码实现

    def regularized_gradient(theta, X, y, l):
        """
        don't penalize theta_0
        args:
            l: lambda constant
        return:
            a vector of gradient
        """
        thetaReg = theta[1:]
        first = (1 / len(X)) * X.T @ (sigmoid(X @ theta) - y)
        # 这里人为插入一维0,使得对theta_0不惩罚,方便计算
        reg = np.concatenate([np.array([0]), (l / len(X)) * thetaReg])
        return first + reg
    

    3,一对多分类器(one-vs-all)

    这部分通过训练多个正则化logistic回归分类器实现一对多分类,每个分类器对应数据集中K类中的一个。
    对于这个任务,我们有10个可能的类,并且由于logistic回归只能一次在2个类之间进行分类,每个分类器在“类别 i”和“不是 i”之间决定。 我们将把分类器训练包含在一个函数中,该函数计算10个分类器中的每个分类器的最终权重,并将权重返回shape为(k, (n+1))数组,其中 n 是参数数量。

    from scipy.optimize import minimize
    
    def one_vs_all(X, y, l, K):
        """generalized logistic regression
        args:
            X: feature matrix, (m, n+1) # with incercept x0=1
            y: target vector, (m, )
            l: lambda constant for regularization
            K: numbel of labels
        return: trained parameters
        """
        all_theta = np.zeros((K, X.shape[1]))  # (10, 401)
        
        for i in range(1, K+1):
            theta = np.zeros(X.shape[1])
            y_i = np.array([1 if label == i else 0 for label in y])
        
            ret = minimize(fun=regularized_cost, x0=theta, args=(X, y_i, l), method='TNC',
                            jac=regularized_gradient, options={'disp': True})
            all_theta[i-1,:] = ret.x
                             
        return all_theta
    
    

    这里需要注意的几点:首先,我们为X添加了一列常数项 1 ,以计算截距项(常数项)。 其次,我们将y从类标签转换为每个分类器的二进制值(要么是类i,要么不是类i)。 最后,我们使用SciPy的较新优化API来最小化每个分类器的代价函数。 如果指定的话,API将采用目标函数,初始参数集,优化方法和jacobian(渐变)函数。 然后将优化程序找到的参数分配给参数数组。

    4,One-vs-all Prediction

    在训练多类别分类器之后,现在可以用它来预测给定图像中包含的数字。对于每个输入,您应该使用以下方法计算它属于每个类的“概率” 训练的Logistic回归分类器。One-vs-all预测函数将选择相应的逻辑回归分类器输出概率最高的类和ret。 将类标签(1、2、…或K)作为输入示例的预测。
    实现向量化代码的一个更具挑战性的部分是正确地写入所有的矩阵,保证维度正确。

    def predict_all(X, all_theta):
        # compute the class probability for each class on each training instance   
        h = sigmoid(X @ all_theta.T)  # 注意的这里的all_theta需要转置
        # create array of the index with the maximum probability
        # Returns the indices of the maximum values along an axis.
        h_argmax = np.argmax(h, axis=1)
        # because our array was zero-indexed we need to add one for the true label prediction
        h_argmax = h_argmax + 1
        
        return h_argmax
    
    

    这里的h共5000行,10列,每行代表一个样本,每列是预测对应数字的概率。我们取概率最大对应的index加1就是我们分类器最终预测出来的类别。返回的h_argmax是一个array,包含5000个样本对应的预测值。

    raw_X, raw_y = load_data('ex3data1.mat')
    X = np.insert(raw_X, 0, 1, axis=1) # (5000, 401)
    y = raw_y.flatten()  # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,)
    
    all_theta = one_vs_all(X, y, 1, 10)
    all_theta  # 每一行是一个分类器的一组参数
    y_pred = predict_all(X, all_theta)
    accuracy = np.mean(y_pred == y)
    print ('accuracy = {0}%'.format(accuracy * 100))
    
    

    在这里插入图片描述
    通过预测的y值与实际y值进行比对,得出结果在这次练习中的多类别分类器的准确率是0.9446。

    展开全文
  • import numpy as np ''' 纯随机数据,练习算法编码 模拟一个三变量双层神经网络 _n代表层数 _v代表向量 ''' w_1_v = np.random.randn(4,3)#4x3 b_1_v = np.random.randn(4,1)#4x1 x_v = np.random.randn(3,10)#3x10 ...
    import numpy as np
    '''
    纯随机数据,练习算法编码
    模拟一个三变量双层神经网络
    _n代表层数
    _v代表向量
    '''
    w_1_v = np.random.randn(4,3)#4x3
    b_1_v = np.random.randn(4,1)#4x1
    x_v = np.random.randn(3,10)#3x10
    y_v = np.random.randn(1,10)#1x10
    w_2_v = np.random.randn(1,4)#1x4
    b_2_v = np.random.randn(1,1)#1x1
    aa = 0.2#Alpha
    z_1_v = np.dot(w_1_v,x_v)+b_1_v#4x10
    a_1_v = (np.exp(z_1_v)-np.exp(-z_1_v))/(np.exp(z_1_v)+np.exp(-z_1_v))#4x10
    z_2_v = np.dot(w_2_v,a_1_v)+b_2_v#1x10
    a_2_v = 1/(1+np.exp(-z_2_v))#1x10
    dz_2_v = a_2_v-y_v#1x10
    dw_2_v = np.dot(dz_2_v,a_1_v.T)#1x4
    db_2_v = 1/10*np.sum(dz_2_v,axis = 1,keepdims=True)#1x1
    dz_1_v = np.dot(w_2_v.T,dz_2_v)*(1-(np.exp(z_1_v)-np.exp(-z_1_v))/(np.exp(z_1_v)+np.exp(-z_1_v))*(np.exp(z_1_v)-np.exp(-z_1_v))/(np.exp(z_1_v)+np.exp(-z_1_v)))#4x10
    dw_1_v = np.dot(dz_1_v,x_v.T)#4x3
    db_1_v = 1/10*np.sum(dz_1_v,axis = 1,keepdims=True)#4x1
    w_1_v = w_1_v-aa*dw_1_v
    w_2_v = w_2_v-aa*dw_2_v
    b_1_v = b_1_v-aa*db_1_v
    b_2_v = b_2_v-aa*db_2_v
    print("w_1_v:")
    print(w_1_v)
    print("w_2_v:")
    print(w_2_v)
    print("b_1_v:")
    print(b_1_v)
    print("b_2_v:")
    print(b_2_v)
    
    
    展开全文
  • 这是Coursera网站上,课程中算法在Matlab语言的实现,同样也可以参考斯坦福大学的计算机课程 。 注意: 您可以在上下载完整课程视频和相关文档; 定义 “如果某计算机程序在T上的性能(由P来衡量)随着经验E的提高而...
  • 多变量线性回归python实现(吴恩达机器学习作业一):'''题目:一个房屋价格数据集,其中有2个变量(房子的大小,卧室的数量)和目标(房子的价格)据此构建多元线性回归模型数据集在本文最后'''import numpy as npimport ...

    多变量线性回归python实现(吴恩达机器学习作业一):

    '''题目:一个房屋价格数据集,其中有2个变量(房子的大小,卧室的数量)和目标(房子的价格)据此构建多元线性回归模型数据集在本文最后'''

    import numpy as np

    import pandas as pd

    import matplotlib.pyplot as plt

    path = 'ex1data2.txt'

    data = pd.read_csv(path, names=['Size', 'Bedrooms', 'Price'])

    print(data.head()) #检查数据是否读取有误

    #对于多变量,需要进行数据预处理步骤:特征归一化

    #注意type(data2)为class 'pandas.core.frame.DataFrame',不是矩阵

    data = (data - data.mean()) / data.std()

    #这里的mean是针对每一列进行求均值的,std类似

    print(data.head())

    #定义代价函数

    def computeCost(X,y,theta):

    inner = np.power(((X * theta.T)-y),2)

    # power(x, y) 函数,计算 x 的 y 次方

    return np.sum(inner)/(2*len(X))

    #len(X)返回的是行的数量

    # add ones column

    data.insert(0, 'Ones', 1)

    # set X (training data) and y (target variable)

    cols = data.shape[1]

    X = data.iloc[:,0:cols-1]

    y = data.iloc[:,cols-1:cols]

    #iloc是基于索引位来选取数据集,

    #0:4就是选取 0,1,2,3这四行,

    #需要注意的是这里是前闭后开集合

    print(X.head()) # head()是观察前5行

    print(y.head())

    # convert to matrices and initialize theta

    X = np.matrix(X.values)

    y = np.matrix(y.values)

    theta = np.matrix(np.array([0,0,0]))

    print(X.shape, theta.shape, y.shape)

    # 看一下矩阵的维度,是否正确

    print(computeCost(X, y, theta))

    # 计算初始代价函数的值

    def gradientDescent(X,y,theta,alpha,epoch):

    temp = np.matrix(np.zeros(theta.shape))#初始化一个临时θ矩阵

    parameters = int(theta.flatten().shape[1])

    #a是个矩阵或者数组,a.flatten()就是把a降到一维,默认是按横的方向降

    cost = np.zeros(epoch)

    m = X.shape[0]

    #python中shape[0]与shape[1]区别:https://blog.csdn.net/weixin_43283397/article/details/108031929

    for i in range(epoch):

    temp = theta - (alpha/m) * (X * theta.T - y).T * X

    theta = temp

    cost[i] = computeCost(X,y,theta)

    return theta,cost

    #初始化学习率α和迭代次数

    alpha = 0.01

    epoch = 1000

    # perform linear regression on the data set

    g, cost = gradientDescent(X, y, theta, alpha, epoch)

    print(g,computeCost(X, y, g))

    #最终得到的θ值和代价函数值为:[[-1.11044365e-16 8.78503652e-01 -4.69166570e-02]] 0.13070336960771892

    数据集如下(运行代码时需要将数据集放入ex1data2.txt文件中):

    2104,3,399900

    1600,3,329900

    2400,3,369000

    1416,2,232000

    3000,4,539900

    1985,4,299900

    1534,3,314900

    1427,3,198999

    1380,3,212000

    1494,3,242500

    1940,4,239999

    2000,3,347000

    1890,3,329999

    4478,5,699900

    1268,3,259900

    2300,4,449900

    1320,2,299900

    1236,3,199900

    2609,4,499998

    3031,4,599000

    1767,3,252900

    1888,2,255000

    1604,3,242900

    1962,4,259900

    3890,3,573900

    1100,3,249900

    1458,3,464500

    2526,3,469000

    2200,3,475000

    2637,3,299900

    1839,2,349900

    1000,1,169900

    2040,4,314900

    3137,3,579900

    1811,4,285900

    1437,3,249900

    1239,3,229900

    2132,4,345000

    4215,4,549000

    2162,4,287000

    1664,2,368500

    2238,3,329900

    2567,4,314000

    1200,3,299000

    852,2,179900

    1852,4,299900

    1203,3,239500

    展开全文
  • 单变量线性回归python实现(吴恩达机器学习作业一):'''题目:使用一个变量实现线性回归,以预测食品卡车的利润。假设你是一家餐馆的首席执行官,正在考虑不同的城市开设一个新的分店。该连锁店已经在各个城市拥有...
  • 吴恩达机器学习作业的Python实现,该部分是神经网络的作业,里面包含数据集和代码
  • 吴恩达机器学习课程笔记+代码实现(19)Python实现支持向量机(Programming Exercise 6)-附件资源
  • import numpy as np import matplotlib.pyplot as plt import pandas as pd #%matplotlib inlinefrom sklearn.datasets import load_iris from sklearn.model_selection import train_test_split ...
  • 2 正则化逻辑回归前文用python实现了基础的逻辑回归,而实际情况中,数据的分类可能更为复杂。为达到更好的拟合效果,决策边界模型自然也就带有更多的项数和更大的次数。而“正则化”有助于简化模型,提高模型的泛化...
  • 里面可以下载进行代码实现的数据集data.txt或data.csv 介绍: 最近在看吴恩达机器学习视频的时候,为了巩固自己的基础,想亲自实现一下课程里面的每个算法。在实现之前,我先看了一下别人实现的相关代码,看完就...
  • 主要根据吴恩达的机器学习视频来学习梯度下降算法,并用代码实现。 梯度下降算法的目的是求使代价函数最小的θ的值,附上相关公式。 上图是假设函数和代价函数的定义,而梯度下降算法的目的就是为了找到是代价...
  • 吴恩达机器学习作业Python版 主要记录自己学习机器学习的过程,以及自己看别人代码时不懂或者疑惑的地方,代码主要参考Cowry5作者的代码,原作者代码和讲解更为详细,本文章如有不好的地方,还请去浏览大神的原文章...
  • 为了分享和帮助广大同学在学习吴恩达机器学习课程的同时,在缺少linux环境下,用pycharm编程实现代码,本资源提供了机器学习代码python版,并有详细注释,原有来源“黄海广”
  • 内有详细搜集的吴恩达机器学习课的课后习题编程实现代码,有官方提供的matlab版本,还有多个用python实现的版本,并且附有详细的注释以及作业文档说明。
  • 吴恩达深度学习课程的课后作业代码python3.5实现
  • 参考@flowerfu的答案https://blog.csdn.net/weixin_41509677/article/details/105192457,进行了完善,把代码贴上,供大家指正。 说明:在不增加特征(特征数401)的情况下,使用一对多分类器进行学习,通过调整正则...
  • 整个项目的github:...里面可以下载进行代码实现的数据集 题目介绍: In this part of the exercise, you will implement regularized logistic regression to predict whethe...
  • Python版本3.6 编译环境:anaconda Jupyter Notebook 链接:实验数据和实验指导书 提取码:i7co 本章课程笔记部分见:13.聚类 在本练习中,我们将实现K-means聚类,并使用它来压缩图像。我们将实施和应用K-means到一...
  • 根据吴恩达作业ex2的Logistic Regression用Python代码实现。 首先贴上公式,整个算法的实现主要依靠两个公式。一个是计算代价函数的公式,一个是进行梯度下降的公式。 计算logistic回归的代价函数定义如下。值得...
  • 代码使用matlab来实现,且只需要填充一些关键步骤,很容易漏掉一些信息,故而用python实现一下:前半部分:# -*- coding...说明:本文档根据吴恩达机器学习课后作业改编而成,源代码是matlab ''' import numpy as ...
  • 整个项目的github:...里面可以下载进行代码实现的数据集 题目介绍: In this exercise, you will implement one-vs-all logistic regression and neural networks to recogni...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 427
精华内容 170
关键字:

吴恩达python代码实现

python 订阅