亦菲喊你来学机器学习(9) --逻辑回归实现手写数字识别

2024-08-23 15:04

本文主要是介绍亦菲喊你来学机器学习(9) --逻辑回归实现手写数字识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 逻辑回归
  • 实现手写数字识别
    • 训练模型
    • 测试模型
  • 总结

逻辑回归

逻辑回归(Logistic Regression)虽然是一种广泛使用的分类算法,但它通常更适用于二分类问题。然而,通过一些策略(如一对多分类,也称为OvR或One-vs-Rest),逻辑回归也可以被扩展到多分类问题,如手写数字识别(通常是0到9的10个类别)。

本篇我们就来尝试一下如何通过逻辑回归来实现手写数字识别

  1. 训练模型
  2. 测试模型

实现手写数字识别

训练模型

  1. 收集数据

在这里插入图片描述

  1. 读取图片

使用opencv处理图片,将图片的像素数值读取进来,并返回的是一个三维(高,宽,颜色)numpy数组:

 pip install opencv-python==3.4.11.45
import cv2
img = cv2.imread("digits.png")
  1. 转为灰度图

将图片转化为灰度图,从而让三维数组变成二位的数组:

grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  1. 处理图片信息

对图片进行处理:将其先垂直切分(横向)成50份,再将每一份水平切分(竖向)成100份,这样我们的每份图片的像素值都为20*20(训练的图片比较规范)共500个,比如:

在这里插入图片描述

import numpy as np
img_info = [np.hsplit(row,100) for row in np.vsplit(grey,50)]
  1. 装进array数组

将切分的每一份图片像素数据都装进array数组中:

x = np.array(img_info)
  1. 分隔训练集与测试集

将数据竖着分隔一半,一半作为训练集,一般作为测试集:

train_x = x[:,:50]
test_x = x[:,50:100]
  1. 调整数据结构

由于我们最后要将数据放在逻辑回归模型中训练,我们得将数据结构调整为适合逻辑回归算法训练的结构,那么我们就来改变每份图片数组的维度:reshape:

new_train_x = train_x.reshape(-1,400).astype(np.float32)
new_test_x = test_x.reshape(-1,400).astype(np.float32)
  1. Z-score标准化

逻辑回归算法进行手写数字识别时,对数据进行标准化是为了提高优化算法的收敛速度、提升模型的预测性能,并避免潜在的数值问题。将数据都进行表示话,避免参数的影响:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
fin_train = scaler.fit_transform(new_train_x)
fin_test = scaler.fit_transform(new_test_x)
  1. 分配标签

我们训练着那么多的数据,却没有给他们具体的类别标签(图像的实际值),因为我们之前的图像处理都是在寻找图像特征,但是并没有给他们一个具体对应的类别,只有空荡荡的特征,无法分类,所以我们得给切分的每份图片打上它们对应的标签:

k = np.arange(10)
train_y = np.repeat(k,250)
test_y = np.repeat(k,250)
train_y = train_y.ravel()
  1. 交叉验证

在逻辑回归的算法中,逻辑模型的参数中,有一参数为正则化强度C,越小的数值表示越强的正则化。我们要进行调参数,看看哪个惩罚因子最为合适,使模型拟合效果更好:

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score#交叉验证选择较优的惩罚因子
scores = []
c_param_range = [0.01,0.1,1,10,100] #参数:一般常用的惩罚因子for i in c_param_range:lr = LogisticRegression(C = i,penalty='l2',solver='lbfgs',max_iter=1000,random_state=0)# C表示正则化强度,越小的数值表示越强的正则化。防止过拟合score = cross_val_score(lr,fin_train,train_y,cv=10,scoring='recall_macro')#交叉验证,将模型和数据集传入,对其进行划分,每份轮流作为测试集来测试模型。返回一个列表对象score_mean = sum(score)/len(score)scores.append(score_mean)
c_choose = c_parma[np.argmax(scores)] #argmax取出最大值的索引位置
  1. 训练模型
lr_model = LogisticRegression(C = c_choose,max_iter=1000,random_state=0)
lr_model.fit(fin_train,train_y)

测试模型

  1. 先用训练数据再次进入模型测试,查看他本身的模型训练效果怎么样:
from sklearn import metrics
train_predict = lr_model.predict(fin_train)
print(metrics.classification_report(train_y,train_predict))  #查看混淆矩阵
-------------------------------precision    recall  f1-score   support0       0.99      1.00      0.99       2501       0.98      1.00      0.99       2502       1.00      0.98      0.99       2503       0.98      0.98      0.98       2504       1.00      1.00      1.00       2505       0.98      0.98      0.98       2506       0.99      1.00      1.00       2507       0.98      0.99      0.98       2508       0.98      0.99      0.99       2509       0.99      0.97      0.98       250accuracy                           0.99      2500macro avg       0.99      0.99      0.99      2500
weighted avg       0.99      0.99      0.99      2500
  1. 再用分割的测试集来测试模型:
test_predict = lr_model.predict(fin_test)
print(metrics.classification_report(test_y,test_predict))
---------------------------precision    recall  f1-score   support0       0.95      0.96      0.95       2501       0.94      0.96      0.95       2502       0.88      0.86      0.87       2503       0.90      0.86      0.88       2504       0.92      0.84      0.88       2505       0.84      0.90      0.87       2506       0.92      0.95      0.93       2507       0.89      0.93      0.91       2508       0.89      0.84      0.86       2509       0.83      0.86      0.85       250accuracy                           0.90      2500macro avg       0.90      0.90      0.89      2500
weighted avg       0.90      0.90      0.89      2500

到这为止!!我们就训练好一个关于手写数字识别的逻辑回归模型啦!!

总结

本篇介绍了如何用逻辑回归算法实现手写数字识别:

  1. 逻辑回归更适合二分类算法,但是也可以通过一些策略,扩展到多分类问题。
  2. 注意要将读取的数据进行标准化操作,灰度图图片数据相差过大。
  3. 学会调整参数,优化模型,比如本篇在交叉验证中找寻最优的惩罚因子。

这篇关于亦菲喊你来学机器学习(9) --逻辑回归实现手写数字识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1099719

相关文章

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

Golang如何用gorm实现分页的功能

《Golang如何用gorm实现分页的功能》:本文主要介绍Golang如何用gorm实现分页的功能方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景go库下载初始化数据【1】建表【2】插入数据【3】查看数据4、代码示例【1】gorm结构体定义【2】分页结构体

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C