使用梯度下降训练线性模型

本文涉及的产品
模型训练 PAI-DLC,100CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
交互式建模 PAI-DSW,每月250计算时 3个月
简介: 使用梯度下降训练线性模型

使用梯度下降训练线性模型


1 实验内容

**课程内容回顾:**在理论课程中,我们回顾了机器学习的基本概念,模型的评估和选择,线性模

型和广义线性模型的概念和相关的梯度下降的优化方法。


**要求:**不使用Tensorfolow、Pytorch 或者scikit-learn 等机器学习框架,仅使用Numpy,Scipy 和

Matplotlib 等Python 常用科学计算和可视化库,使用梯度下降训练线性模型,实现(两类)正态

分布数据的分类。


2 实验原理

线性分类——最小二乘法

一般来说,线性回归都可以通过最小二乘法求出其方程,可以计算出对于y=bx+a的直线。


一般地,影响y的因素往往不止一个,假设有x1,x2,…,xk,k个因素,通常可考虑如下的线性关系式:


logistic回归

logistic回归是一种广义线性回归(generalized linear model),因此与多重线性回归分析有很多相同之处。它们的模型形式基本上相同,都具有 $ wx+b $ ,其中w和b是待求参数,其区别在于他们的因变量不同,多重线性回归直接将w‘x+b作为因变量,即 $ y =wx+b $ ,而logistic回归则通过函数L将 w x + b 对应一个隐状态 p = L ( w x + b ) ,然后根据p 与1-p的大小决定因变量的值。如果L是logistic函数,就是logistic回归。


3 具体实现

数据生成与可视化:

使用Numpy生成两类正态分布N ( ± μ , I d ) , d = 2 , μ = [ 1 ; − 1 ] ,数据总数目m = 500。


这里可以使用多种方法:


1.由numpy.random.multivariate_normal(mean, cov[, size, check_valid, tol]).直接生成。

2.先由np.random.randn()生成一维的正态分布,再转化为2维正态。

代码如下所示:

import numpy as np
from numpy.linalg import cholesky
import matplotlib.pyplot as plt
import pandas as pd
sampleNo = 250
mu = np.array([1, -1])
mu2 = np.array([-1, 1])
Sigma = np.array([[1, 0], [0, 1]])
s1 = np.random.multivariate_normal(mu, Sigma, sampleNo)
s1 = np.random.multivariate_normal(mu2, Sigma, sampleNo)
# R = cholesky(Sigma).T
# va, vc = np.linalg.eig(Sigma)
# R2 = (np.diag(va) ** 0.5) @ vc.T
# s1 = np.random.randn(sampleNo, 2) @ R + mu
# s2 = np.random.randn(sampleNo, 2) @ R + mu2


生成数据后,我们使用matplotlib对数据可视化如下:

plt.plot(*s1.T, '.', label='s1')
plt.plot(*s2.T, '.', label='s2')
plt.axis('scaled')
plt.legend()
plt.show()

最后,我们为两类数据打上Label,再打乱后存入csv文件。

data1 = pd.DataFrame(s1)
data1['label'] = 1
data2 = pd.DataFrame(s2)
data2['label'] = -1
data = pd.concat([data1, data2])
data0 = data.sample(frac=1)
data0.to_csv('data0.csv', header=False, index=False)


数据读取与处理:

从csv文件中读取数据,按照8:2的比例划分训练集与测试集,并对数据添加常数1,构造常数项。

def init_data(a = 0.8):
    data = np.loadtxt('data0.csv', delimiter=',')
    index_m = round(data.shape[0]*a)
    traindata = data[:index_m]
    testdata = data[index_m:]
    train_x, train_y = data_p(traindata)
    test_x, test_y = data_p(testdata)
    return train_x, train_y, test_x, test_y
def data_p(dataIn):
    dataMatIn = dataIn[:, 0:-1]
    classLabels = dataIn[:, -1]
    dataMatIn = np.insert(dataMatIn, 0, 1, axis=1)  #特征数据集,添加1是构造常数项x0
    return dataMatIn, classLabels


法一:利用最小二乘求解线性分类

代码为:

def Leastsquare(train_x, train_y):
    # 最小二乘法
    H = train_x
    H0 = np.array(H)
    # H1为H的转置矩阵
    H1 = np.array(H0).T
    H2 = H1 @ H0
    # 求逆矩阵
    H3 = np.linalg.inv(H2)
    # 最终结果计算
    W = H3 @ H1 @ train_y
    # W = grad_descent(train_x, train_y)
    return W


法二:利用线性分类+梯度下降:

代码:

def grad_descent_mse(dataMatIn, classLabels, maxCycle=500):
    dataMatrix = np.mat(dataMatIn)  # (m,n)
    labelMat = np.mat(classLabels).transpose()
    m, n = np.shape(dataMatrix)
    weights = np.ones((n, 1))  # 初始化回归系数(n, 1)
    alpha = 0.001  # 步长
    # 最大循环次数默认为500
    for i in range(maxCycle):
        y_hat = dataMatrix * weights
        weights = weights - alpha * dataMatrix.transpose()*(y_hat - labelMat).reshape(-1,1)
    return weights


法三:利用逻辑回归+梯度下降:

随机梯度下降:

使用随机梯度下降与动态调整步长的随机梯度下降。

'''
sigmoid函数
'''
def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))
'''
随机梯度下降算法
'''
def stocGradAscent0(dataList, labelList):
    dataArr = np.array(dataList)  # 数据转化为矩阵
    m, n = np.shape(dataArr)
    alpha = 0.01
    weights = np.ones(n)
    for i in range(m):
        h = sigmoid(np.sum(dataArr[i]*weights))
        error = (h-labelList[i])
        weights = weights-alpha*error*dataArr[i]
    return weights
'''
改进的随机梯度下降算法
'''
def stocGradAscent1(dataList, labelList, numIter=150):
    dataArr = np.array(dataList)
    m,n = np.shape(dataArr)
    weights = np.ones(n)
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            alpha = 4/(1.0+j+i)+0.01        # 步长为动态变化
            rand = int(np.random.uniform(0, len(dataIndex)))
            choseIndex = dataIndex[rand]
            h = sigmoid(np.sum(dataArr[choseIndex]*weights))
            error = h-labelList[choseIndex]
            weights = weights-alpha*error*dataArr[choseIndex]
            del(dataIndex[rand])
    return weights


利用逻辑回归模型分类:

该函数以回归系数和特征向量作为输入来计算对应的Sigmoid值,如果Sigmoid值大于0.5则函数返回1,反之返回-1。

def classifyVector(inX, weights):
    prob = sigmoid(np.sum(inX * weights))
    if prob > 0.5:
        return 1
    else:
        return -1


计算分类精度:

def colicTest(trainWeights, testDataList, testLabelList):
    rightCount = 0  # 判断错误的数量
    testCount = len(testDataList)
    for i in range(testCount):
        if int(classifyVector(np.array(testDataList[i]), trainWeights))==int(testLabelList[i]):
            rightCount += 1
    acc = float(rightCount)/testCount
    print("本次的精度为%f" % acc)
    return acc


分类结果可视化:

使用matplotlib对分类边界与分类结果进行可视化:

def plotBestFIt(weights, dataMatIn, classLabels):
    n = np.shape(dataMatIn)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    for i in range(n):
        if classLabels[i] == 1:
            xcord1.append(dataMatIn[i][1])
            ycord1.append(dataMatIn[i][2])
        else:
            xcord2.append(dataMatIn[i][1])
            ycord2.append(dataMatIn[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1,s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = np.arange(-3, 3, 0.1)
    y = (-weights[0, 0] - weights[1, 0] * x) / weights[2, 0]  #matix
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()


4 结果比较

最小二乘法求解:


分类精度与求得W矩阵为:



在测试集上的结果可视化:


训练集上的分类结果为:


2.线性分类+梯度下降:


分类精度与求得W矩阵为:



在测试集上的结果为:


在训练集上的结果为:


3.逻辑回归+梯度下降:


分类精度与求得W矩阵为:



这里我们也确实观察到了二元逻辑回归W的Norm会不断变大的现象!


在测试集上的结果为:


在训练集上的结果为:

目录
相关文章
|
7月前
|
机器学习/深度学习 PyTorch 算法框架/工具
训练误差与泛化误差的说明
训练误差与泛化误差的说明
192 0
|
7月前
|
机器学习/深度学习 算法
大模型开发:什么是过拟合和欠拟合?你如何防止它们?
机器学习中,过拟合和欠拟合影响模型泛化能力。过拟合是模型对训练数据过度学习,测试集表现差,可通过正则化、降低模型复杂度或增加训练数据来缓解。欠拟合则是模型未能捕捉数据趋势,解决方案包括增加模型复杂度、添加特征或调整参数。平衡两者需通过实验、交叉验证和超参数调优。
794 0
|
5月前
|
机器学习/深度学习
训练逻辑回归
【7月更文挑战第22天】训练逻辑回归。
45 4
|
机器学习/深度学习 数据采集 前端开发
机器学习--方差和偏差、Bagging、Boosting、Stacking
机器学习--方差和偏差、Bagging、Boosting、Stacking
448 0
机器学习--方差和偏差、Bagging、Boosting、Stacking
线性回归中的L1与L2正则化
线性回归中的L1与L2正则化
198 0
线性回归中的L1与L2正则化
|
机器学习/深度学习 算法 开发者
回归模型参数估计-5| 学习笔记
快速学习回归模型参数估计-5。
回归模型参数估计-5| 学习笔记
|
机器学习/深度学习 算法 开发者
回归模型参数估计-4| 学习笔记
快速学习回归模型参数估计-4。
回归模型参数估计-4| 学习笔记
|
机器学习/深度学习 算法 开发者
回归模型参数估计-3| 学习笔记
快速学习回归模型参数估计-3。
回归模型参数估计-3| 学习笔记
|
机器学习/深度学习 算法 开发者
回归模型的参数估计-2| 学习笔记
快速学习回归模型的参数估计-2。
回归模型的参数估计-2| 学习笔记
|
机器学习/深度学习 算法 开发者
回归模型的参数估计-1| 学习笔记
快速学习回归模型的参数估计-1。
回归模型的参数估计-1| 学习笔记

热门文章

最新文章