机器学习1:西瓜3.0简单入门
通过实现“判断西瓜好坏”这一实验,简单介绍机器学习的大致过程,参考书籍:《西瓜书》
提取数据
1
2
3
4
5
6
7
| powershell:
pip install numpy
pip install pandas
# 导入库函数
import numpy as np
import pandas as pd
|
首先,我们的数据一般放在.csv或.xlsx等文件中,使用pandas库来进行读取,我们以.csv文件为例,使用阿里天池提供的西瓜数据3.0。
1
2
3
| # pandas 读取操作
df = pd.read_csv('watermelon_3.csv', encoding='utf-8-sig')
print(df.head())
|

特征工程
我们可以这样比喻:
数据处理就像是洗菜、切菜——把原材料弄干净、切成标准块。
特征工程则像是调味和搭配——不是简单地把菜丢进锅里,而是思考怎么组合、怎么处理,让最终的菜肴更好吃。
我们通常将特征,也就是属性,分为两类:数值属性和类别属性。
数值属性如“密度”和“含糖量”,他们已经是数字了,但是范围不同,我们需要采用标准化和归一化的方式来处理。
类别属性如“色泽”、“根蒂”和“敲声”,它们是文字,需要转换,我们通常可以采用one-hot,也就是独热编码来处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer
# 将“是”映射为 1,将“否”映射为 0
df['好瓜'] = df['好瓜'].map({'是': 1, '否': 0})
# 定义类别特征与数值特征
cat_features = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感']
num_features = ['密度', '含糖率']
# OneHotEncoder 处理类别特征,StandardScaler 处理数值特征
ct = ColumnTransformer(transformers=[
('cat', OneHotEncoder(sparse_output=False), cat_features),
('num', StandardScaler(), num_features)
])
# 获取处理后的特征矩阵 X 和 标签向量 y
X = ct.fit_transform(df)
y = df['好瓜'].values
# 查看转换后的结果维度
print(f"原始特征列数: {len(cat_features) + len(num_features)}")
print(f"处理后特征列数 (One-hot 展开后): {X.shape[1]}")
|

处理后的特征数据:
标签数据就是简单的0和1,这里就不做展示了。
划分数据集
将数据集划分为训练集和测试集,以避免在同一个数据集上同时进行训练和测试,造成过拟合。
1
2
3
4
5
6
7
8
| from sklearn.model_selection import train_test_split
# test_size=0.2 表示测试集占 20%
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"训练集样本数: {len(X_train)}, 测试集样本数: {len(X_test)}")
|

训练数据
大致就是下图所示这样,先用模型对训练集进行分类和矫正,优化参数,然后喂入测试集测试性能。

1
2
3
4
5
6
| # 训练
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
print("模型训练完成!")
print(f"模型参数为{model.coef_}")
|

测试性能
使用测试集测试性能,参考性能指标: 准确率、查准率和查全率(召回率)。
1
2
3
4
5
6
7
8
9
10
11
12
| # 测试
from sklearn.metrics import accuracy_score, precision_score, recall_score
# 使用模型对测试集进行预测
y_pred = model.predict(X_test)
# 计算参数
acc = accuracy_score(y_test, y_pred)
pre = precision_score(y_test, y_pred)
rec = recall_score(y_test, y_pred)
print(f"准确率: {acc:.2f}")
print(f"查准率: {pre:.2f}")
print(f"查全率: {rec:.2f}")
|

绘制ROC曲线图和计算AUC的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
# 获取模型预测的概率值
y_scores = model.predict_proba(X_test)[:, 1]
# 计算 FPR(假正率), TPR(真正率) 和 阈值
fpr, tpr, thresholds = roc_curve(y_test, y_scores)
# 计算 AUC 值(曲线下的面积)
roc_auc = auc(fpr, tpr)
# 绘图
plt.figure()
plt.plot(fpr, tpr, color='darkorange', label=f'ROC curve (area = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='navy', linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Watermelon 3.0 ROC Curve')
plt.legend(loc="lower right")
plt.grid(True)
plt.show()
|

我们得到了这样的ROC曲线图。
什么是ROC曲线图:ROC曲线图是用于评估二分类模型性能的一种重要工具。它以图形化的方式展示了模型在不同阈值设定下的表现。为了更直观地理解,可以把ROC曲线想象成一把“尺子”,用来衡量一个分类模型把“正类”和“负类”分开的能力。
ROC曲线图的横坐标是假正率,也就是模型错误地将“坏瓜”预测成“好瓜”的比例,这个比例对于我们而言,当然是越低越好;而纵坐标则是真正率,也就是模型把“好瓜”正确预测出来的比例,这个值越高越好。
至于阈值,就是判断好坏的标准值,大于或等于这个值,就预测为好瓜,小于这个值,就预测为坏瓜。
此外,AUC是指ROC曲线下的面积,范围在0到1之间。
1
2
3
4
| AUC = 1 完美模型
AUC > 0.5 比随机预测好,有预测价值
AUC = 0.5 和随机预测一样,没有预测价值
AUC < 0.5 比随机预测还差 (很少见,除非模型方向搞反了)
|
思考
可以看到,我们将80%的数据用作训练的话,得到的模型性能是很差的。
我们猜测是因为小测试集很难覆盖所有可能的特征组合。
为了验证这个猜测,我们可以对比测试集为20%、30% 和 50% 的模型性能。

观察上图我们可以看到,不同的测试集占比的模型训练出来的性能有所不同,其中占比20%的模型效果最差,和随机预测没两样,但随着占比增加到30%,模型效果变好,AUC变大。
但随着测试集占比来到50%时,模型效果又变差了,这或许是因为训练集不够导致模型的参数优化不够,从而导致模型性能不太行。
总结
通过上述实验,我们初步认识了机器学习的大致过程:
1
| 提取数据 -> 处理数据 -> 特征工程 -> 数据划分 -> 参数选择(如测试集占比)-> 训练模型 -> 测试性能
|