1.K近邻算法
1.1基本思想
对于待判断的点,找到离他最近的几个数据点,根据他们的类型决定待判断点的类型。可用于分类问题,也可以用于回归问题。
1.2基本步骤
- 数据准备:首先,我们需要收集和准备带有标签的训练数据集,其中包括输入样本的特征以及对应的类别或目标值。
- 计算距离:对于一个新的未知样本,我们需要计算它与训练集中每个样本的距离。通常使用欧氏距离、曼哈顿距离等度量方法来衡量样本之间的距离。
- 选择K值:K值是KNN算法中的一个重要参数,表示选择离待预测样本最近的K个训练样本作为参考。K的取值决定了模型的复杂度和泛化能力,可以通过交叉验证等方法选择合适的K值。
- 确定类别:根据选定的K值,在距离待预测样本最近的K个训练样本中统计各个类别的数量,然后根据多数投票原则确定待预测样本的类别。即将K个最接近的样本中出现次数最多的类别标记为待预测样本的类别。
- 预测结果:将待预测样本分类到出现次数最多的类别中,作为预测结果。
1.3优缺点
- 优点:1.理论成熟,思想简单 2.可用于非线性 3.准确度高 4.对异常值不敏感。
- 缺点:1.计算量大 2.样本不均衡的问题 3.需要大量的内存。
1.4案例-鸢尾花分类
假设我们有一个鸢尾花数据集,其中包含了150个样本,每个样本有4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度),以及它们对应的类别(山鸢尾、变色鸢尾、维吉尼亚鸢尾)。我们可以使用K近邻算法来根据花萼和花瓣的测量值来预测一朵鸢尾花属于哪个类别。
python
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data # 特征向量
y = iris.target # 标签
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用K近邻算法进行分类
knn_classifier = KNeighborsClassifier(n_neighbors=3) # 选择K=3
knn_classifier.fit(X_train, y_train)
y_pred = knn_classifier.predict(X_test)
# 模型评估
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy: ", accuracy)
上述代码中,使用Scikit-Learn库中自带的load_iris()函数加载鸢尾花数据集。然后,将数据集划分为训练集和测试集,并使用KNeighborsClassifier类定义一个K近邻分类器模型。在这个例子中,选择K=3作为模型的参数,表示选取距离待预测样本最近的3个训练样本作为参考。最后,使用测试集对模型进行评估,并输出准确率。
2.K-means
2.1基本思想
物以类聚,人以群分。K-means算法通过迭代的方式不断优化聚类中心的位置,使得数据点与所属聚类中心之间的距离最小化。在每次迭代中,数据点被重新分配到最近的聚类中心所属的簇,然后更新每个簇的聚类中心。
2.2基本步骤
- 初始化:选择要将数据集分成的簇的数量K,并随机选择K个数据点作为初始的聚类中心。
- 分配数据点:对于数据集中的每个数据点,计算其与每个聚类中心的距离,并将其分配给距离最近的聚类中心所属的簇。
- 更新聚类中心:对于每个簇,计算其所有数据点的平均值,将其作为新的聚类中心。
- 重复步骤2和步骤3,直到达到停止条件。停止条件可以是达到最大迭代次数、聚类中心不再发生变化或达到预定义的误差阈值等。
- 得到最终的聚类结果。
2.3优缺点
- 优点:1. 原理简单,容易实现 2. 内存占用小
- 缺点:
-
K值需要预先给定,属于预先知识,很多情况下K值的估计是非常困难的,对于像计算全部微 信用户的交往圈这样的场景就完全的没办法用K-Means进行。
-
K-Means算法对初始选取的聚类中心点是敏感的,不同的随机种子点得到的聚类结果完全不 同(K-Means++)。
-
K均值算法并不适合所有的数据类型。
-
对离群点的数据进行聚类时,K均值也有问题,这种情况下离群点检测和删除有很大的帮助。
2.4案例-客户分类
假设我们有一家电商平台,想要对客户进行分组,以便更好地了解他们的购买行为和推荐相关产品。我们收集了一些客户的数据,包括每个客户的年龄和购买金额。我们可以使用K-means算法将客户分成不同的群组,以便更好地理解他们的购买行为。
python
import numpy as np
def kmeans(data, K, max_iters=100):
# 随机初始化聚类中心
centers = data[np.random.choice(len(data), K, replace=False)]
for _ in range(max_iters):
# 分配数据点到最近的聚类中心
labels = np.argmin(np.linalg.norm(data[:, np.newaxis] - centers, axis=2), axis=1)
# 更新聚类中心为簇内数据点的平均值
new_centers = np.array([data[labels == k].mean(axis=0) for k in range(K)])
# 检查聚类中心是否变化
if np.allclose(centers, new_centers):
break
centers = new_centers
return labels, centers
# 生成随机数据集
np.random.seed(0)
data = np.random.rand(100, 2) # 100个二维数据点
# 执行K-means聚类
K = 3
labels, centers = kmeans(data, K)
# 打印每个数据点的簇标签和聚类中心
print("簇标签:", labels)
print("聚类中心:", centers)
上述代码中,首先定义了一个kmeans函数,它接收数据集、簇的数量K和最大迭代次数作为输入。在函数内部,随机选择K个数据点作为初始的聚类中心,并进行迭代优化。在每次迭代中,根据数据点与聚类中心的距离将其分配到最近的簇。然后,根据每个簇内数据点的平均值更新聚类中心。这样反复迭代直到达到停止条件为止。
3.线性回归
3.1基本思想
线性回归假设目标值与特征之间线性相关,即满足一个多元一次方程。通过构建损失函数,来求解损失函数最小时的参数w和b。
3.2具体介绍
线性回归是一种用于建立线性模型的机器学习算法,它用于预测一个连续的目标变量。线性回归的目标是通过拟合最佳直线来描述自变量与因变量之间的关系。
在线性回归中,我们假设自变量(输入特征)和因变量(输出变量)之间存在线性关系。线性回归模型通过以下方程表示:
y = b0 + b1 * x1 + b2 * x2 + ... + bn * xn
其中,y是因变量,x1, x2, ..., xn 是自变量,b0, b1, b2, ..., bn 是待估计的系数。
线性回归的目标是找到最佳的系数,使得模型预测的值与实际观测值之间的差异最小化。这通常通过最小化损失函数来实现,常用的损失函数是均方误差
3.3优缺点
- 优点:1.模型简单,容易实现 2.许多非线性模型的基础 3.机器学习的基石
- 缺点:1.对于非线性数据或者数据特征间具有相关性多项式回归难以建模 2.难以很好地表达高度复杂的数据
3.4应用案例-房屋特征预测房价
将使用一些特征(如房屋面积、卧室数量、所在地区等)来预测房价(因变量)。收集有关房屋特征和房价的数据。使用Python中的一些机器学习工具和库来构建我们的线性回归模型。
python
from sklearn import linear_model
import pandas as pd
# 1. 加载数据
data = pd.read_csv('house_data.csv')
# 2. 准备数据
X = data[['Area', 'Bedrooms']] # 取出特征
y = data['Price'] # 取出目标变量
# 3. 训练模型
model = linear_model.LinearRegression()
model.fit(X, y)
# 4. 使用模型进行预测
X_test = [[1500, 3], [2000, 4]]
y_pred = model.predict(X_test)
print(y_pred)
在上述代码中,我们首先使用Pandas库加载房屋数据,并选择Area和Bedrooms作为自变量,Price作为因变量。然后,我们使用Scikit-Learn库中的LinearRegression类来训练一个线性回归模型,并使用predict()函数来进行预测。最后,我们将新的房屋特征(面积1500和3个卧室,面积2000和4个卧室)作为输入传递给模型,并输出了预测的房价。
4.逻辑回归
4.1基本思想
逻辑回归是机器学习从统计领域借鉴的另一种技术。 这是二分类问题的专用方法(两个类值的问题)。与线性回归不同的是,输出的预测值得使用称为逻辑函数的非线性函数进行变换。逻辑函数看起来像一个大S,并能将任何值转换为0到1的范围内。
4.2具体介绍
逻辑回归是一种广泛应用于分类问题的机器学习算法。与线性回归不同,逻辑回归的因变量是离散的而不是连续的。
逻辑回归的目标是根据自变量(输入特征)来预测因变量的概率。它使用逻辑函数(也称为sigmoid函数)将线性组合转换为概率值,通常使用以下形式表示:
P(y=1|x) = 1 / (1 + e^(-z))
其中,P(y=1|x) 是给定输入特征 x 条件下因变量 y 为1的概率,z 是线性组合 b0 + b1 * x1 + b2 * x2 + ... + bn * xn。
在训练过程中,我们使用最大似然估计或其他优化算法来找到最佳的系数 b0, b1, b2, ..., bn,以最大化真实标签的概率。
4.3优缺点
- 优点:1.实现简单,广泛应用于工业上 2.分类时计算量非常小,速度很快,存储资源少 3.可观测样本的概率分数。
- 缺点:1.特征空间很大时,性能不是很好 2.容易前拟合,一般准确度不高 3.只能处理二分类线性可分问题。
4.4案例-预测患者是否患有糖尿病
使用Python中的Scikit-Learn库和Kaggle数据集进行二分类预测。该数据集包含有关患有糖尿病的女性的医疗数据,我们将使用这些数据来预测患者是否患有糖尿病。
python
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
# 1. 加载数据
df = pd.read_csv('diabetes.csv')
# 2. 准备数据
X = df.drop('Outcome', axis=1)
y = df['Outcome']
# 3. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 4. 创建模型并拟合数据
model = LogisticRegression()
model.fit(X_train, y_train)
# 5. 使用模型进行预测
y_pred = model.predict(X_test)
# 6. 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
使用Pandas库加载糖尿病数据集。然后,准备数据,将自变量(所有特征列)存储在X中,因变量(二分类标签列)存储在y中。接下来,随机选择20%的数据作为测试集,并使用LogisticRegression类创建逻辑回归模型。接下来,通过fit()函数拟合数据来训练模型。然后,使用predict()函数进行预测,并计算预测结果与真实标签的准确率。
5.决策树
5.1基本思想
决策树的基本思想是通过一系列的判断条件对数据进行分类或预测。它类似于人类在做决策时所使用的"是"或"否"的问题,在每个节点上根据某个特征进行划分,直到达到预定的终止条件为止。
5.2构建过程
- 特征选择:根据某个度量准则(如信息增益、基尼指数等),选择最佳的特征作为当前节点的划分标准。
- 划分数据集:根据选定的特征,将数据集划分成不同的子集,每个子集对应一个分支或子节点。
- 递归构建子树:对每个子集重复步骤1和步骤2,直到满足终止条件,如达到最大深度、节点包含的样本数小于阈值等。
- 添加叶节点:当到达终止条件时,将叶节点添加到决策树中,该叶节点表示所属类别或回归值。
- 剪枝(可选):为了避免过拟合,可以对构建好的决策树进行剪枝操作,删除一些无关或冗余的节点。
5.3优缺点
- 优点:1.计算简单,易于理解,可解释行强;2.比较适合有缺失属性的样本;3.能够处理连续和离散特征;4.在短时间内可以对大型数据做出好的结果。
- 缺点:1.容易发生过拟合;2.对异常值敏感;3.忽略了数据之间的相关性;4.各个类别样本数量不一致的数据,信息增益偏向具有更多数值的特征。
5.4案例-预测一个人是否会购买某个产品
Dart
以下是一个简单的决策树案例,用于预测一个人是否会购买某个产品,假设有以下特征:年龄、收入和职业。
数据集如下:
序号 年龄 收入 职业 是否购买
1 青年 高 学生 否
2 青年 中等 白领 否
3 中年 中等 白领 是
4 老年 中等 白领 是
5 老年 低 蓝领 是
6 老年 低 学生 否
7 中年 高 学生 是
8 青年 中等 蓝领 否
9 青年 低 白领 否
10 老年 高 蓝领 是
基于以上数据,我们可以使用决策树算法来构建一个分类模型。
首先选择最佳的特征进行划分。可以使用信息增益或基尼指数等来评估特征的重要性。选择使用基尼指数。
首先计算整个数据集的基尼指数:
否的数量为6,是的数量为4,总样本数为10。
否的概率为6/10,是的概率为4/10。
整个数据集的基尼指数为1 - (6/10)^2 - (4/10)^2 ≈ 0.48。
然后按照每个特征的不同值划分数据集,并计算每个划分的基尼指数,选取具有最小基尼指数的特征进行划分。
通过计算可以得出,收入的基尼指数最小,因此我们将以收入作为第一次划分的特征。
在收入为高的情况下,所有样本都是"是",因此可以直接生成一个"是"的叶节点。
我们继续选择下一个最佳特征进行划分,可以计算年龄和职业的基尼指数。在这个例子中,我们选择使用年龄。
在年龄为青年的情况下,所有样本都是"否",因此可以直接生成一个"否"的叶节点。
我们继续选择下一个最佳特征进行划分,可以计算职业的基尼指数。
在职业为白领的情况下,所有样本都是"是",因此可以直接生成一个"是"的叶节点。
在职业为学生的情况下,所有样本都是"是",因此可以直接生成一个"是"的叶节点。
python
收入
├── 高: 是
├── 中等
│ ├── 年龄
│ │ ├── 青年: 否
│ │ └── 中年
│ │ ├── 职业
│ │ │ ├── 白领: 是
│ │ │ └── 学生: 是
└── 低: 是
这个决策树可以用来预测一个人是否会购买某个产品。在预测时,我们根据特征的取值沿着决策树依次判断,
直到达到叶节点,然后根据叶节点的类别标签进行预测。
python
# 定义训练数据集
training_data = [
['青年', '否'],
['中年', '否'],
['中年', '是'],
['老年', '是'],
['老年', '是'],
['青年', '否'],
['中年', '否'],
['青年', '是']
]
# 定义特征名称
feature_names = ['年龄']
# 定义类别名称
target_names = ['否', '是']
# 定义决策树节点类
class Node:
def __init__(self, feature_index=None, threshold=None, label=None):
self.feature_index = feature_index # 特征索引
self.threshold = threshold # 分割阈值
self.label = label # 叶节点类别
self.left = None # 左子节点
self.right = None # 右子节点
# 定义决策树训练函数
def train_decision_tree(data, feature_names):
labels = [sample[-1] for sample in data]
if labels.count(labels[0]) == len(labels): # 如果所有样本类别相同,则直接返回叶节点
return Node(label=labels[0])
if len(data[0]) == 1: # 如果已经遍历完所有特征,则返回叶节点,类别为出现次数最多的类别
majority_label = max(set(labels), key=labels.count)
return Node(label=majority_label)
best_feature_index = 0
best_information_gain = 0
for i in range(len(data[0]) - 1): # 遍历每个特征
feature_values = set([sample[i] for sample in data])
for value in feature_values: # 遍历每个特征值,计算信息增益
left_data = [sample for sample in data if sample[i] == value]
right_data = [sample for sample in data if sample[i] != value]
info_gain = calc_information_gain(data, left_data, right_data)
if info_gain > best_information_gain:
best_information_gain = info_gain
best_feature_index = i
best_feature_name = feature_names[best_feature_index]
node = Node(feature_index=best_feature_index)
node.left = train_decision_tree([sample for sample in data if sample[best_feature_index] == best_feature_name], feature_names)
node.right = train_decision_tree([sample for sample in data if sample[best_feature_index] != best_feature_name], feature_names)
return node
# 计算信息熵
def calc_entropy(data):
labels = [sample[-1] for sample in data]
label_counts = {}
for label in labels:
if label not in label_counts:
label_counts[label] = 0
label_counts[label] += 1
entropy = 0.0
for count in label_counts.values():
prob = count / len(data)
entropy -= prob * np.log2(prob)
return entropy
# 计算信息增益
def calc_information_gain(parent_data, left_data, right_data):
parent_entropy = calc_entropy(parent_data)
left_entropy = calc_entropy(left_data)
right_entropy = calc_entropy(right_data)
left_ratio = len(left_data) / len(parent_data)
right_ratio = len(right_data) / len(parent_data)
information_gain = parent_entropy - (left_ratio * left_entropy + right_ratio * right_entropy)
return information_gain
# 定义决策树预测函数
def predict(node, sample):
if node.label is not None:
return node.label
feature_value = sample[node.feature_index]
if feature_value == feature_names[node.feature_index]:
return predict(node.left, sample)
else:
return predict(node.right, sample)
# 构建决策树
decision_tree = train_decision_tree(training_data, feature_names)
# 预测新样本
new_sample = ['老年']
prediction = predict(decision_tree, new_sample)
print('预测结果:', prediction)
这段代码实现了一个简单的决策树,包括训练和预测两个部分。训练部分使用了信息熵和信息增益来选择最佳特征进行分割,然后递归地构建决策树。预测部分使用构建好的决策树对新样本进行分类预测。
6.随机森林
6.1基本思想
随机森林通过构建多个决策树,并采用随机抽样和特征采样的方法来实现集成决策,提高模型的准确性和鲁棒性,是一种强大的机器学习算法。
6.2基本步骤
- 随机抽样:从训练数据集中有放回地随机抽样,形成多个大小相等的采样集。对于每个采样集,可以使用不同的样本数目或相同的样本数目,这取决于训练数据集的规模和需要。
- 特征采样:对于每棵决策树的构建过程,从所有特征中随机选择一部分特征进行训练。这个特征子集的大小可以事先指定,也可以通过交叉验证等方法进行选择。
- 决策树的构建:对于每个采样集和特征子集,使用决策树算法(如ID3、CART等)构建一棵决策树。在决策树构建过程中,通过递归地选择最佳的划分特征和阈值,将数据集划分为更纯净的子集。
- 预测结果的集成:当需要对新样本进行预测时,将新样本输入到每棵决策树中,得到每棵树的预测结果。对于分类问题,可以通过投票或取概率平均的方式得到最终的预测结果。对于回归问题,可以取平均或加权平均的方式得到最终的预测结果。
6.3优缺点
- 优点:1.可以解决分类和回归问题 2.抗过拟合能力强 3.稳定性强。
- 缺点:1.模型复杂 2.计算成本高 3.计算时间长。
6.4案例-垃圾邮件过滤
6.4.1步骤:
- 数据收集:首先收集大量的垃圾邮件和正常邮件样本,并将它们转化为特征向量。这些特征可以包括词频、包含特定关键词的数量、邮件长度等。
- 数据预处理:对收集到的数据进行预处理,包括去除噪声、处理缺失值、进行特征选择等。
- 数据划分:将预处理后的数据集划分为训练集和测试集。通常,大部分数据用于训练模型,少部分用于评估模型性能。
- 随机森林参数设置:确定随机森林的参数,如决策树数量、特征子集大小等。可以使用交叉验证等方法进行调参,选择最佳的参数组合。
- 随机森林训练:使用训练集来构建随机森林模型。每棵决策树都会从训练集中进行自助采样和特征采样,然后通过决策树算法构建。
- 预测和评估:使用测试集对随机森林模型进行预测,并根据预测结果和真实标签计算分类准确率、精确率、召回率等指标来评估模型性能。
- 模型优化:根据评估结果可以进一步优化模型,调整参数或改变特征选择方法,以提高模型的性能。
- 模型应用:当模型达到满意的性能后,可以将其应用于实际的垃圾邮件过滤任务中。输入待判断的邮件内容,模型将输出预测的结果,判断是否为垃圾邮件。
6.4.2代码:
python
# 导入需要的库
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 假设已经准备好了垃圾邮件和正常邮件的数据集,分别存储在spam_data和ham_data中
# 将数据集合并为一个整体数据集,并创建对应的标签
data = spam_data + ham_data
labels = ['spam'] * len(spam_data) + ['ham'] * len(ham_data)
# 把文本数据转换为数值特征向量
vectorizer = CountVectorizer()
features = vectorizer.fit_transform(data)
# 数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=42)
# 构建随机森林模型
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
# 在训练集上训练模型
rf_classifier.fit(X_train, y_train)
# 在测试集上进行预测
predictions = rf_classifier.predict(X_test)
# 计算模型的准确率
accuracy = accuracy_score(y_test, predictions)
print("模型准确率:", accuracy)
这段代码首先导入了需要的库,包括RandomForestClassifier(随机森林分类器)、CountVectorizer(用于文本特征向量化)、train_test_split(数据集划分函数)和accuracy_score(用于计算准确率)。然后,将垃圾邮件和正常邮件数据集合并,并创建对应的标签。通过CountVectorizer将文本数据转换为数值特征向量。接着,使用train_test_split函数将数据集划分为训练集和测试集。然后构建一个随机森林模型,并在训练集上进行训练。最后,使用训练好的模型对测试集进行预测,并计算模型的准确率。
7.支持向量机
7.1基本思想
支持向量机(Support Vector Machine,SVM)是一种广泛应用于模式分类和回归分析的监督学习方法。其基本思想是找到一个最优的超平面来将不同类别的样本尽可能地分隔开。通过最大化间隔来找到一个稳定的决策边界,使得对新样本的预测能够更加准确。
7.2相关概念
- 最大化间隔:SVM试图找到一个最大间隔的超平面,将两个不同类别的样本分开。这个间隔被定义为从超平面到最近的样本点的距离,也称为"支持向量"。
- 特征空间映射:如果样本在原始特征空间中无法线性分隔,SVM可以通过使用"核函数"将样本映射到更高维的特征空间,使得样本可线性分隔。
- 决策边界:SVM通过在特征空间中找到一个决策边界来分类样本。对于二分类问题,决策边界就是超平面,将特征空间划分为两个区域。
- 支持向量:支持向量是离决策边界最近的那些样本点。这些样本点对于定义超平面并进行分类起关键作用。
- 正则化参数:SVM中的正则化参数C控制着对误分类样本的惩罚程度。较小的C值会产生更大的间隔,但可能会有更多的误分类,较大的C值会尽量减少误分类,但可能导致较小的间隔。
7.3分类步骤
- 数据预处理:收集并准备用于训练和测试的数据集。包括数据清洗、特征选择、特征缩放等。
- 特征向量化:将训练数据转换为特征向量表示,以便于SVM对其进行处理。可以使用各种特征提取方法,如词袋模型、TF-IDF等。
- 划分训练集和测试集:随机把训练集和测试集划分开。
- SVM模型训练:使用训练数据训练SVM分类器。训练过程中需要设置一些参数,例如SVM类型、核函数类型、正则化参数等。训练完毕后得到一个模型。
- 模型测试和评估:使用测试数据对训练好的SVM模型进行测试和评估。计算准确率、精确率、召回率等指标来评估分类器性能。
- 参数调优:如果模型效果不满意,可以通过交叉验证等方法调整SVM模型的参数,如正则化参数C值、核函数的参数等,以优化模型性能。
- 应用模型进行预测:使用训练好的分类器对未知样本进行预测。
7.4优缺点
- 优点:1.可以解决高维问题,即大型特征空间 2.能够处理非线性特征的相互作用 3.无需依赖整个数据。
- 缺点:1.当观测样本很多的时候,效率不是很高 2.对非线性问题没有通用的解决方案,很难找到一个合适的核函数 3.对缺失数据敏感。
7.5案例-手写数字识别
Dart
数据准备:我们将使用Scikit-Learn库中自带的手写数字数据集(load_digits())作为示例数据集。该数据集包含了一系列手写数字的图像数据和对应的标签。
数字图像特征化:每个手写数字图像在数据集中表示为一个8x8的矩阵,我们需要将其转换为一个用于训练模型的特征向量。可以将8x8矩阵展开为一个64维的向量,
每个元素表示一个像素的灰度值。
划分训练集和测试集:随机将数据集分为训练集和测试集,通常将大部分数据用于训练,少部分用于测试。
SVM模型训练:使用训练集进行支持向量机模型的训练。选择适当的SVM类型、核函数类型和正则化参数等。训练过程中,SVM会找到一个最优的决策边界以区分不同的手写数字。
模型测试和评估:使用测试集对训练好的SVM模型进行测试。通过计算准确率等指标来评估分类器的性能,了解其在未知数据上的表现。
参数调优:如果模型效果不理想,可以通过交叉验证等方法调整SVM模型的参数,如正则化参数C值或核函数的参数,以提高模型性能。
预测新样本:当模型训练完成且性能满意后,我们可以使用训练好的分类器对新的手写数字图像进行预测。
python
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载手写数字数据集
digits = datasets.load_digits()
X = digits.data # 特征向量
y = digits.target # 标签
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# SVM模型训练与预测
svm_classifier = SVC(kernel='rbf', C=1.0)
svm_classifier.fit(X_train, y_train)
y_pred = svm_classifier.predict(X_test)
# 模型评估
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy: ", accuracy)
上述代码中,我们使用Scikit-Learn库中自带的datasets.load_digits()函数加载手写数字数据集。然后,我们将数据集划分为训练集和测试集,并使用SVC类定义一个支持向量机分类器模型。在这个例子中,我们使用了高斯径向基核函数(radial basis function,'rbf')和C=1.0作为模型的参数。最后,我们使用测试集对模型进行评估,并输出准确率。
8.朴素贝叶斯
8.1基本思想
朴素贝叶斯是贝叶斯分类器中的一种模型,用已知类别的数据集训练模型,从而实现对未知类别数据的类别判断。其理论基础是贝叶斯决策论
8.2基本步骤
- 数据预处理:首先需要对数据进行清洗、归一化、特征选择等操作,确保数据的质量和适用性。同时还需要将数据集划分为训练集和测试集。
- 计算先验概率:在训练集上计算出每个类别的先验概率,即P(Ci),其中Ci表示第i个类别。
- 计算条件概率:对于每个类别,计算每个特征在给定类别下的条件概率,即P(Xj|Ci),其中Xj表示样本的第j个特征。
- 应用贝叶斯定理进行分类:通过计算后验概率来进行分类。对于给定的未知样本x,计算它属于每个类别Ci的后验概率P(Ci|x),然后选择具有最大后验概率的类别作为预测结果。
- 处理连续型特征:对于连续型特征,可以使用概率密度函数(PDF)对条件概率进行建模,如高斯分布、正态分布等。
- 处理离散型特征:对于离散型特征,可以使用频率计数来估计条件概率。
- 处理高维数据:由于涉及到多个特征,条件概率的计算可能会涉及到高维度的数据,为了避免维数灾难,可以采用特征选择、降维等技术来简化模型。
- 模型优化:通过调整参数或者采用其他优化方法来提高模型的准确性和泛化能力,如交叉验证、平滑算法等。
8.3优缺点
- 优点:1.朴素贝叶斯起源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率 2.对小规模的数据表现很好,能进行多分类 3.对缺失值不敏感,算法简单。
- 缺点:1.需要计算先验概率 2.对特征间强相关的模型分类效果不好。
8.4案例-电影分类
假设我们有一个电影分类问题,要将电影分为动作片、喜剧片和科幻片三类。
- 数据准备:我们收集了一批已经标注好的电影数据作为训练集。每部电影都有相应的特征,比如导演、演员、时长等,并且有对应的标签(动作片、喜剧片或科幻片)。
- 数据预处理:对于电影数据,可以对特征进行处理和转换,例如对导演和演员进行编码或者使用独热编码表示电影类型。
- 计算先验概率:在训练集中计算出每个类别的先验概率P(action)、P(comedy)和P(science fiction)。
- 计算条件概率:对于每个特征,计算它在给定电影类别下的条件概率,例如P(director|action)、P(actor|comedy)和P(duration|science fiction)。可以使用频率计数或者平滑算法(如拉普拉斯平滑)来估计条件概率。
- 应用贝叶斯定理进行分类:对于一部未知电影,计算它属于每个类别的后验概率P(action|movie)、P(comedy|movie)和P(science fiction|movie),选择具有最大后验概率的类别作为预测结果。
- 模型评估和优化:使用测试集对模型进行评估,计算准确率、召回率、F1值等指标来衡量分类器的性能。根据评估结果,可以调整模型参数或者采用其他优化方法来提高分类器的性能。
python
import numpy as np
class NaiveBayes:
def fit(self, X, y):
self.classes = np.unique(y)
self.num_classes = len(self.classes)
self.priors = np.zeros(self.num_classes)
self.conditional_probs = []
for i, c in enumerate(self.classes):
X_class = X[y == c]
self.priors[i] = len(X_class) / len(X)
conditional_prob = {}
for feature in X_class.T:
values, counts = np.unique(feature, return_counts=True)
prob = dict(zip(values, counts / len(feature)))
conditional_prob[feature.name] = prob
self.conditional_probs.append(conditional_prob)
def predict(self, X):
predictions = []
for sample in X:
probs = []
for i, c in enumerate(self.classes):
prior = np.log(self.priors[i])
posterior = 0
for feature_name, feature_value in zip(X.columns, sample):
if feature_value in self.conditional_probs[i][feature_name]:
conditional_prob = self.conditional_probs[i][feature_name][feature_value]
posterior += np.log(conditional_prob)
prob = prior + posterior
probs.append(prob)
pred_class_idx = np.argmax(probs)
pred_class = self.classes[pred_class_idx]
predictions.append(pred_class)
return np.array(predictions)
# 示例用法
# 假设我们有一个电影数据集,包含导演、演员和时长这三个特征,以及对应的标签类别(动作片、喜剧片、科幻片)
X = pd.DataFrame({'director': ['Director A', 'Director B', 'Director B', 'Director C', 'Director A'],
'actor': ['Actor A', 'Actor B', 'Actor A', 'Actor C', 'Actor C'],
'duration': [120, 90, 100, 110, 95]})
y = np.array(['action', 'comedy', 'comedy', 'science fiction', 'action'])
nb = NaiveBayes()
nb.fit(X, y)
# 预测新的电影类别
new_movie = pd.DataFrame({'director': ['Director A'], 'actor': ['Actor B'], 'duration': [105]})
predicted_class = nb.predict(new_movie)
print(predicted_class) # 输出:['action']
9.神经网络
9.1基本概念
神经网络(Neural Network)是一种模拟人脑神经元工作原理的数学模型。它由多个节点(神经元)和连接这些节点的权重组成,通过对输入数据的加权处理和非线性变换来实现复杂的计算和决策。
神经网络通常由输入层、隐藏层和输出层构成。每个层都由多个神经元组成,并且每个神经元都与前一层和后一层中的部分或全部神经元相连接。在神经网络中,每个神经元接收来自上一层神经元的输出,并将其加权求和后通过激活函数进行非线性变换,产生本层神经元的输出。这个输出又会传递给下一层神经元,依此类推,直到输出层产生最终的输出结果。
神经网络的训练过程是通过反向传播算法来实现的。该算法根据预测结果与真实标签之间的误差,通过调整网络中每个连接的权重来最小化误差。训练的目标是使得网络能够更好地泛化到未见过的数据,以便对未知数据进行准确的预测或分类。
神经网络可以应用于各种任务,包括图像识别、语音识别、自然语言处理、模式识别等。它具有很强的非线性拟合能力和适应性,并且在许多领域取得了出色的成果。随着深度学习的兴起,深度神经网络(Deep Neural Network)成为最主要的神经网络模型,其拥有更多的隐藏层和更复杂的结构,可以处理更高维度、更复杂的数据。
9.2基本步骤
- 数据准备:收集、清洗和预处理数据。这包括对输入数据进行特征提取、数据标准化和归一化等操作,以便于神经网络能够更好地处理和学习。
- 构建神经网络模型:选择合适的神经网络架构,并配置网络的层数、神经元数量、激活函数等参数。常见的神经网络模型包括全连接神经网络(FCN)、卷积神经网络(CNN)、循环神经网络(RNN)等。
- 定义损失函数:选择适当的损失函数来度量模型的预测输出与真实标签之间的差异。常见的损失函数包括均方误差(MSE)、交叉熵损失等。
- 配置优化器:选择合适的优化算法来调整神经网络中的权重和偏置,以最小化损失函数。常见的优化算法有梯度下降法、Adam、RMSprop等。
- 模型训练:使用标记数据集对神经网络模型进行训练。通过将输入数据传入网络,计算输出结果,并与真实标签进行比较,利用反向传播算法更新网络参数,不断优化模型。
- 模型评估:使用预留的测试数据集对训练后的模型进行评估,计算模型在新数据上的性能指标,如准确率、精确率、召回率等。
- 模型调优:根据评估结果,根据需要对模型进行调整和改进。可以尝试调整网络结构、参数初始化方式、正则化技术等方法来提高模型的性能。
- 模型应用:经过训练和调优后,将神经网络模型应用于实际场景中的新数据,进行预测或分类等任务。
9.3优缺点
- 优点:
- 适用于复杂的非线性问题:神经网络在处理非线性数据和解决非线性问题方面表现出色,可以通过多层隐藏层来捕捉数据中的复杂关系。
- 自动特征提取:神经网络能够通过训练过程自动学习到数据中的重要特征,不需要手动进行特征工程,简化了特征提取的过程。
- 并行计算:神经网络的计算过程可以并行化,在GPU等硬件上运行效率较高,能够处理大规模的数据和复杂的模型。
- 泛化能力强:经过合理训练后,神经网络对于未见过的数据能够具有较好的泛化能力,能够较好地处理噪声和不完整的数据。
- 缺点:
- 训练时间较长:由于神经网络中参数众多,并且需要反复进行迭代调整,所以其训练过程往往需要较长的时间,特别是在大规模数据和复杂模型的情况下。
- 需要大量的标记数据:神经网络通常需要大量的标记数据进行训练,而在一些领域中获取标记数据可能较为困难或耗时。
- 模型解释性差:由于神经网络的复杂性,其结果往往难以解释和理解。这使得神经网络在某些应用场景中的可接受性较低,比如医疗诊断等需要解释性的场景。
9.4案例-手写数字识别
手写数字识别是指将手写数字的图像输入神经网络模型,通过训练和学习,使得神经网络能够准确地识别输入的手写数字是0-9中的哪一个。
- 需要准备一个手写数字的数据集,例如MNIST数据集,它包含了大量的手写数字图像和对应的标签。
- 构建一个神经网络模型,可以使用深度学习框架(如TensorFlow、Keras、PyTorch)来构建。模型的输入层接收手写数字的图像,输出层为10个节点(0-9),表示数字的类别。
- 使用数据集对模型进行训练。训练过程中,我们将手写数字图像作为输入,与其对应的标签进行比较,计算损失函数(如交叉熵),然后使用反向传播算法调整模型的权重,以最小化损失函数。
- 在模型训练完成后,可以使用测试集对模型进行评估。将手写数字图像输入模型中,得到输出结果,与标签进行比较,计算准确率或其他评估指标,以评估模型的性能。
- 可以使用训练好的模型对新的手写数字进行预测。将手写数字的图像输入模型中,得到输出结果,即可判断输入的手写数字是0-9中的哪一个。
python
import tensorflow as tf
from tensorflow.keras.datasets import mnist
# 加载MNIST数据集
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 数据预处理
x_train = x_train / 255.0
x_test = x_test / 255.0
# 构建神经网络模型
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))
# 评估模型
loss, accuracy = model.evaluate(x_test, y_test)
print('Test loss:', loss)
print('Test accuracy:', accuracy)
# 使用模型进行预测
predictions = model.predict(x_test)
这段代码首先加载MNIST数据集,然后对数据进行预处理,将像素值归一化到0-1范围。接下来,通过Sequential顺序模型来构建神经网络模型。该模型包含一个Flatten层用于将图像展平为一维向量,一个Dense层作为隐藏层,并使用ReLU激活函数,最后一个Dense层作为输出层,使用softmax激活函数进行多分类。然后,使用compile方法编译模型,设置优化器、损失函数和评估指标。通过fit方法对模型进行训练,传入训练数据集和标签,并指定训练轮数。训练完成后,使用evaluate方法评估模型在测试数据集上的性能,得到损失值和准确率。最后,使用训练好的模型对测试数据集进行预测,得到预测结果。