机器学习之手写字体(digits)识别——利用sklearn实现


机器学习之手写字体(digits)识别——利用sklearn实现


1实验目的

为了进一步地掌握建立机器学习模型的流程,理解机器学习的基本概念,此次实验针对sklearn自带的digits数据集(手写字体识别数据集)进行分类预测。
在此次实验中,我选用了KNN、MLP、Random Forest、Adaboost、SVM、Decision Tree、Logistic Regression这七种机器学习算法模型进行手写字体的识别。
本次项目的实验环境为pycharm + python3.9,经测试,各种算法模型在安装了python3.9的jupyter notebook中均可以正常运行

2实验过程

2.1 查看数据集

首先,将sklearn库中的数据集导入到项目中,其中X为1797*64的二维数组,代表数据集中1797个样本,每一个样本图片均是一维向量,特征维度为64,每个像素点代表1维的特征,其取值范围为0-16;y为样本所对应的标签值,共有10个类别,其取值范围为0-9中的任意一个数字。将数据集导入项目中的代码如下所示:

from sklearn.datasets import load_digits
digits = load_digits()
X = digits.data
y = digits.target

如果要可视化查看数据集,则需要将样本图片转换为二维,然后借助matplotlib包实现,以数据集中的第1796个样本9为例,具体的实现方式,如下所示:

import matplotlib.pyplot as plt
def show(image):
    test = image.reshape((8, 8))  # 从一维变为二维,这样才能被显示
    print(test.shape)  # 查看是否是二维数组
    plt.imshow(test, cmap=plt.cm.gray)  # 显示灰色图像
plt.show()
if __name__ == '__main__':
    show(X[1795])

数字9图片如下图所示:
在这里插入图片描述
考虑到在后续算法模型的建立过程中,需要用到的样本是一维向量,故show()函数只用来对数据集的查看和检验,并不将数据集全部进行转换。

2.2 数据清理

数据集的预处理主要分为两部分,分别是特征标准化和特征降维。

2.2.1特征标准化

调用sklearn中对数据进行标准化的函数处理样本X,特征标准化的过程如下:

from sklearn.preprocessing import StandardScaler
def standard_demo(data):
    transfer = StandardScaler()
    data_new = transfer.fit_transform(data)
    print(data_new)
    return data_new
if __name__ == '__main__':
    X_new = standard_demo(X)

2.2.2特征降维

考虑到样本中的特征维度为64维,可能包含一些相近的维度或噪音等,这些维度会影响算法模型的性能,容易产生过拟合等现象,因此,在数据清理时,需要对样本进行特征降维。实现代码如下:

from sklearn.decomposition import PCA
def pca_demo(data):
    transfer = PCA(n_components=0.92)
    data_new = transfer.fit_transform(data)
    print(data_new)
    return data_new
if __name__ == '__main__':
    X_new = pca_demo(X_new)

其中,在进行降维的过程中,保留原本数据集大小的百分比对与算法的准确率具有较大的影响,此次实验中,以KNN算法为例,从84%一直到96%,实验PCA降维之后算法的准确率,最终实验得到的结果如下表所示:

Percentage(%)	84	85	86	87	88	89	90	91	92	93	94	95	96
Accuracy	0.96	0.96	0.97	0.97	0.96	0.97	0.97	0.97	0.98	0.97	0.97	0.97	0.97

由于这是在调参之后测出的结果,所以在四舍五入之后,它们之间并没有很明显的差距,但是在保留原数据集92%的情况下,准确率依然很明显,故此次实验的降维参数n_components=0.92,特征维度降为34维,由此可见,数据集中的确存在大量的噪音或比较接近的特征维度。

2.3 机器学习建模

数据集已经准备好了,下一步就是建立机器学习算法模型,对模型进行训练。

2.3.1 KNN算法

我第一个选择的算法模型为KNN算法,因为它的原理比较简单,对于这种小数据集来说,理论上看它应该会有不错的表现,模型构建如下:

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
def knn_demo(data, label):
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(data, label, random_state=6)
    # 训练模型
    estimate = KNeighborsClassifier(n_neighbors=10)
estimate.fit(X_train, y_train)  # 模型构建好了
if __name__ == '__main__':
    knn_demo
### 机器学习手写字体识别实现方法 #### 使用支持向量机 (LinearSVC) 对于手写字体识别的任务,可以采用线性支持向量分类器(Linear Support Vector Classifier)。这种方法适用于较小规模的数据集,并能提供良好的泛化能力。具体来说,在Python环境中利用`sklearn.svm.LinearSVC`库函数构建模型并训练它以区分不同的手写数字[^1]。 ```python from sklearn import datasets, svm, metrics from sklearn.model_selection import train_test_split # 加载数据集 digits = datasets.load_digits() # 创建特征矩阵X和目标向量y n_samples = len(digits.images) data = digits.images.reshape((n_samples, -1)) target = digits.target # 将数据分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split( data, target, test_size=0.5, shuffle=False) # 初始化和支持向量机参数设置 classifier = svm.LinearSVC() # 训练模型 classifier.fit(X_train, y_train) # 预测新样本的结果 predicted = classifier.predict(X_test) print(f'Classification report:\n{metrics.classification_report(y_test, predicted)}') ``` #### 应用逻辑回归算法 另一种常见的做法是运用逻辑回归来进行多类别分类问题求解。此过程涉及收集足够的标记好类别的手写字符图像作为输入资料;接着预处理这些原始图片使之适应所选算法的要求;最后建立一个合适的预测框架完成最终目的——即对手写的阿拉伯数码做出精准判断[^4]。 ```python import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.datasets import fetch_openml from sklearn.model_selection import train_test_split mnist = fetch_openml('mnist_784', version=1) X, y = mnist["data"], mnist["target"] # 转换为目标变量为整型 y = y.astype(np.int8) # 构建管道:标准化 -> logistic regression clf = make_pipeline(StandardScaler(), LogisticRegression(max_iter=100)) # 分割成训练/验证集合 X_train, X_val, y_train, y_val = train_test_split(X, y) # 开始拟合模型 clf.fit(X_train, y_train) score = clf.score(X_val, y_val) print(f'Model accuracy on validation set is {score:.2f}') ``` #### 利用卷积神经网络(CNN)与PyTorch框架 随着深度学习的发展,特别是卷积神经网络的应用,使得自动从大量未标注数据中发现有用模式成为可能。相比于传统的方法论,这类技术更擅长捕捉到复杂的视觉结构特性而不需要过多依赖人工定义好的属性描述符。因此,在解决诸如OCR这样的实际挑战时表现出色[^3]。 ```python import torch import torchvision.transforms as transforms import torchvision.datasets as dsets from torch.utils.data import DataLoader import torch.nn.functional as F import torch.optim as optim class Net(torch.nn.Module): def __init__(self): super().__init__() self.conv1 = torch.nn.Conv2d(in_channels=1, out_channels=16, kernel_size=(5, 5), stride=(1, 1), padding='same') self.pool = torch.nn.MaxPool2d(kernel_size=2, stride=2, padding=0) self.fc1 = torch.nn.Linear(in_features=16 * 14 * 14, out_features=120) self.fc2 = torch.nn.Linear(in_features=120, out_features=84) self.fc3 = torch.nn.Linear(in_features=84, out_features=10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = x.view(-1, 16 * 14 * 14) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean=[0], std=[1])]) train_dataset = dsets.MNIST(root='./data', train=True, transform=transform, download=True) test_dataset = dsets.MNIST(root='./data', train=False, transform=transform) batch_size = 100 num_workers = 2 train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, num_workers=num_workers, shuffle=True) test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, num_workers=num_workers, shuffle=False) model = Net() criterion = torch.nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=.001, momentum=0.9) for epoch in range(1): # loop over the dataset multiple times running_loss = 0. for i, data in enumerate(train_loader, start=0): inputs, labels = data optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 200 == 199: # print every 200 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 200)) running_loss = 0. correct = 0 total = 0 with torch.no_grad(): for data in test_loader: images, labels = data
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sky.Grey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值