利用python 实现手写数字识别
·
手写数字识别是计算机视觉和机器学习中的一个经典问题。下面我将介绍如何使用 Python 和几种常见的方法来实现手写数字识别。
方法一:使用 Scikit-learn 和 MNIST 数据集
1. 安装必要的库
bash
pip install numpy scikit-learn matplotlib
2. 代码实现
python
import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# 加载MNIST数据集
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X, y = mnist.data, mnist.target
# 数据预处理
X = X / 255.0 # 归一化像素值到0-1范围
y = y.astype(np.uint8) # 将标签转换为整数
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练逻辑回归模型
model = LogisticRegression(max_iter=1000, random_state=42)
model.fit(X_train, y_train)
# 预测并评估模型
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy:.4f}")
# 可视化一些预测结果
fig, axes = plt.subplots(2, 5, figsize=(10, 4))
for i, ax in enumerate(axes.flat):
ax.imshow(X_test[i].reshape(28, 28), cmap='gray')
ax.set_title(f"预测: {y_pred[i]}\n真实: {y_test[i]}")
ax.axis('off')
plt.tight_layout()
plt.show()
方法二:使用 TensorFlow/Keras 和神经网络
1. 安装 TensorFlow
bash
pip install tensorflow
2. 代码实现
python
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
# 加载MNIST数据集
(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data()
# 数据预处理
X_train = X_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
X_test = X_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0
# 构建CNN模型
model = keras.Sequential([
keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Conv2D(64, (3, 3), activation='relu'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Flatten(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
history = model.fit(X_train, y_train, epochs=5, validation_split=0.1)
# 评估模型
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"测试准确率: {test_acc:.4f}")
# 预测
predictions = model.predict(X_test)
# 可视化一些预测结果
fig, axes = plt.subplots(2, 5, figsize=(12, 5))
for i, ax in enumerate(axes.flat):
ax.imshow(X_test[i].reshape(28, 28), cmap='gray')
pred_label = np.argmax(predictions[i])
ax.set_title(f"预测: {pred_label}\n真实: {y_test[i]}")
ax.axis('off')
plt.tight_layout()
plt.show()
方法三:使用 PyTorch
1. 安装 PyTorch
bash
pip install torch torchvision
2. 代码实现
python
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 定义数据转换
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
# 加载数据集
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transform)
# 创建数据加载器
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
# 定义神经网络模型
class NeuralNet(nn.Module):
def __init__(self):
super(NeuralNet, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10)
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNet().to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练模型
num_epochs = 5
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.to(device)
labels = labels.to(device)
# 前向传播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (i+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}')
# 测试模型
model.eval()
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'测试准确率: {100 * correct / total:.2f}%')
# 可视化一些预测结果
dataiter = iter(test_loader)
images, labels = next(dataiter)
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs, 1)
# 将图像转换回CPU并准备显示
images = images.cpu()
fig, axes = plt.subplots(2, 5, figsize=(12, 5))
for i, ax in enumerate(axes.flat):
ax.imshow(images[i].squeeze(), cmap='gray')
ax.set_title(f"预测: {predicted[i].item()}\n真实: {labels[i].item()}")
ax.axis('off')
plt.tight_layout()
plt.show()
总结
以上三种方法都可以实现手写数字识别:
-
Scikit-learn方法:简单快速,适合初学者和理解基本概念
-
TensorFlow/Keras方法:使用CNN,准确率更高,适合深度学习入门
-
PyTorch方法:更灵活,适合研究和自定义模型
对于实际应用,推荐使用深度学习方法(TensorFlow或PyTorch),因为它们通常能获得更高的准确率。如果你刚开始学习,可以从Scikit-learn开始,然后逐步过渡到深度学习方法。
你可以根据自己的需求和硬件条件选择合适的方法。如果有GPU支持,深度学习方法训练速度会快很多。
更多推荐


所有评论(0)