当前位置: 首页 > news >正文

python学智能算法(十一)|机器学习逻辑回归深入(Logistic回归)

引言

前序学习进程中,已经对逻辑回归的本质进行了探索,特别是对梯度下降的公式进行了细致地推导,相关文章链接为:
python学智能算法(十)|机器学习逻辑回归(Logistic回归)
在此基础上,今天进一步解读逻辑回归的代码。

代码结构

读懂代码需要先看结构,比较通俗简单的做法是先跳过def定义的函数,直接看剩余的部分。以逻辑回归的代码为例,除去def定义的函数外,剩下的主要有两部分。

开头

第一部分是开头处的模块引入:

import numpy as np

这里的目的是引入numpy模块进行数学运算。

结尾

结尾部分展示了调用系列函数实现逻辑回归运算目标:

# 生成数据
X, y = generate_data()# 划分训练集和测试集,这里简单地取前 80% 作为训练集,后 20% 作为测试集
train_size = int(0.8 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]# 训练逻辑回归模型
weights, bias = logistic_regression(X_train, y_train)# 进行预测
y_pred = predict(X_test, weights, bias)# 计算准确率
acc = accuracy(y_test, y_pred)
print(f"模型的准确率为: {acc}")

这里首先调用了generate_data()函数,生成的数据集既可用于训练也可用于测试。
之后很快就划分了数据集:train_size = int(0.8 * len(X)),按照8:2的比例选定了训练集和测试集。
再之后就进行训练,训练依然调用了自定义函数logistic_regression()。
在此基础上就可以基于训练成果进行预测。
之后把预测成果和测试集进行对比,通过accuracy()函数获得准确率。

自定义代码

这个时候就可以回过头来逐个学习最后调用到的函数。

generate_data()函数

generate_data()函数用于生成初始数据。

# 生成示例数据
def generate_data(n_samples=1000, n_features=10):# 生成特征矩阵 X,从标准正态分布中采样# 特征分布 X 为(n_samples行, n_features列)的数组X = np.random.randn(n_samples, n_features)# 真实的权重向量,随机生成# true_weights是一个n_features列的一维数组true_weights = np.random.randn(n_features)# 计算线性组合# 这里采用了np.dot()点乘,X的每一列和true_weights的每一列相乘,最后得到一个一维数组,结构为X的行数,但是只有1列# X 为(n_samples行, n_features列)的数组,true_weights是(1行,n_feature列)的一维数组# np.dot()点乘结果linear_combination是(n_samples行, 1)的数组linear_combination = np.dot(X, true_weights)# 使用sigmoid函数将线性组合转换为概率# sigmoid函数会对linear_combination数组中的每一个元素都进行转化probabilities = 1 / (1 + np.exp(-linear_combination))# 根据概率生成标签 y,以概率决定标签为 1 或 0# y是一个伯努利试验的结果,每个元素都只有一次试验机会,取到1的概率就是probabilities# probabilities是一个n_samples行, 1列)的数组,各个位置取到1的概率和这个位置的probabilities大小有关y = np.random.binomial(1, probabilities)return X, y

从对generate_data()函数的理解可以看出,generate_data()函数最初随机生成了两组正态分布数据X和true_weights,并且让两组数据以点乘的形式计算获得linear_combination,之后使用sigmoid()函数转换得到一个代表概率的数组probabilities。概率数据约束一个新的随机数y,y=1的概率按照伯努利分布的原则计算。由于probabilities中每个元素的取值不一样,所以每一次y=1时的概率也不一样。

sigmoid()函数

之后定义了sigmoid()函数,将在预测计算中使用到:

# 定义sigmoid函数
def sigmoid(z):# sigmoid函数公式,将输入转换为 0 到 1 之间的概率值return 1 / (1 + np.exp(-z))

sigmoid()函数

之后定义了逻辑回归训练函数:

# 定义逻辑回归模型的训练函数
def logistic_regression(X, y, learning_rate=0.01, num_iterations=1000):# 获取样本数量 n 和特征数量 m# 获得的 n是X的行数,m是X 的列数n, m = X.shape# 初始化权重向量,全部设为 0# 定义一个1行m列的纯0矩阵weights = np.zeros(m)# 初始化偏置项为 0bias = 0# for循环的次数num_iterations在函数定义的时候当做已知参数传入for _ in range(num_iterations):# 计算线性组合# 这里的X和 weights按照点乘的形式计算,也获得了(n_samples行, 1列)的数组# bias会自动广播,生成和np.dot(X, weights)形状相同,但每个位置的元素都相等的数组linear_combination = np.dot(X, weights) + bias# 通过sigmoid函数得到预测概率# y_pred也是(n_samples行, 1列)的数组y_pred = sigmoid(linear_combination)# 计算权重的梯度dw = (1 / n) * np.dot(X.T, (y_pred - y))# 计算偏置的梯度db = (1 / n) * np.sum(y_pred - y)# 使用梯度下降更新权重weights -= learning_rate * dw# 使用梯度下降更新偏置bias -= learning_rate * dbreturn weights, bias

这里的X和y都是generate()函数传进来的参数,这里主要做的事情是,将初始值为0的weights数组和bias元素按照梯度下降的原则经过反复迭代后获得相对准确的值。

预测函数

预测函数将上一步训练得到的weights和bias代入运算过程,获得预测值:

# 定义预测函数
def predict(X, weights, bias):# 计算线性组合linear_combination = np.dot(X, weights) + bias# 通过sigmoid函数得到预测概率probabilities = sigmoid(linear_combination)# 根据概率将预测结果转换为 0 或 1predictions = (probabilities >= 0.5).astype(int)return predictions

这里的一个处理细节是,预测获得的结果会代入sigmoid()函数,经函数计算,如果计算值超过0.5,就会取1,否则取0。
这是因为在generate_data()函数里面,是按照伯努利抽样的形式给y赋值0或者1。

accuracy()函数

之后是通过accuracy()函数完成预测值和测试集的对比:

# 定义计算准确率的函数
def accuracy(y_true, y_pred):# 计算预测正确的比例return np.mean(y_true == y_pred)

accuracy()函数通过调用numpy模块里面的mean()函数获得准确率,这个设计比较巧妙:通过比较判断预测值和测试值是否相等,相等的时候赋值1,否则就是0,然后把这些0和1求和载取平均值,不相等的部分因为取0,所以不会在均值中体现出来,最后获得均值就是所有取1的数据比例。

细节说明

X和true_weights都是符合正态分布的随机数,由它们计算获得的y本身也充满了随机特性,所以用随机数来校正权重数组weights和偏置量bias是一个非常开放的做法,因为X和y是否存在数学关系是存疑的,但这种方法能够在运算后获得相对高的(超过80%)的准确预测率,表明逻辑回归算法的拟合能力极强。
需要注意的是,代码每一次的运行结果都不一样,因为随机数的产生结果不同,但准确率波动较小。

总结

此时的完整代码为:

import numpy as np
from sympy.logic.algorithms.dpll import pl_true_int_repr# 生成示例数据
def generate_data(n_samples=1000, n_features=10):# 生成特征矩阵 X,从标准正态分布中采样# 特征分布 X 为(n_samples行, n_features列)的数组X = np.random.randn(n_samples, n_features)# 真实的权重向量,随机生成# true_weights是一个n_features列的一维数组true_weights = np.random.randn(n_features)# 计算线性组合# 这里采用了np.dot()点乘,X的每一列和true_weights的每一列相乘,最后得到一个一维数组,结构为X的行数,但是只有1列# X 为(n_samples行, n_features列)的数组,true_weights是(1行,n_feature列)的一维数组# np.dot()点乘结果linear_combination是(n_samples行, 1)的数组linear_combination = np.dot(X, true_weights)# 使用sigmoid函数将线性组合转换为概率# sigmoid函数会对linear_combination数组中的每一个元素都进行转化probabilities = 1 / (1 + np.exp(-linear_combination))# 根据概率生成标签 y,以概率决定标签为 1 或 0# y是一个伯努利试验的结果,每个元素都只有一次试验机会,取到1的概率就是probabilities# probabilities是一个n_samples行, 1列)的数组,各个位置取到1的概率和这个位置的probabilities大小有关y = np.random.binomial(1, probabilities)return X, y# 定义sigmoid函数
def sigmoid(z):# sigmoid函数公式,将输入转换为 0 到 1 之间的概率值return 1 / (1 + np.exp(-z))# 定义逻辑回归模型的训练函数
def logistic_regression(X, y, learning_rate=0.01, num_iterations=1000):# 获取样本数量 n 和特征数量 m# 获得的 n是X的行数,m是X 的列数n, m = X.shape# 初始化权重向量,全部设为 0# 定义一个1行m列的纯0矩阵weights = np.zeros(m)# 初始化偏置项为 0bias = 0# for循环的次数num_iterations在函数定义的时候当做已知参数传入for _ in range(num_iterations):# 计算线性组合# 这里的X和 weights按照点乘的形式计算,也获得了(n_samples行, 1列)的数组# bias会自动广播,生成和np.dot(X, weights)形状相同,但每个位置的元素都相等的数组linear_combination = np.dot(X, weights) + bias# 通过sigmoid函数得到预测概率# y_pred也是(n_samples行, 1列)的数组y_pred = sigmoid(linear_combination)# 计算权重的梯度dw = (1 / n) * np.dot(X.T, (y_pred - y))# 计算偏置的梯度db = (1 / n) * np.sum(y_pred - y)# 使用梯度下降更新权重weights -= learning_rate * dw# 使用梯度下降更新偏置bias -= learning_rate * dbreturn weights, bias# 定义预测函数
def predict(X, weights, bias):# 计算线性组合linear_combination = np.dot(X, weights) + bias# 通过sigmoid函数得到预测概率probabilities = sigmoid(linear_combination)# 根据概率将预测结果转换为 0 或 1predictions = (probabilities >= 0.5).astype(int)return predictions# 定义计算准确率的函数
def accuracy(y_true, y_pred):# 计算预测正确的比例return np.mean(y_true == y_pred)# 生成数据
X, y = generate_data()# 划分训练集和测试集,这里简单地取前 80% 作为训练集,后 20% 作为测试集
train_size = int(0.8 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]# 训练逻辑回归模型
weights, bias = logistic_regression(X_train, y_train)# 进行预测
y_pred = predict(X_test, weights, bias)# 计算准确率
acc = accuracy(y_test, y_pred)
print(f"模型的准确率为: {acc}")
print('y=',y)
print('weights=',weights)
print('bias=',bias)

通过本次学习,对逻辑回归算法的代码进行了详细分析。

http://www.xdnf.cn/news/324667.html

相关文章:

  • skywalking服务安装与启动
  • AbMole的Calcein-AM/PI细胞双染试剂盒,精准区分细胞活死状态
  • Search After+PIT 解决ES深度分页问题
  • react+ts中函数组件父子通信方式
  • C#——NET Core 中实现汉字转拼音
  • Spring MVC Controller 方法的返回类型有哪些?
  • 项目优先级频繁变动,如何应对?
  • C++入门之认识整型
  • 使用OpenCV 和 Dlib 实现人脸融合技术
  • shell(11)
  • 使用ffmpeg截取MP3等音频片段
  • MCP Client适配DeepSeek
  • SpringBoot 集成 Ehcache 实现本地缓存
  • Vue3 自定义指令的原理,以及应用
  • Ubuntu 单机多卡部署脚本: vLLM + DeepSeek 70B
  • ERP进销存系统源码,SaaS模式多租户ERP管理系统,SpringBoot、Vue、UniAPP技术框架
  • 基于nnom的多选择器
  • springboot国家化多语言实现
  • mybatis-plus分页查询count语句为什么没有left join
  • 正则表达式非捕获分组?:
  • CHAPTER 17 Iterators, Generators, and Classic Coroutines
  • 构建高质量数据湖:大数据治理在湖仓一体架构下的实践指南
  • mathtype转化
  • Vivo 手机官网交互效果实现解析
  • arXiv论文 MALOnt: An Ontology for Malware Threat Intelligence
  • ubuntu中解决matplotlib无法显示中文问题
  • 【MVCP】基于解纠缠表示学习和跨模态-上下文关联挖掘的多模态情感分析
  • 码蹄集——平方根X、整除幸运数
  • Rust 与 Golang 深度对决:从语法到应用场景的全方位解析
  • 平面坐标系中判断点P是否在线段上AB上的常用方法总结