目录
一、数据准备
1. 获取数据集
2. 数据可视化
3. 数据清洗
二、特征提取
1. 数据标准化
2. 图像增强
三、模型训练
1. 划分训练集和测试集
2. 训练 SVM 模型
3. 参数调优
四、模型评估
1. 评估模型性能
2. 可视化结果
五、预测新图像
1. 加载和预处理新图像
编辑
完整代码
总结
专栏:机器学习笔记
总篇:学习路线
第一卷:线性回归模型
第二卷:逻辑回归模型
第三卷:决策树
数据准备是机器学习项目的基础步骤。数据的质量直接影响模型的性能和最终结果。在图像识别任务中,数据通常是大量的图像文件,我们需要将这些图像转化为适合模型处理的格式。我们将使用 MNIST 数据集,这是一个包含手写数字图像的标准数据集。
MNIST 数据集包含 70,000 个 28x28 像素的灰度图像,每个图像表示一个 0-9 的数字。这个数据集非常适合初学者进行机器学习和图像识别的练习。
首先,我们需要从公开数据源下载 MNIST 数据集。我们可以使用 fetch_openml
函数从 OpenML 平台下载该数据集:
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import fetch_openml # 下载 MNIST 数据集 mnist = fetch_openml('mnist_784', version=1) X, y = mnist["data"], mnist["target"] # 将标签转换为整数 y = y.astype(int) # 将 X 转换为 NumPy 数组 X = X.values
上述代码使用 fetch_openml
函数从 OpenML 平台下载 MNIST 数据集。数据存储在 X
和 y
中,X
包含图像数据,y
包含对应的标签。X
是一个包含 70,000 个样本的数组,每个样本是一个 784 维(28x28)的向量。y
是对应的标签,表示图像中的数字。
小李的理解:数据准备是整个过程的基础。就像建房子一样,地基要打好。如果数据质量不好,后续的模型训练和评估都可能会出问题。MNIST 数据集很好用,因为它已经预处理好了,但在实际应用中,可能需要更多的数据清洗和预处理工作。
为了更好地理解数据,我们可以可视化一些样本图像。这有助于直观地了解数据的分布和特征。
def plot_digit(data): image = data.reshape(28, 28) plt.imshow(image, cmap=plt.cm.binary, interpolation='nearest') plt.axis("off") # 显示前十个图像 plt.figure(figsize=(12, 8)) for i in range(10): plt.subplot(2, 5, i + 1) plot_digit(X[i]) plt.show()
通过这些代码,我们将展平的向量重新转换为 28x28 的图像,并使用 Matplotlib 绘制出来。这样可以直观地看到手写数字的样本图像。
小李的理解:数据可视化有助于我们直观地了解数据。如果我们能看到图像,就更容易理解模型为什么会做出某些预测。
虽然 MNIST 数据集已经经过了预处理,但在实际应用中,数据可能需要进行进一步清洗。数据清洗的目的是去除或修正数据中的错误和异常值。常见的数据清洗方法包括去除重复数据、填补缺失值和纠正数据格式等。在图像数据中,清洗过程可能包括去除模糊或损坏的图像。
在机器学习中,特征提取是将原始数据转换为模型能够处理的特征向量的过程。对于 MNIST 数据集,每个图像已经是 784 维的向量,因此我们不需要额外的特征提取步骤。
标准化是将数据的特征缩放到相同的尺度上,这有助于加快训练速度并提高模型的性能。在这里,我们使用 StandardScaler
对数据进行标准化处理。
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X)
StandardScaler
会将每个特征调整为均值为 0,标准差为 1 的分布,这样可以避免某些特征由于数值范围较大而对模型产生过大的影响。
小李的理解:标准化有助于确保模型不会被某些特征的数量级所主导。它让所有特征在同一个尺度上,更加公平地影响模型。
虽然在这次任务中我们不需要进行复杂的图像处理,但在实际应用中,图像增强是常见的步骤。图像增强技术可以通过旋转、缩放、裁剪、颜色变换等方式增加数据集的多样性,从而提升模型的泛化能力。例如,我们可以使用 OpenCV 或其他图像处理库进行数据增强。
import cv2 def augment_image(image): # 随机旋转图像 angle = np.random.randint(-15, 15) M = cv2.getRotationMatrix2D((14, 14), angle, 1) rotated = cv2.warpAffine(image, M, (28, 28)) # 随机缩放图像 scale = np.random.uniform(0.9, 1.1) scaled = cv2.resize(rotated, None, fx=scale, fy=scale) return scaled # 应用图像增强 augmented_images = np.array([augment_image(img.reshape(28, 28)).flatten() for img in X])
小李的理解:图像增强技术可以增加数据的多样性,有助于提高模型的泛化能力。在实际项目中,合理地使用图像增强技术是非常有必要的。
模型训练是机器学习过程中的关键步骤。在这个过程中,我们将使用支持向量机(SVM)来训练模型。SVM 是一种强大的分类算法,特别适用于高维数据。
首先,我们需要将数据集划分为训练集和测试集。训练集用于训练模型,测试集用于评估模型性能。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
上述代码将数据集划分为训练集(80%)和测试集(20%)。random_state
参数用于确保结果的可重复性。
小李的理解:将数据划分为训练集和测试集是为了能够评估模型的泛化能力。如果不划分数据,模型可能会过拟合,无法在新数据上表现良好。
接下来,我们使用线性核的 SVM 进行模型训练。线性核适用于数据线性可分的情况。
from sklearn.svm import SVC # 创建 SVM 分类器 svm_clf = SVC(kernel='linear', C=1) # 训练模型 svm_clf.fit(X_train, y_train)
在这段代码中,我们创建了一个线性核的 SVM 分类器,并使用训练集的数据训练模型。C
参数是正则化参数,控制模型的复杂度。较小的 C
值会使模型更简单,但可能欠拟合;较大的 C
值会使模型更复杂,但可能过拟合。
小李的理解:SVM 的目标是找到一个最佳的决策边界,将不同类别的样本分开。C 参数可以调节模型的复杂度,适当的 C 值可以避免过拟合或欠拟合。
在训练模型时,选择合适的参数是非常重要的。除了 C
参数外,SVM 的核函数也可以选择不同的类型,如多项式核、RBF 核等。我们可以使用网格搜索(Grid Search)来自动化选择最佳参数组合。
from sklearn.model_selection import GridSearchCV param_grid = [ {'C': [0.1, 1, 10, 100], 'kernel': ['linear']}, {'C': [0.1, 1, 10, 100], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']}, ] grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy') grid_search.fit(X_train, y_train) print("Best parameters:", grid_search.best_params_)
小李的理解:参数调优是提高模型性能的重要步骤。通过网格搜索,我们可以系统地测试不同的参数组合,找到最佳的模型配置。
在模型训练完成后,我们需要评估其性能。常用的评估指标包括准确率、精确率、召回率和 F1 值。此外,我们还可以使用混淆矩阵来进一步分析模型的表现。
我们使用测试集数据进行预测,并计算模型的评估指标。
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix y_pred = grid_search.predict(X_test) # 计算准确率 accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy}") # 打印分类报告 print("Classification Report:\n", classification_report(y_test, y_pred)) # 打印混淆矩阵 print("Confusion Matrix:\n", confusion_matrix(y_test, y_pred))
上述代码首先使用测试集的数据进行预测,然后计算并打印了模型的准确率、分类报告和混淆矩阵。准确率是正确分类的样本数与总样本数的比值。分类报告包含了每个类别的精确率、召回率和 F1 值。混淆矩阵显示了分类器在每个类别上的表现情况。
小李的理解:评估模型就像考试后的成绩单,不仅要看总分(准确率),还要看单科成绩(精确率、召回率等)。混淆矩阵对分析模型的分类能力特别有用,能看出哪些类别容易混淆。
为了更直观地理解模型的性能,我们可以可视化一些预测结果。
def plot_digits(images, labels, predictions, start_idx, num): plt.figure(figsize=(12, 8)) for i in range(num): plt.subplot(2, num//2, i + 1) plot_digit(images[start_idx + i]) plt.title(f"True: {labels[start_idx + i]}\nPred: {predictions[start_idx + i]}") plt.show() # 显示前十个预测结果 plot_digits(X_test, y_test, y_pred, 0, 10)
这段代码定义了一个函数 plot_digits
,用于绘制图像并显示真实标签和预测标签。我们使用它来可视化前十个预测结果。
小李的理解:可视化结果能直观地看到模型的预测效果,特别是可以发现哪些图像被错误分类,并分析其原因。
最后,我们来看一下如何使用训练好的模型来预测新图像的类别。
假设我们有一张新的手写数字图像,存储在文件 new_digit.png
中。我们需要加载这张图像,并将其转换为模型可以处理的格式。
import cv2 # 加载图像 img = cv2.imread('new_digit.png', cv2.IMREAD_GRAYSCALE) # 调整图像大小为 28x28 img_resized = cv2.resize(img, (28, 28)) # 展平图像为 784 维向量 img_flattened = img_resized.flatten() # 归一化图像 img_normalized = img_flattened / 255.0 # 标准化图像 img_standardized = scaler.transform([img_normalized]) # 预测图像类别 prediction = grid_search.predict(img_standardized) print(f"Predicted class: {prediction[0]}")
在这段代码中,我们使用 OpenCV 加载灰度图像,并将其调整为 28x28 的大小。然后展平图像为 784 维的向量,并归一化处理。接着,我们使用之前的标准化器对图像进行标准化处理。最后,我们使用训练好的 SVM 模型预测图像的类别。
小李的理解:预测新图像时,需要将图像转换为与训练数据相同的格式。这包括调整图像大小、展平成向量、归一化和标准化。这样,模型就可以理解并进行预测了。
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import fetch_openml from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.svm import SVC from sklearn.metrics import accuracy_score, classification_report, confusion_matrix import cv2 # 一、数据准备 # 1. 获取数据集 mnist = fetch_openml('mnist_784', version=1) X, y = mnist["data"], mnist["target"] y = y.astype(np.int) # 2. 数据可视化 def plot_digit(data): image = data.reshape(28, 28) plt.imshow(image, cmap=plt.cm.binary, interpolation='nearest') plt.axis("off") plt.figure(figsize=(12, 8)) for i in range(10): plt.subplot(2, 5, i + 1) plot_digit(X[i]) plt.show() # 二、特征提取 # 1. 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 三、模型训练 # 1. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42) # 2. 训练 SVM 模型 param_grid = [ {'C': [0.1, 1, 10, 100], 'kernel': ['linear']}, {'C': [0.1, 1, 10, 100], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']}, ] grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy') grid_search.fit(X_train, y_train) print("Best parameters:", grid_search.best_params_) # 四、模型评估 # 1. 评估模型性能 y_pred = grid_search.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy}") print("Classification Report:\n", classification_report(y_test, y_pred)) print("Confusion Matrix:\n", confusion_matrix(y_test, y_pred)) # 2. 可视化结果 def plot_digits(images, labels, predictions, start_idx, num): plt.figure(figsize=(12, 8)) for i in range(num): plt.subplot(2, num//2, i + 1) plot_digit(images[start_idx + i]) plt.title(f"True: {labels[start_idx + i]}\nPred: {predictions[start_idx + i]}") plt.show() plot_digits(X_test, y_test, y_pred, 0, 10) # 五、预测新图像 # 1. 加载和预处理新图像 img = cv2.imread('new_digit.png', cv2.IMREAD_GRAYSCALE) img_resized = cv2.resize(img, (28, 28)) img_flattened = img_resized.flatten() img_normalized = img_flattened / 255.0 img_standardized = scaler.transform([img_normalized]) prediction = grid_search.predict(img_standardized) print(f"Predicted class: {prediction[0]}")
支持向量机(SVM)进行图像识别的完整过程,包括从获取并可视化MNIST数据集、进行数据标准化、划分训练和测试集、通过网格搜索优化SVM模型、评估模型性能到预测新图像的各个步骤,并在代码中添加了调试输出和计时器以便更好地跟踪和优化整个过程。