zoukankan      html  css  js  c++  java
  • machine learning学习之逻辑回归解决多分类问题&神经网络前向传播

    写在前面:

    此次作业是使用两种方式来识别手写数字,顺序为逻辑回归、神经网络前向传播(带已经训练好的参数)

    1. 逻辑回归解决多分类问题

    思路:对于每个数字,创建一个分类器(比如说1,则创建分类器识别该组数据是否是一),然后算出每个分类器的参数,将所有分类器(因为此处是数字,所以有十组参数)参数存在一个总的参数数据集中(此数据集就是训练的结果,也就是说通过此数据集可以判断一个新的手写数字图片是数字几)

    tips:原理就是将图片的每个参数当做特征,然后训练模型来识别特征值达到学习的目的,最终得到分类器(可以识别新数字的)

    下面上源代码:

    '''
    warning:
    the range of initial data in matlab file is 1-10
    but in this place ,the 10 is indicate 0
    
    the data in ex3data1.mat is so many row which size is 1*400(has been compressed)
    '''
    
    # 此处不使用自己定义的梯度下降函数,使用scipy模块中自带的minimize函数
    
    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.io as sio
    from scipy.optimize import minimize
    
    # the function which can plot one image(anyone) in pic_set
    
    '''
    minimize参数解释:
    - fun:要优化的函数(损失函数)
    - method:优化方法
    - jac:梯度向量
    - x0:参数初始值(n,)(n,1)
    
    (n,)(n,1)的区别
    '''
    def plot_an_image(X):
        pick_one = np.random.randint(len(X))
        image = X[pick_one,:]
        fig,ax = plt.subplots(figsize = (1,1))
        ax.imshow(image.reshape(20,20).T,cmap = 'gray_r')
        # 去掉刻度
        plt.xticks([])
        plt.yticks([])
        plt.show()
    
    def plot_100_image(X):
        sample_index = np.random.choice(len(X),100)
        images = X[sample_index,:]
        # 后面两个参数控制横纵坐标是否显示
        fig,ax = plt.subplots(ncols=10,nrows=10,figsize = (8,8),sharex=True,sharey=True)
        for r in range(10):
            for c in range(10):
                ax[r][c].imshow(images[10*r+c].reshape(20,20).T,cmap = 'gray_r')
        # ax.imshow(image.reshape(20,20).T,cmap = 'gray_r')
        # 去掉刻度
        plt.xticks([])
        plt.yticks([])
        plt.show()
    
    def sigmoid(z):
        return 1/(1+np.exp(-z))
    
    # 注意此处的传入参数顺序是固定的,打乱会导致调用np模块内优化算法出错
    def costFunction(theta,X,y,lamda):
        A = sigmoid(X@theta)
    
        first = (~y)* np.log(A)
        second = (1-y) * np.log(1-A)
    
        # 惩罚项
        # 两种写法都可以
        # reg = np.sum(np.power(theta[1:],2))*( lamda / 2 * len(X))
        reg = theta[1:]@theta[1:]*(lamda / 2 * len(X))
    
        return np.sum(first - second)/len(X) + reg
    # 无需循环,使用np的内置方法
    def gradient_reg(theta,X,y,lamda):
        reg = theta[1:]*(lamda/len(X))
        reg = np.insert(reg,0,values = 0,axis = 0)
    
        first = (X.T@(sigmoid(X@theta) - y))/len(X)
    
        return first + reg
    
    def one_va_all(X,y,lamda,K):
        n = X.shape[1]
        # 使用二维数组来存储所有theta
        theta_all = np.zeros((K,n))
    
        for i in range(1,K+1):
            # 定义第i个分类器的参数
            theta_i = np.zeros(n,)
            # 判别式y==i是用来分辨是第几类标签
            res = minimize(fun = costFunction,
                           x0 = theta_i,
                           args = (X,y == i,lamda),
                           method = 'TNC',
                           jac = gradient_reg)
            theta_all[i-1,:] = res.x
    
        return theta_all
    
    def predict(X,theta_final):
        h = sigmoid(X@theta_final.T)
        h_argmax = np.argmax(h,axis = 1)# 返回一行中最大值的索引
        return h_argmax + 1
    
    data = sio.loadmat('./data_set/ex3data1.mat')
    # print(data)
    # print(type(data))
    # print(data.keys())
    
    raw_X  = data['X']
    raw_y  = data['y']
    # print(raw_X.shape)
    # print(raw_X[1].shape)
    # plot_an_image(raw_X)
    # plot_100_image(raw_X)
    
    X = np.insert(raw_X,0,values=1,axis = 1)
    # 将y从二维数组变成一维数组
    y = raw_y.flatten()
    
    lamda = 1
    K = 10
    theta_final = one_va_all(X,y,lamda,K)
    # for each in y:
    #     print(each)
    
    y_pred = predict(X,theta_final)
    acc = np.mean(y == y_pred)
    print(acc)

    2.使用神经网路解决问题

    思路:此处因为已经有训练好的参数,所以直接前向传播就好,此处有一个隐藏层,一个输入层,一个输出层,激活函数使用sigmoid函数,输入层传入的参数是每个照片的图片参数,然后输出层是每个图片在每一个数字判断器中运算的结果(也就是概率),最大的那个就是预测出来的数值

    下面上源代码:

    '''
    natural network
    use natural network to implement the recognization of hand write number
    input the number image's attribute
    and output the predict number of each image
    '''
    
    import numpy as np
    import scipy.io as sio
    
    def sigmoid(z):
        return 1/(1+np.exp(-z))
    
    
    
    data = sio.loadmat('./data_set/ex3data1.mat')
    raw_X = data['X']
    raw_y = data['y']
    
    X = np.insert(raw_X,0,values = 1,axis = 1)
    # X.shape
    y = raw_y.flatten()
    
    # the theta is format by dictionary
    theta = sio.loadmat('./data_set/ex3weights.mat')
    # print(theta.keys())
    
    # <Theta1> includes the attribute of input layer to hidden layer
    # <Theta2> includes the attribute of hidden layer to output layer
    theta1 = theta['Theta1']
    theta2 = theta['Theta2']
    
    # use sigmoid function as activate function
    a1 = X
    # obtain the number of hidden layer
    z2 = X @ theta1.T
    a2 = sigmoid(z2)
    
    a2 = np.insert(a2,0,values = 1,axis = 1)
    # obtain the number of output layer
    z3 = a2 @ theta2.T
    a3 = sigmoid(z3)
    
    y_pred = np.argmax(a3,axis = 1)
    y_pred += 1
    
    acc = np.mean(y_pred==y)
    print(acc)

    以上

    希望对大家有所帮助

  • 相关阅读:
    jquery tmpl 模板引擎 取小数点 三目运算
    ztree 根据id选中某一点且触发当前点的click事件
    rgb(123,25,62)拆分
    html5 vedio
    同一个dom上加单击事件和双击事件的冲突解决办法,双击事件方法进不去
    axios拦截器
    foreach、for、for in循环方式
    echarts markline 不同颜色
    组件里传值到父级
    vue路由钩子拦截器beforeEach和afterEach及页面路由变化路由监听
  • 原文地址:https://www.cnblogs.com/lavender-pansy/p/13504654.html
Copyright © 2011-2022 走看看