算法基础入门-knn & kmeans

有监督算法 & 无监督算法

有监督学习和无监督学习是机器学习中的两种主要类型的学习算法,分别用于不同的任务。下面我通过具体的例子来生动地说明这两者的区别:

有监督学习

定义:有监督学习是一种机器学习方法,其中模型在训练阶段接收标注好的数据,即每个训练样本都有一个对应的标签。模型的目标是学会从输入数据中预测这些标签。

例子:假设你有一组动物的图片,每张图片都有一个标签,标签是“猫”或“狗”。你可以用这些图片来训练一个有监督学习模型。模型在训练时会看到图片和它们的标签,并且学习到什么样的特征可以区分猫和狗。例如,模型可能会学习到猫的耳朵通常是尖的,而狗的耳朵可能是圆的。训练完成后,你可以给模型一张新的图片,模型会根据它所学的特征来预测这张图片是猫还是狗。

应用:垃圾邮件过滤器、疾病预测(比如根据病人的症状预测是否患有某种疾病)、情感分析(根据文本内容预测情感倾向)。

无监督学习

定义:无监督学习是一种机器学习方法,其中模型在训练阶段接收的只是未标注的数据,即没有预先定义好的标签。模型的目标是从这些数据中发现潜在的结构或模式。

例子:假设你有一组不同类型的客户的购买记录,但你不知道他们的具体群体或类别。你可以使用无监督学习中的聚类算法(比如K-means算法)来对这些客户进行分组。模型会分析每个客户的购买行为,并将类似的客户归为同一类。通过这种方式,你可以发现潜在的客户群体,例如“高消费群体”、“中等消费群体”和“低消费群体”,这些群体是模型自动发现的,而不是事先定义好的。

应用:市场细分(发现不同的客户群体)、异常检测(识别数据中的异常点,比如信用卡欺诈检测)、主题建模(从文档中自动提取主题)。

这两种方法都非常强大,适用于不同的任务和数据类型。选择哪种方法通常取决于你是否有标签数据以及你的具体目标。

K-最近邻(K-Nearest Neighbors, KNN)算法是一种简单且直观的监督学习算法,广泛用于分类和回归任务。其基本思想是通过计算样本点之间的距离来进行分类或预测。

KNN算法

KNN 算法的基本步骤

  1. 选择参数 K:选择一个正整数 K,表示在做分类时考虑最近的 K 个邻居。

  2. 计算距离:对于待分类的样本,计算它与训练集中所有样本的距离。常用的距离度量包括欧氏距离、曼哈顿距离等。

  3. 选择最近邻居:找到距离待分类样本最近的 K 个邻居。

  4. 进行分类或预测

    • 分类:根据这 K 个邻居中出现频率最高的类别来确定待分类样本的类别。
    • 回归:计算这 K 个邻居的目标值的平均值(或加权平均值),作为待预测样本的目标值。

示例

问题:假设你正在开发一个基于花瓣和花萼长度来分类鸢尾花(Iris)品种的系统。你有一个包含鸢尾花数据集的训练集,每个样本包括花瓣长度、花瓣宽度、花萼长度和花萼宽度,还有对应的花品种标签(如 Setosa, Versicolor, Virginica)。

步骤

  1. 选择参数 K:假设我们选择 K = 3,即在分类时考虑最近的 3 个邻居。

  2. 计算距离:对于每个待分类的鸢尾花样本,计算它与训练集中所有样本的距离。例如,可以使用欧氏距离来计算。

  3. 选择最近邻居:假设我们有一个待分类的鸢尾花样本(花瓣长度为 4.5 cm,花瓣宽度为 1.5 cm)。我们计算它与训练集中所有样本的距离,并找到最近的 3 个邻居。

  4. 进行分类

    • 假设最近的 3 个邻居分别属于 Setosa、Versicolor 和 Setosa。
    • 由于 Setosa 出现了 2 次,Versicolor 出现了 1 次,最终根据 KNN 算法,待分类的样本将被分类为 Setosa。

优点和缺点

优点

  • 简单直观,易于理解和实现。
  • 不需要模型训练,因为它是一个懒惰学习算法(即所有计算都在预测时完成)。

缺点

  • 计算复杂度高,对于大数据集,预测时间可能很长。
  • 对噪声敏感,尤其是在特征空间中有大量噪声时。
  • 选择合适的 K 值可能需要经验或交叉验证。 

KNN 是一种非常直观且有效的算法,尤其适用于中小规模的数据集和需要解释的场景。

伪代码

以下是 K-最近邻(KNN)算法的伪代码实现,适用于分类任务。伪代码包括了 KNN 的主要步骤:选择 K 值、计算距离、选择最近邻居和进行分类。

function KNN(training_data, test_point, K):
    # training_data 是一个包含训练样本的集合,每个样本包含特征和标签
    # test_point 是需要分类的测试样本
    # K 是选择的邻居数量

    # 1. 计算所有训练样本到测试样本的距离
    distances = []
    for each sample in training_data:
        distance = calculate_distance(sample.features, test_point.features)
        distances.append((distance, sample.label))

    # 2. 根据距离对训练样本进行排序
    sorted_distances = sort_by_distance(distances)

    # 3. 选择距离最近的 K 个样本
    nearest_neighbors = select_first_K(sorted_distances, K)

    # 4. 统计 K 个邻居中每个类别的出现次数
    class_count = {}
    for each neighbor in nearest_neighbors:
        label = neighbor.label
        if label not in class_count:
            class_count[label] = 0
        class_count[label] += 1

    # 5. 根据出现次数最多的类别确定测试样本的类别
    predicted_label = find_most_frequent_class(class_count)

    return predicted_label

# 辅助函数
function calculate_distance(features1, features2):
    # 计算两个特征向量之间的欧氏距离
    sum_squared = 0
    for i = 0 to length(features1) - 1:
        sum_squared += (features1[i] - features2[i])^2
    return sqrt(sum_squared)

function sort_by_distance(distances):
    # 对距离进行排序
    return sort(distances, by_distance)

function select_first_K(sorted_distances, K):
    # 选择前 K 个最近的样本
    return sorted_distances[0:K]

function find_most_frequent_class(class_count):
    # 找到出现次数最多的类别
    max_count = -1
    most_frequent_class = None
    for each class_label, count in class_count:
        if count > max_count:
            max_count = count
            most_frequent_class = class_label
    return most_frequent_class

KMeans算法

K-means 算法是一种常见的无监督学习算法,主要用于数据聚类任务。其目标是将数据集分成 K 个簇(cluster),使得每个簇中的数据点尽可能地相似,而不同簇之间的数据点尽可能地不同。K-means 算法基于数据点的特征,自动地将数据分组。

K-means 算法的基本步骤

  1. 选择 K 值:选择要分成的簇的数量 K。

  2. 初始化簇中心:随机选择 K 个数据点作为初始簇中心(centroids)。

  3. 分配簇

    • 将每个数据点分配到距离最近的簇中心。
    • 这个步骤基于某种距离度量(通常是欧氏距离)来确定。
  4. 更新簇中心

    • 对于每个簇,计算该簇内所有数据点的均值,并将该均值作为新的簇中心。
  5. 重复步骤 3 和 4

    • 继续分配簇和更新簇中心,直到簇中心不再变化或变化非常小(收敛)。

示例

问题:假设你有一组关于学生的考试成绩数据,包括数学和英语两个科目的分数。你希望将这些学生分成 K 个簇,以发现不同的学习群体。

步骤

  1. 选择 K 值:假设我们选择 K = 3,即将学生分成 3 个群体。

  2. 初始化簇中心

    • 随机选择 3 个学生的数学和英语分数作为初始簇中心。例如,初始簇中心可能是 (80, 70), (60, 50), 和 (90, 85)。
  3. 分配簇

    • 对于每个学生,根据其数学和英语分数计算与每个簇中心的距离,并将学生分配到距离最近的簇中心。例如,一个学生的分数是 (75, 65),他可能会被分配到与簇中心 (80, 70) 距离最近的簇。
  4. 更新簇中心

    • 计算每个簇内学生数学和英语分数的均值,并将这些均值作为新的簇中心。例如,如果簇 1 包含学生 (70, 60), (80, 70), 和 (75, 65),则簇 1 的新簇中心将是这三个点的均值。
  5. 重复步骤 3 和 4

    • 根据新的簇中心重新分配学生,更新簇中心,并重复直到簇中心稳定。

优点和缺点

优点

  • 算法简单,易于理解和实现。
  • 对大数据集效果良好,计算速度较快。

缺点

  • 需要预先指定 K 值,选择不合适的 K 值可能影响聚类效果。
  • 对初始簇中心选择敏感,可能会导致局部最优解。
  • 对离群点和噪声敏感。

K-means 是一种非常流行且实用的聚类算法,尤其适用于数据集中簇的数量已知或容易确定的情况。

伪代码

以下是 K-means 算法的伪代码实现,适用于数据聚类任务。伪代码包括了 K-means 的主要步骤:初始化簇中心、分配簇、更新簇中心和迭代直到收敛。

function KMeans(data, K, max_iterations):
    # data 是待聚类的数据集
    # K 是选择的簇的数量
    # max_iterations 是最大迭代次数

    # 1. 随机初始化 K 个簇中心
    centroids = initialize_centroids(data, K)
    
    for iteration = 1 to max_iterations:
        # 2. 分配每个数据点到最近的簇中心
        clusters = assign_clusters(data, centroids)
        
        # 3. 更新簇中心
        new_centroids = update_centroids(data, clusters, K)
        
        # 4. 检查收敛条件(簇中心是否变化)
        if centroids_equal(new_centroids, centroids):
            break
        
        centroids = new_centroids
    
    return clusters, centroids

# 辅助函数
function initialize_centroids(data, K):
    # 从数据集中随机选择 K 个样本作为初始簇中心
    return random_samples(data, K)

function assign_clusters(data, centroids):
    # 为每个数据点分配到最近的簇中心
    clusters = []
    for each point in data:
        distances = [calculate_distance(point, centroid) for each centroid in centroids]
        nearest_centroid_index = find_index_of_min(distances)
        clusters.append(nearest_centroid_index)
    return clusters

function update_centroids(data, clusters, K):
    # 根据每个簇中的数据点计算新的簇中心
    new_centroids = []
    for k = 0 to K-1:
        points_in_cluster = [data[i] for i = 0 to length(data)-1 if clusters[i] == k]
        new_centroid = calculate_mean(points_in_cluster)
        new_centroids.append(new_centroid)
    return new_centroids

function calculate_distance(point1, point2):
    # 计算两个点之间的欧氏距离
    sum_squared = 0
    for i = 0 to length(point1) - 1:
        sum_squared += (point1[i] - point2[i])^2
    return sqrt(sum_squared)

function centroids_equal(centroids1, centroids2):
    # 判断两个簇中心是否相等(收敛条件)
    for i = 0 to length(centroids1) - 1:
        if calculate_distance(centroids1[i], centroids2[i]) > tolerance:
            return false
    return true

function calculate_mean(points):
    # 计算点集的均值
    num_points = length(points)
    dimensions = length(points[0])
    mean = [0] * dimensions
    for each point in points:
        for d = 0 to dimensions - 1:
            mean[d] += point[d]
    for d = 0 to dimensions - 1:
        mean[d] /= num_points
    return mean

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值