机器学习实战(3)——分类

本文详细探讨了机器学习中的分类问题,通过MNIST数据集为例,讲解了如何训练二元分类器,包括使用SGDClassifier,并通过交叉验证、混淆矩阵、精度和召回率等方法评估性能。此外,还讨论了多类别分类器的实现和错误分析,以及多标签和多输出分类的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 MNIST数据集

2 训练一个二元分类器

3 性能考核

3.1 使用交叉验证测量精度

3.2 混淆矩阵

3.3 精度和召回率

3.4 精度/召回率权衡

3.5 ROC曲线

4 多类别分类器

5 错误分析

6 多标签分类

7 多输出分类


MNIST数据集

MNIST数据集是一组由美国高中生和人口调查员手写的70 000个数字的图片,每张图像都用其代表的数字标记。

获取MNIST数据集:

from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1, cache=True, as_frame=False)
mnist["data"],mnist["target"]

运行结果如下:

(array([[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]]),
 array(['5', '0', '4', ..., '4', '5', '6'], dtype=object))

Scikit-Learm加载的数据集通常具有类似的字典结构,包括:

  • DESCR键:描述数据集
  • data键:包含一个数组,每个实例为一行,每个特征为一列
  • target键:包含一个带有标记的数组

我们来看看这些数组:

X, y = mnist["data"], mnist["target"]
X.shape, y.shape

运行结果如下:

((70000, 784), (70000,))

共有7万张图片,每张图片有784个特征。图片是28×28像素,每个特征代表一个像素点的强度。

我们随便抓取一个实例的特征向量:

import matplotlib as mpl
import matplotlib.pyplot as plt

# 抓取一个实例的特征向量

# 提取行数据
#方法一:
import numpy as np
some_digit = np.array(X[36000,])

#方法二:
# some_digit = X[36000]

some_digit_image = some_digit.reshape(28, 28)

#可视化
plt.imshow(some_digit_image, cmap = mpl.cm.binary,
           interpolation="nearest")
plt.axis("off")
plt.show()



#查看手写字标签
y[36000]

运行结果如下:

'9'

此处运行结果与书上的“5”不一样是由于fetch_openml()返回给我们的是未排序的数据。

有关plt.imshow()用法如下:(参考博客:plt.imshow()_小小程序猩的博客-优快云博客_plt.imshow

plt.imshow(
    X,
    cmap=None,
    norm=None,
    aspect=None,
    interpolation=None,
    alpha=None,
    vmin=None,
    vmax=None,
    origin=None,
    extent=None,
    shape=None,
    filternorm=1,
    filterrad=4.0,
    imlim=None,
    resample=None,
    url=None,
    *,
    data=None,
    **kwargs,
)




**X:**
图像数据。支持的数组形状是:
(M,N) :带有标量数据的图像。数据可视化使用色彩图。
(M,N,3) :具有RGB值的图像(float或uint8)。
(M,N,4) :具有RGBA值的图像(float或uint8),即包括透明度。
前两个维度(M,N)定义了行和列图片,即图片的高和宽;
RGB(A)值应该在浮点数[0, ..., 1]的范围内,或者
整数[0, ... ,255]。超出范围的值将被剪切为这些界限。
**cmap:**
将标量数据映射到色彩图
颜色默认为:rc:image.cmap。
**norm :**
~matplotlib.colors.Normalize
如果使用scalar data ,则Normalize会对其进行缩放[0,1]的数据值内。
默认情况下,数据范围使用线性缩放映射到颜色条范围。 RGB(A)数据忽略该参数。
**aspect:**
{'equal','auto'}或float,可选
控制轴的纵横比。该参数可能使图像失真,即像素不是方形的。
equal:确保宽高比为1,像素将为正方形。(除非像素大小明确地在数据中变为非正方形,坐标使用 extent )。
auto: 更改图像宽高比以匹配轴的宽高比。通常,这将导致非方形像素。
**interpolation:**
str
使用的插值方法
支持的值有:'none', 'nearest', 'bilinear', 'bicubic','spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser',
'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc','lanczos'.
如果interpolation = 'none',则不执行插值
**alpha:**
alpha值,介于0(透明)和1(不透明)之间。RGBA输入数据忽略此参数。
**vmin, vmax : scalar,**
如果使用* norm 参数,则忽略 vmin , vmax *。
vmin,vmax与norm结合使用以标准化亮度数据。
**origin : {'upper', 'lower'}**
将数组的[0,0]索引放在轴的左上角或左下角。
'upper'通常用于矩阵和图像。
请注意,垂直轴向上指向“下”但向下指向“上”。
**extent:(left, right, bottom, top)**
数据坐标中左下角和右上角的位置。 如果为“无”,则定位图像使得像素中心落在基于零的(行,列)索引上。

这里我们不需要创建测试集,因为MNIST数据集已经分成训练集(前6万张图像)和测试集(后1万张图像)了:

X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]

同样,我们需要先将训练数据洗牌,这样能保证交叉验证时所有的折叠都差不多(避免机器学习算法对训练实例的顺序敏感)。

import numpy as np
 
# 训练集随机重新排列
shuffle_index = np.random.permutation(60000) #生成一个随机排列的数组
X_train,y_train = X_train[shuffle_index], y_train[shuffle_index]

2 训练一个二元分类器

现在,我们先简化问题,只尝试识别一个数字——比如数字9。那么这个“数字9检测器” 就是一个二元分类器的例子,它只能区分两个类别:9和非9。先为此分类任务创建目标向量:

# 先尝试识别一个数字
y_train_9 = (y_train == '9')
y_test_9 = (y_test == '9')

接着挑选一个分类器并开始训练。一个好的初始选择是随机梯度下降(SGD(stochastic gradient descend))分类器, 使用 Scikit-Learn的SGDClassifier类即可。这个分类器的优势是,能够有效处理非常大型的数据集。这部分是因为SGD独立处理训练实例,一次一个(这也使得SGD非常适合在线学习)。此时先创建一个SGDClassifier并在整个训练集上进行训练:

from sklearn.linear_model import SGDClassifier

# sgd_clf = SGDClassifier(max_iter=9, tol=-np.infty, random_state=42)
# sgd_clf.fit(X_train, y_train_9)

sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train, y_train_9)

运行结果如下:

SGDClassifier(random_state=42)

由于SGDClassifier在训练时是完全随机的,如果我们每次运行想要得到相同的结果,需要设置随机数种子该参数random_state。max_iter=9, tol=-np.infty与random_state作用相同。

现在我们检验一下:

sgd_clf.predict([some_digit])

运行结果如下:

array([False])

分类器不认为这个图像是9,显然预测错了,下面评估一下这个模型的性能。

3 性能考核

3.1 使用交叉验证测量精度

交叉验证是一个评估模型的好办法。我们先看一下cross_val_score验证后的模型得分,采用K-flod交叉验证法,3个折叠(将训练集分成3个折叠,每次留其中一个折叠进行预测,剩余折叠用于训练):

from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train_9, cv=3, scoring="accuracy")

运行结果如下:

array([0.948  , 0.93885, 0.91695])

 注意:cross_val_score用法:

cross_val_score(estimator, X, y=None, *, groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch="2*n_jobs", error_score=np.nan)

#参数解释:

estimator:估计器,也就是模型
X, y:数据,标签值
soring:调用的方法
cv:交叉验证生成器或可迭代的次数
n_jobs:同时工作的cpu个数(-1代表全部)
verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出
fit_params:传递给估计器的拟合方法的参数
pre_dispatch:控制并行执行期间调度的作业数量。减少这个数量对于避免在CPU发送更多作业时CPU内存消耗的扩大是有用的。none,在这种情况下,所有的工作立即创建并产生。将其用于轻量级和快速运行的作业,以避免由于按需产生作业而导致延迟;一个int&#x
### 机器学习实战项目的材料、教程、示例代码和数据集 #### 探索型数据分析 (EDA) 在任何机器学习项目中,探索型数据分析是一个重要的初步阶段。通过 EDA 可以更好地理解数据特性并发现潜在模式。通常会使用 Pandas 和 Matplotlib 进行基础的数据处理与可视化。 ```python import pandas as pd import matplotlib.pyplot as plt # 加载数据集 data = pd.read_csv('dataset.csv') # 查看前几行记录 print(data.head()) # 描述统计信息 print(data.describe()) ``` #### 特征工程 特征工程对于提高模型性能至关重要。这一步骤涉及选择最能代表目标变量的输入属性,并可能创建新的衍生特征来增强模型的表现力[^1]。 ```python from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaled_features = scaler.fit_transform(features) ``` #### 建立线性回归模型 作为监督学习的一种方法,线性回归适用于数值预测问题。下面展示了如何利用 `sklearn` 库中的 `LinearRegression` 类建立简单线性回归模型: ```python from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) model = LinearRegression() model.fit(X_train, y_train) predictions = model.predict(X_test) mse = mean_squared_error(y_test, predictions) print(f'Mean Squared Error: {mse}') ``` #### 使用梯度提升树进行回归分析 除了传统的线性模型外,还可以尝试更复杂的算法如梯度提升决策树(GBDT),它能够捕捉非线性的关系,在许多实际应用中有更好的表现效果。 ```python gbdt_regressor = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42) gbdt_regressor.fit(X_train, y_train) gbdt_predictions = gbdt_regressor.predict(X_test) gbdt_mse = mean_squared_error(y_test, gbdt_predictions) print(f'Gradient Boosting MSE: {gbdt_mse}') ``` #### 利用逻辑回归分类手写数字图像 当面对二元或多类别分类任务时,可以考虑使用逻辑回归模型。这里给出一个简单的例子,展示如何训练一个识别 MNIST 手写字体图片集中数字的手工实现过程[^2]。 ```python logisticRegr = LogisticRegression(solver='lbfgs') logisticRegr.fit(train_img, train_lbl) score = logisticRegr.score(test_img, test_lbl) print(f'Test Accuracy: {score:.4f}') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值