python+numpy利用梯度下降算法实现逻辑回归(对比sklearn官方demo)

概要描述

在逻辑回归中,可以使用梯度下降算法来求解模型(即确定sigmoid函数中的各系数和截距)。
本文用python实现梯度下降算法,并使用numpy做矩阵计算求解逻辑回归模型,最后与sklearn官方代码结果验证结果正确性。

详细说明

python实现梯度下降算法

# !/usr/bin/python
# -*- coding: utf-8 -*-
"""
PROJECT_NAME = Datawhale
Author : sciengineer
Email : 821072960@qq.com
Time = 2021/7/22 18:09
"""


import numpy as np

# General a toy dataset:s it's just a straight line with some Gaussian noise:
xmin, xmax = -5, 5
n_samples = 100
np.random.seed(0)
X = np.random.normal(size=n_samples)
y = (X > 0).astype(np.int64)
X[X > 0] *= 4
X += .3 * np.random.normal(size=n_samples)
X = X[:, np.newaxis]


# learning rate: lr
lr = 1


# gradient descent algorithm
def grad_desc(x_ndarr, y_ndarr):


    """
    :param x_ndarr: ndarray of features (for example, 422 samples with 3 fetures, then the shape of x_ndarr
    is (422,3)
    :param y_ndarr: ndarray of label (for example, 422 samples with 1 label, then the shape of y_ndarr
    is (422,)
    :return: a list contains interception and coeffients of the logistic regression model
    """
    x0 = np.ones(x_ndarr.shape[0])
    # in order to use matrix multiplication, add this column x0
    x_ndarr = np.insert(x_ndarr, 0, x0, axis=1)
    theta_arr = np.zeros(x_ndarr.shape[1])

    # to find a reasonable number to initialize the j_loss_last, I
    # calculate the j_loss when i == 0 in the for loop (69), and
    # set j_loss_last the  same order of magnitude with j_loss.
    j_loss_last = 1e2
    delta = 1e-10

    for i in range(10 ** 10):

        # z = theta0 * x0 + theta1 * x1 +theta2 * x2+ ... +thetan * xn
        # z = np.dot(x_ndarr, theta_arr)
        z = np.dot(x_ndarr, theta_arr)
        # z = np.dot( theta_arr, x_ndarr.T)
        #
        y_hat = 1/(1+np.exp(-z))
        # use the clip to bound the y_hat in (0,1) , and to avoid warning "divide by zero encountered in log" or
        # "invalid value encountered in log". Otherwise this will ruin the optimization.
        y_hat = np.clip(y_hat,delta,1-delta)
        # j_loss = np.dot((y_hat - y_ndarr).T, (y_hat - y_ndarr))
        j_loss = -np.dot(y_ndarr , np.log(y_hat))  - np.dot((1-y_ndarr),np.log(1-y_hat))
        delta_j_loss = j_loss_last - j_loss
        rate = abs(delta_j_loss / j_loss)
        # partial derivative of function j_loss with respect to variable theta_arr
        pd_j2theta_arr = np.dot(y_hat - y_ndarr, x_ndarr)

        # theta_arr updates each interation
        theta_arr = theta_arr - lr * 0.01*pd_j2theta_arr
        j_loss_last = j_loss

        # I choose the rate as the condition of convergence

        if rate < 5 * 1e-10:
            break
    return theta_arr



theta_arr = grad_desc(X, y)
# The coeffients: theta1, theta2,..., thetan
print('Coeffients: \n', theta_arr[1:])
# The interception: theta0
print('Interception: \n', theta_arr[0])

运行结果:

Coeffients: 
 [6.90478134]
Interception: 
 -1.6481480918181262

sklearn官方demo

只选取这个官方demo中的前面部分,主要是为了验证手写的逻辑回归算法实现的正确性。

# !/usr/bin/python
# -*- coding: utf-8 -*-
# Code source: Gael Varoquaux
# License: BSD 3 clause

import numpy as np
import matplotlib.pyplot as plt

from sklearn import linear_model
from scipy.special import expit

# General a toy dataset:s it's just a straight line with some Gaussian noise:
xmin, xmax = -5, 5
n_samples = 100
np.random.seed(0)
X = np.random.normal(size=n_samples)
y = (X > 0).astype(float)
X[X > 0] *= 4
X += .3 * np.random.normal(size=n_samples)

X = X[:, np.newaxis]

# Fit the classifier
clf = linear_model.LogisticRegression(C=1e10)
clf.fit(X, y)

print('Coeffients: \n', clf.coef_)
print('Interception: \n',clf.intercept_)

运行结果:

Coeffients: 
 [[6.90879439]]
Interception: 
 [-1.64913083]

可以看到,使用python实现的逻辑回归与sklearn库的运行结果一致。当然,这个实现肯定有许多需要优化的地方,欢迎讨论。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是使用Python代码对梯度下降算法实现线性回归的示例: 首先,我们需要导入所需的包: ```python import numpy as np import matplotlib.pyplot as plt ``` 然后,我们定义一个函数来计算误差,即损失函数: ```python def compute_cost(X, y, theta): m = len(y) predictions = X.dot(theta) square_err = (predictions - y) ** 2 J = 1 / (2 * m) * np.sum(square_err) return J ``` 其中,X是一个m行n列的特征矩阵,y是一个m行1列的目标向量,theta是一个n行1列的参数向量,m是样本数量,n是特征数量。 接下来,我们定义一个函数来执行梯度下降算法: ```python def gradient_descent(X, y, theta, alpha, num_iters): m = len(y) J_history = np.zeros((num_iters, 1)) for i in range(num_iters): predictions = X.dot(theta) errors = np.subtract(predictions, y) delta = (alpha / m) * X.transpose().dot(errors) theta = theta - delta J_history[i] = compute_cost(X, y, theta) return theta, J_history ``` 其中,alpha是学习率,num_iters是迭代次数,J_history记录了每次迭代后的损失函数值。 最后,我们可以使用上述函数来拟合一个简单的线性模型: ```python # 生成随机数据 np.random.seed(0) X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) # 对特征矩阵X添加一列全为1的向量,以便于计算截距 X_b = np.c_[np.ones((100, 1)), X] # 初始化参数向量theta theta = np.random.randn(2, 1) # 执行梯度下降算法 alpha = 0.1 num_iters = 1000 theta, J_history = gradient_descent(X_b, y, theta, alpha, num_iters) # 绘制拟合直线 plt.scatter(X, y) plt.plot(X, X_b.dot(theta), 'r') plt.show() ``` 这里我们生成了一个简单的一维数据集,然后对其进行线性回归拟合并绘制出拟合直线。 完整代码如下:
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值