zoukankan      html  css  js  c++  java
  • 逻辑回归实现

    逻辑回归算法的Python实现

    代码

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    %matplotlib inline
    # Get data as DataFrame Object
    df = pd.read_csv('/Users/air/Macro/MegaChen/Study/ProgramOfStudy/MachineLearning/Data/梯度下降/data/LogiReg_data.txt', names=['Exam1', 'Exam2', 'Result'])
    df.insert(0, 'Ones', 1)
    matrix = df.as_matrix()
    
    # 发现是监督学习的分类学习, 一般采用的是sigmoid函数构造最大似然函数从而得出损失函数, 为什么在这里不强调目标函数, 因为目标函数在目前
    # 学到知识范围中, 就是一个t = theta0 * 1 + theta1 * x 1 + ... + thetan * xn == theta.T * x, 就是我们的theta矩阵的转置乘以
    # 我们的训练集
    
    # 此为原始的sigmoid函数, 后面的model函数仅仅是将这里的x换元成theta0 * 1 + theta1 * x 1 + ... + thetan * xn == theta.T * x
    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
    
    # 对原始的sigmoid函数的换元封装, 用于为之后求似然函数作铺垫
    def model(x, theta_set):
        return sigmoid(np.dot(x, theta_set.T))
    
    
    # x_set是一个二维矩阵, len函数是求出它的行数, 也就是一维的元素的个数
    
    # 与数学中的函数有一些不一样, 这里作为参数的theta_set虽然是自变量, 但是在计算机中是不允许的, 所以这里的thata_set也要是一个具体的值
    # 而x_set和y_set是函数的参数, 他们也是某种意义上的“自变量”, 因为他们的值也在随着我们的数据改变
    
    def cost(x_set, y_set, theta_set):
        left_side = np.multiply(-y_set, np.log(model(x_set, theta_set)))
        right_side = np.multiply(1 - y_set, np.log(1 - model(x_set, theta_set)))
        return sum(left_side - right_side) / len(x_set)
    
    
    
    # 求出了cost损失函数, 接下来对该cost函数进行梯度下降求解出每一个theta的梯度, 并一一对应的保存到一个list中
    def gradient(x_set, y_set, theta_set):
        grad = np.zeros(theta_set.shape)
        error = (model(x_set, theta_set) - y_set).ravel() # 将(100,1)的二维矩阵转为一维, 为了term = np.multiply(error, x_set[:, i])中能够计算
        # error = (model(X, theta)- y).ravel()
        for i in range(len(theta_set.ravel())):
            term = np.multiply(error, x_set[:, i])
            grad[0, i] = sum(term) / len(x_set)
        return grad
    
    # 得出了梯度, 我们只需要假定一个起始的α学习率值, 进行一个梯度下降即可
    def descent(data, rate, theta_set):
        np.random.shuffle(data)
        x_set = data[:, 0:3]
        print(x_set.shape)
        y_set = data[:, 3:]
        print(y_set.shape)
        # 计算原始的损失函数, 这个时候的theta_set应该都全为0
        costs = [cost(x_set, y_set, theta_set)]
        times = 0
        while True:
            times += 1
            grad = gradient(x_set, y_set, theta_set)
            # 更新了我们的参数, 这里就是计算机的学习过程:-)
            theta_set = theta_set - rate * grad
            print(theta_set)
            print(theta_set)
            print(theta_set)
            costs.append(cost(x_set, y_set, theta_set))
            # 什么时候结束
            if times > 5000:
                return theta_set, costs
    
            
    theta_set, costs = descent(matrix, 0.0001, np.zeros((1,3)))
    plt.figure(figsize=(12,4))
    plt.plot(range(len(costs)), costs, c='r')
    plt.show()
    print(theta_set)
    

    小结

    • 一般程序的开头就是调用梯度下降函数, 在该函数中调用我们之前定义好的sigmoid, model等函数, 该函数的返回结果就是我们需要的theta参数
    • 对于array([1,2,3])这样矩阵, 它默认是一个列向量, 但是我们希望将他当做一个行向量来使用, 那就使用切片, 保留:, 如a[3:], 如果总共4列的话, 这样就得到了最后一列的行向量, 因为(3,)其实是一个list, 而(3,1)才是矩阵的, 矩阵最起码是二维的
    • 虽然我们的数学公式中的自变量都是一个数, 但是在Python的应用中, 我们都是传入矩阵的, 也就是将我们的数据一并以矩阵的形式传入到函数中, 这样全部的数据一下子就计算出来了
    • 列向量一定是二维的, 而行向量应该是一维的
    • ravel()函数会降维
    • 在强调一下, numpy中的zeros, ones返回的都是二维的矩阵, 不可能出现(3,), 除非a = np.array([1,2,3])

    大致步骤

    1. 判断模型, 以逻辑回归为例
    2. 使用sigmoid函数
    3. h(x) = ...
    4. 用model函数表示h(x), 对sigmoid函数进行封装
    5. 定义cost函数, 需用推出数学公式, 在该函数中调用model函数
    6. 使定义gradient函数, 返回每一个参数对应的gradient的值组成的list, 注意: 该gradient函数不会调用cost函数, 因为一个是梯度(导数), 另一个是cost的函数值
    7. 定义主要的梯度下降函数descent, 返回的就是我们需要的theta_set, 在该函数中调用cost和gradient函数, 其中cost函数的值放在一个costs数据中, 用于画出函数图形和比较两次cost函数值的差, 如果小于我们规定的一个值, 就return退出函数, 而gradient就是为了一个这样的函数, theta = theta - alpha * gradient, 得出我们下一个theta值
  • 相关阅读:
    Sqlite教程(1) SQLiteOpenHelper
    检查网络连接状态。
    GSON解译Json为DTO
    Okhttp教程 (1)
    HashMap的扩容算法
    回溯算法
    动态规划
    实现自旋锁
    Java堆
    垃圾回收算法总结
  • 原文地址:https://www.cnblogs.com/megachen/p/9555860.html
Copyright © 2011-2022 走看看