小小总结一下 KNN、K-means 和 SVM 及其 Python 实现
好久没更新了,最近准备秋招,在机器学习中感觉经常被问的几个算法:K近邻算法(K-Nearest Neighbors, KNN)、K均值聚类算法(K-means)以及支持向量机(Support Vector Machine, SVM)。给自己做个总结笔记,并贴出来,如果有误欢迎指出。
1. K近邻算法 (KNN)
什么是 KNN?
K近邻算法是一种监督学习算法,常用于分类和回归问题。它的核心思想是:给定一个新样本,找出在特征空间中距离它最近的K个已知样本,然后基于这些邻居的信息进行分类或预测。
工作原理:
- 选择参数K(即最近邻居的数量)。
- 计算新样本与训练数据集中所有样本的距离(通常使用欧几里得距离)。
- 选择距离最近的K个样本。
- 根据这K个邻居的类别,进行投票以决定新样本的类别(在分类问题中)。
KNN的优缺点:
- 优点:简单易理解,适合小数据集,直观。
- 缺点:随着数据量的增加,计算量也增加;对特征的尺度和噪声敏感。
Python实现KNN
import numpy as np
from collections import Counter
# KNN算法实现
class KNN:
def __init__(self, k=3):
self.k = k
def fit(self, X_train, y_train):
self.X_train = X_train
self.y_train = y_train
def predict(self, X_test):
predictions = [self._predict(x) for x in X_test]
return np.array(predictions)
def _predict(self, x):
# 计算欧几里得距离
distances = [np.sqrt(np.sum((x - x_train)**2)) for x_train in self.X_train]
# 选择K个最近邻
k_indices = np.argsort(distances)[:self.k]
k_nearest_labels = [self.y_train[i] for i in k_indices]
# 进行投票
most_common = Counter(k_nearest_labels).most_common(1)
return most_common[0][0]
# 示例数据
X_train = np.array([[1, 2], [2, 3], [3, 4], [6, 7], [7, 8]])
y_train = np.array([0, 0, 0, 1, 1])
X_test = np.array([[2, 3], [5, 6]])
# KNN实例化并预测
knn = KNN(k=3)
knn.fit(X_train, y_train)
predictions = knn.predict(X_test)
print(predictions)
2. K均值算法 (K-means)
什么是 K-means?
K-means是一种无监督学习算法,常用于聚类问题。它通过将数据集划分为K个簇,使得同一簇中的数据点彼此之间更加相似,而与其他簇的数据点差异更大。
工作原理:
- 选择K个初始质心(可以随机选取数据点作为质心)。
- 将每个数据点分配给最近的质心,形成K个簇。
- 计算每个簇的质心。
- 重复步骤2和3,直到质心不再改变(或变化微小)。
K-means的优缺点:
- 优点:简单快速,适合大数据集。
- 缺点:对初始质心选择敏感,可能陷入局部最优,K值需要人为设定。
Python实现K-means
from sklearn.cluster import KMeans
import numpy as np
# 示例数据
X = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])
# K-means聚类
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
# 输出结果
print("簇的质心:", kmeans.cluster_centers_)
print("簇的分配:", kmeans.labels_)
##############################################################
# 以上是调包的代码,具体实现如下
##############################################################
import numpy as np
class KMeans:
def __init__(self, k=2, max_iters=100):
self.k = k # 簇的数量
self.max_iters = max_iters # 最大迭代次数
self.centroids = None # 质心
# 计算欧几里得距离
def _euclidean_distance(self, a, b):
return np.sqrt(np.sum((a - b) ** 2))
# 随机初始化质心
def _initialize_centroids(self, X):
np.random.seed(42)
indices = np.random.choice(X.shape[0], self.k, replace=False)
return X[indices]
# 更新每个簇的质心为该簇所有点的均值
def _compute_centroids(self, clusters, X):
centroids = np.zeros((self.k, X.shape[1]))
for idx, cluster in enumerate(clusters):
centroids[idx] = np.mean(X[cluster], axis=0)
return centroids
# 将每个数据点分配给最近的质心
def _assign_clusters(self, X, centroids):
clusters = [[] for _ in range(self.k)]
for idx, point in enumerate(X):
distances = [self._euclidean_distance(point, centroid) for centroid in centroids]
nearest_centroid_idx = np.argmin(distances)
clusters[nearest_centroid_idx].append(idx)
return clusters
# 拟合K-means模型
def fit(self, X):
self.centroids = self._initialize_centroids(X)
for _ in range(self.max_iters):
clusters = self._assign_clusters(X, self.centroids)
previous_centroids = self.centroids
self.centroids = self._compute_centroids(clusters, X)
# 如果质心没有变化,提前终止
if np.all(previous_centroids == self.centroids):
break
# 预测每个点所属的簇
def predict(self, X):
return [np.argmin([self._euclidean_distance(x, centroid) for centroid in self.centroids]) for x in X]
# 示例数据
X = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])
# K-means实例化并训练
kmeans = KMeans(k=2)
kmeans.fit(X)
# 输出结果
print("质心:", kmeans.centroids)
predictions = kmeans.predict(X)
print("簇的分配:", predictions)
3. 支持向量机 (SVM)
什么是 SVM?
SVM是一种强大的监督学习算法,常用于分类问题。它的目标是找到一个最优的超平面,能够最大化区分不同类别的数据点。SVM不仅仅适用于线性可分问题,还可以通过引入核函数来处理非线性问题。
工作原理:
- 对于线性分类问题,SVM找到一个最大化分类间距的超平面。
- 对于非线性分类问题,SVM通过将数据映射到高维空间,使得数据在高维空间中线性可分。
- 核函数是SVM的核心之一,常见的核函数有线性核、RBF核等。
SVM的优缺点:
- 优点:对高维数据效果好,能够处理非线性数据。
- 缺点:对数据量较大的情况下计算开销较高,难以解释。
Python实现SVM
from sklearn import svm
import numpy as np
# 示例数据
X = np.array([[1, 2], [2, 3], [3, 4], [6, 7], [7, 8]])
y = np.array([0, 0, 0, 1, 1])
# SVM分类器
clf = svm.SVC(kernel='linear')
clf.fit(X, y)
# 测试数据预测
X_test = np.array([[2, 3], [5, 6]])
predictions = clf.predict(X_test)
print("SVM预测结果:", predictions)
##############################################################
# 以上是调包的代码,具体实现如下
##############################################################
import numpy as np
class SVM:
def __init__(self, learning_rate=0.001, lambda_param=0.01, n_iters=1000):
self.lr = learning_rate
self.lambda_param = lambda_param # 正则化参数
self.n_iters = n_iters
self.w = None # 权重
self.b = None # 偏差
# 拟合SVM模型
def fit(self, X, y):
n_samples, n_features = X.shape
y_ = np.where(y <= 0, -1, 1) # 将标签转化为-1和1
# 初始化权重和偏差
self.w = np.zeros(n_features)
self.b = 0
# 梯度下降
for _ in range(self.n_iters):
for idx, x_i in enumerate(X):
condition = y_[idx] * (np.dot(x_i, self.w) - self.b) >= 1
if condition:
# 如果分类正确,只需要最小化权重的正则项
self.w -= self.lr * (2 * self.lambda_param * self.w)
else:
# 如果分类错误,更新权重和偏差
self.w -= self.lr * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx]))
self.b -= self.lr * y_[idx]
# 预测数据类别
def predict(self, X):
linear_output = np.dot(X, self.w) - self.b
return np.sign(linear_output)
# 示例数据
X = np.array([[1, 2], [2, 3], [3, 4], [6, 7], [7, 8]])
y = np.array([0, 0, 0, 1, 1]) # 标签:0变为-1,1保持不变
# SVM实例化并训练
svm = SVM()
svm.fit(X, y)
# 预测测试数据
X_test = np.array([[2, 3], [5, 6]])
predictions = svm.predict(X_test)
print("SVM预测结果:", predictions)
总结
- KNN 是一种基于距离的简单分类方法,适合小规模数据集。
- K-means 是一种聚类算法,能够将数据集分割成多个簇。
- SVM 是一种强大的分类算法,适用于线性和非线性问题。