什么是监督学习?
我们假设一下,你在教小朋友辨认水果。你拿起一个苹果说:“这是苹果。” 然后再拿起一个香蕉说:“这是香蕉。” 你不断重复这种过程,直到小朋友能准确地辨认苹果和香蕉。这就是监督学习的基本思路。
在机器学习的世界里,监督学习就是让机器从一堆已经标注好的数据中学习,然后它可以自己去判断新的数据。这些标注好的数据就像是你手中的苹果和香蕉——已经有了正确答案,机器只需要通过学习这些例子,来学会“看图识水果”。
监督学习的分类
监督学习主要有两种类型:
分类(Classification)
回归(Regression)
分类:分类就像是一个“多选题”,机器需要从几个选项中选出正确答案。比如判断一封邮件是垃圾邮件还是正常邮件,这就是一个二分类问题——只有两种可能的结果。当然,也有多分类问题,比如辨认不同种类的水果。
回归:回归则更像是一个“填空题”,机器需要预测一个连续的值。比如预测房价、股票价格等等。房子有多大?位置如何?这些特征都是填空题的提示,而最终答案就是房子的价格。
常见的监督学习算法
接下来,我们来聊聊一些常见的监督学习算法,就像是教小朋友辨认水果时用的方法一样,每种算法都有自己的“教学风格”。
K-近邻算法(K-Nearest Neighbors,KNN):
KNN 就像是“跟着邻居走”。想象一下,你走进一个新社区,想知道某个房子是属于哪个街区的。你可能会看看周围的房子,发现它们大多数属于某个特定街区。于是,你就猜测这个新房子也应该属于这个街区。KNN 就是这样工作的:它根据新数据点周围的“K”个最近邻的数据点来做出分类或预测。
决策树(Decision Tree):
决策树就像是一个“二十问题”游戏。你不断地问“是”或“否”问题,把问题的范围逐步缩小,直到最终得到答案。比如,判断一个动物是猫还是狗,你可能会先问“它会汪汪叫吗?”如果答案是“是”,那么它更可能是狗;如果“不是”,那可能是猫。决策树就是通过这种层层筛选的方式来做出决策。
备注:
“二十问题游戏”是一种有趣的猜谜游戏,玩法很简单:一方想出一个物品或概念,而另一方则可以通过问最多20个是非问题来猜出这个物品或概念的是什么。问题的回答只能是“是”或“否”。
举个例子,如果我想的是一只猫,你可能会问:
这是一个动物吗?
它能飞吗?
它有四条腿吗?
它会汪汪叫吗?
通过这些问题,你逐步缩小了范围,直到你有足够的信息猜出答案是“猫”。这个游戏考验的是你提出问题的策略和逻辑推理能力,随着问题的推进,你越来越接近正确答案。
这个游戏的思路和决策树算法有点相似——通过一系列“是”或“否”的问题来逐步缩小可能的选项范围,最终得到答案。
支持向量机(Support Vector Machine,SVM):
SVM 就像是“划分两块地”。想象你在一块地上种植两种不同的作物,想要用篱笆把它们分开。SVM 会找到那条最佳的篱笆,让两种作物尽可能远离对方。对于分类问题,SVM 会找到一条最佳分界线,把不同类别的数据点分开。
线性回归(Linear Regression):
线性回归就像是“画一条直线”。假设你要预测一家商店的销售额,你可能会根据过去的销售数据画一条直线,看看它的趋势如何。这条直线就是线性回归的结果,它能帮助你预测未来的销售情况。
朴素贝叶斯(Naive Bayes):
朴素贝叶斯就像是“先入为主的猜测”。假设你知道绝大多数苹果都是红色的,那么当你看到一个红色的水果时,你可能会猜它是苹果。朴素贝叶斯算法就是基于这种“先入为主”的概率来进行分类的。
监督学习就像是教小朋友辨认水果一样,通过不断学习标注好的数据,让机器学会去识别新的数据。不同的算法就像是不同的教学方法,各有各的优点和适用场景。KNN、决策树、SVM、线性回归和朴素贝叶斯这些常见的算法,就像是我们教学工具箱里的五种工具,掌握它们,我们就能更好地理解和应用监督学习。
实践环节:
在进行实践之前我们先了解一下Sklearn:
Sklearn,全名是Scikit-learn,是一个基于Python的机器学习库。它是由各种不同的机器学习算法和工具组成的,让数据科学家和工程师可以更轻松地构建、训练和评估机器学习模型。
Sklearn有丰富的算法库,Sklearn包含了从简单到复杂的各种机器学习算法,比如线性回归、支持向量机、决策树、随机森林等等。不管你是要做分类、回归、聚类还是降维,Sklearn都能帮你搞定。
Sklearn的API设计非常简洁,使用起来就像搭积木一样。你只需要几行代码,就可以完成数据预处理、模型训练和预测。
Sklearn的文档非常详细,而且有大量的教程、示例和社区讨论,让你在学习和使用过程中遇到问题时能快速找到答案。Sklearn可以很方便地与其他Python库集成,比如NumPy、Pandas和Matplotlib,这使得数据处理、分析和可视化变得更加方便。
下面我们使用Sklearn对监督学习常用的算法进行演示:
a. K-近邻算法(K-Nearest Neighbors, KNN)示列:
假设我们有一些水果的特征数据(如重量和颜色深度),我们想通过这些特征来预测一种新水果是苹果还是香蕉,代码如下:
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
# 1. 创建训练数据
# 数据格式:[重量, 颜色深度]
X = np.array([[150, 1], [160, 1], [170, 0], [180, 0], [120, 1], [130, 1], [140, 0], [150, 0]])
# 0代表苹果,1代表香蕉
y = np.array([0, 0, 1, 1, 0, 0, 1, 1])
# 2. 创建KNN分类器
# 参数 n_neighbors=3 表示我们将使用最近的3个邻居来进行投票决定分类。
knn = KNeighborsClassifier(n_neighbors=3)
# 3. 用训练数据拟合模型
knn.fit(X, y)
# 4. 创建新水果的特征数据来进行预测
new_fruit = np.array([[160, 0]])
# 5. 预测新水果的类别
predicted_class = knn.predict(new_fruit)
# 6. 输出预测结果
if predicted_class == 0:
print("预测结果:这个水果是苹果。")
else:
print("预测结果:这个水果是香蕉。")
# 7. 可视化数据
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm', label='Training Data')
plt.scatter(new_fruit[:, 0], new_fruit[:, 1], color='green', marker='*', s=200, label='New Fruit')
plt.xlabel('Weight')
plt.ylabel('Color Depth')
plt.title('K-Nearest Neighbors (KNN)')
plt.legend()
plt.show()
# 输出
预测结果:这个水果是香蕉。
b. 决策树(Decision Tree)示例:
我们将使用Scikit-learn库中的决策树分类器决策树(Decision Tree)来处理一个经典的鸢尾花数据集(Iris dataset),这是一个常用于测试机器学习算法的数据集。
鸢尾花数据集是一个经典的机器学习数据集,用于分类和模式识别任务。它由著名的统计学家和生物学家埃德加·安德森(Edgar Anderson)于1930年代首次引入,并由著名的统计学家和计算机科学家罗纳德·费希尔(Ronald A. Fisher)在1936年进行了介绍。这个数据集包含了三种鸢尾花(Iris species)的数据:Setosa、Versicolor和Virginica。
数据集结构说明:
数据特征:
萼片长度(Sepal Length):鸢尾花的萼片(花萼)的长度,单位是厘米(cm)。
萼片宽度(Sepal Width):鸢尾花的萼片的宽度,单位是厘米(cm)。
花瓣长度(Petal Length):鸢尾花的花瓣的长度,单位是厘米(cm)。
花瓣宽度(Petal Width):鸢尾花的花瓣的宽度,单位是厘米(cm)。
每个特征都有一个浮点数值,用于描述每朵鸢尾花的物理特性。
标签:
Iris Setosa:第一种鸢尾花。
Iris Versicolor:第二种鸢尾花。
Iris Virginica:第三种鸢尾花。
每个样本都有一个对应的类别标签,用于表示花的种类。
数据样本数量:总共150个样本。
每种鸢尾花的样本数量:每种鸢尾花各50个样本。
数据格式:数据集通常以二维数组的形式提供,其中每一行代表一朵鸢尾花的特征,最后一列是花的类别标签。
数据示例(单行数据):
鸢尾花数据集是机器学习和统计学中的标准测试数据集,用于:
分类任务:用于测试和评估分类算法的性能。
数据可视化:用于演示和练习数据可视化技巧。
模型验证:用于进行模型验证和调整。
代码如下:
# 导入必要的库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report
import matplotlib.pyplot as plt
from sklearn import tree
# 1. 加载数据
iris = load_iris()
X = iris.data
y = iris.target
# 2. 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. 创建决策树分类器
clf = DecisionTreeClassifier()
# 4. 训练模型
clf.fit(X_train, y_train)
# 5. 进行预测
y_pred = clf.predict(X_test)
# 6. 评估模型
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
print("nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# 7. 绘制决策树
plt.figure(figsize=(12,8))
tree.plot_tree(clf, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.show()
# 8. 绘制训练数据和测试数据的散点图
plt.figure(figsize=(14, 7))
# 绘制训练数据
plt.subplot(1, 2, 1)
for i, color in zip(range(3), ['red', 'green', 'blue']):
plt.scatter(X_train[y_train == i, 0], X_train[y_train == i, 1], color=color, label=iris.target_names[i])
plt.title('Training Data')
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.legend()
# 绘制测试数据
plt.subplot(1, 2, 2)
for i, color in zip(range(3), ['red', 'green', 'blue']):
plt.scatter(X_test[y_test == i, 0], X_test[y_test == i, 1], color=color, label=iris.target_names[i])
plt.title('Test Data')
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.legend()
plt.tight_layout()
plt.show()
# 输出
Accuracy: 1.00
Classification Report:
precision recall f1-score support
setosa 1.00 1.00 1.00 19
versicolor 1.00 1.00 1.00 13
virginica 1.00 1.00 1.00 13
accuracy 1.00 45
macro avg 1.00 1.00 1.00 45
weighted avg 1.00 1.00 1.00 45
c. 支持向量机(Support Vector Machine,SVM)示例:
本次我们使用支持向量机来处理一个经典的鸢尾花数据集,数据集信息已在上个例子说明,代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report
from sklearn.decomposition import PCA
# 1. 加载数据
iris = load_iris()
X = iris.data
y = iris.target
# 2. 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. 降维到2维(用于可视化)
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)
# 4. 创建支持向量机分类器
svm = SVC(kernel='linear') # 使用线性核函数
# 5. 训练模型
svm.fit(X_train_pca, y_train)
# 6. 进行预测
y_pred = svm.predict(X_test_pca)
# 7. 评估模型
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
print("nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# 8. 绘制决策边界
plt.figure(figsize=(12, 6))
# 绘制训练数据
plt.subplot(1, 2, 1)
plt.scatter(X_train_pca[y_train == 0, 0], X_train_pca[y_train == 0, 1], color='red', label='Setosa', marker='o')
plt.scatter(X_train_pca[y_train == 1, 0], X_train_pca[y_train == 1, 1], color='green', label='Versicolor', marker='x')
plt.scatter(X_train_pca[y_train == 2, 0], X_train_pca[y_train == 2, 1], color='blue', label='Virginica', marker='^')
# 绘制决策边界
xx, yy = np.meshgrid(np.linspace(X_train_pca[:, 0].min(), X_train_pca[:, 0].max(), 500),
np.linspace(X_train_pca[:, 1].min(), X_train_pca[:, 1].max(), 500))
Z = svm.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.get_cmap('coolwarm'))
plt.title('SVM Decision Boundary (Training Data)')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend()
# 绘制测试数据
plt.subplot(1, 2, 2)
plt.scatter(X_test_pca[y_test == 0, 0], X_test_pca[y_test == 0, 1], color='red', label='Setosa', marker='o')
plt.scatter(X_test_pca[y_test == 1, 0], X_test_pca[y_test == 1, 1], color='green', label='Versicolor', marker='x')
plt.scatter(X_test_pca[y_test == 2, 0], X_test_pca[y_test == 2, 1], color='blue', label='Virginica', marker='^')
# 绘制决策边界
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.get_cmap('coolwarm'))
plt.title('SVM Decision Boundary (Test Data)')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend()
plt.tight_layout()
plt.show()
# 输出
Accuracy: 0.98
Classification Report:
precision recall f1-score support
setosa 1.00 1.00 1.00 19
versicolor 0.93 1.00 0.96 13
virginica 1.00 0.92 0.96 13
accuracy 0.98 45
macro avg 0.98 0.97 0.97 45
weighted avg 0.98 0.98 0.98 45
d. 线性回归(Linear Regression)示例:
线性回归是一种基本的回归分析方法,用于建立一个目标变量(y)与一个或多个自变量(x)之间的线性关系。代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 1. 生成示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1) # 生成100个样本的特征数据
y = 4 + 3 * X + np.random.randn(100, 1) # 目标变量,包含线性关系和一些噪声
# 2. 创建线性回归模型
lin_reg = LinearRegression()
# 3. 训练模型
lin_reg.fit(X, y)
# 4. 进行预测
y_pred = lin_reg.predict(X)
# 5. 评估模型
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"Mean Squared Error: {mse:.2f}")
print(f"R^2 Score: {r2:.2f}")
# 6. 绘制结果
plt.figure(figsize=(10, 6))
# 绘制数据点
plt.scatter(X, y, color='blue', label='Data Points')
# 绘制回归线
plt.plot(X, y_pred, color='red', linewidth=2, label='Regression Line')
plt.title('Linear Regression')
plt.xlabel('Feature')
plt.ylabel('Target')
plt.legend()
plt.grid(True)
plt.show()
# 输出
Mean Squared Error: 0.99
R^2 Score: 0.75
e. 朴素贝叶斯(Naive Bayes)示例:
朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理的分类算法,适用于分类问题。它的"朴素"之处在于假设特征之间是条件独立的,这种假设在实际情况中可能不完全成立,但在许多场景下,朴素贝叶斯仍然表现出色。
在这里,我们依旧使用 scikit-learn 提供的鸢尾花数据集作为示例,演示如何使用朴素贝叶斯进行分类。代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import seaborn as sns
# 1. 加载数据
iris = load_iris()
X = iris.data
y = iris.target
feature_names = iris.feature_names
target_names = iris.target_names
# 2. 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. 创建朴素贝叶斯模型
nb_model = GaussianNB()
# 4. 训练模型
nb_model.fit(X_train, y_train)
# 5. 进行预测
y_pred = nb_model.predict(X_test)
# 6. 评估模型
accuracy = accuracy_score(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
class_report = classification_report(y_test, y_pred, target_names=target_names)
print(f"Accuracy: {accuracy:.2f}")
print("Confusion Matrix:")
print(conf_matrix)
print("Classification Report:")
print(class_report)
# 7. 可视化混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=target_names, yticklabels=target_names)
plt.title('Confusion Matrix')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()
# 输出
Accuracy: 0.98
Confusion Matrix:
[[19 0 0]
[ 0 12 1]
[ 0 0 13]]
Classification Report:
precision recall f1-score support
setosa 1.00 1.00 1.00 19
versicolor 1.00 0.92 0.96 13
virginica 0.93 1.00 0.96 13
accuracy 0.98 45
macro avg 0.98 0.97 0.97 45
weighted avg 0.98 0.98 0.98 45