基于weka手工实现K-means

这篇具有很好参考价值的文章主要介绍了基于weka手工实现K-means。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、K-means聚类算法

K均值聚类(K-means clustering)是一种常见的无监督学习算法,用于将数据集中的样本划分为K个不同的类别或簇。它通过最小化样本点与所属簇中心点之间的距离来确定最佳的簇划分。

K均值聚类的基本思想如下:

  1. 随机选择K个初始聚类中心(质心)。
  2. 对于每个样本,计算其与各个聚类中心之间的距离,并将样本分配到距离最近的聚类中心所代表的簇。
  3. 对于每个簇,计算簇中样本的均值,并将该均值作为新的聚类中心。
  4. 重复步骤2和步骤3,直到聚类中心不再变化或达到预定的迭代次数。

K均值聚类的关键是如何选择初始的聚类中心。常见的方法是随机选择数据集中的K个样本作为初始聚类中心,或者使用一些启发式的方法来选择。

K均值聚类的优点包括简单易实现、计算效率高和可扩展性好。它在许多领域中被广泛应用,如数据分析、图像处理、模式识别等。然而,K均值聚类也存在一些限制,例如对于初始聚类中心的敏感性、对于离群值的影响较大以及需要事先指定簇的个数K等。

在实际应用中,可以根据实际问题和数据集的特点来选择合适的K值,并进行多次运行以获得更稳定的结果。此外,K均值聚类也可以与其他算法相结合,如层次聚类(hierarchical clustering)和密度聚类(density-based clustering),以获得更好的聚类效果。

总的来说,K均值聚类是一种常用的无监督学习算法,用于将数据集中的样本划分为K个簇。它简单而高效,适用于许多聚类问题。然而,在使用K均值聚类时需要注意选择初始聚类中心和合适的K值,以及对其限制和局限性的认识。文章来源地址https://www.toymoban.com/news/detail-646603.html

二、基于weka手工实现K-means聚类算法

package weka.clusterers.myf;

import weka.clusterers.RandomizableClusterer;
import weka.core.*;

import java.util.*;

/**
 * @author YFMan
 * @Description 自定义的 KMeans 聚类器
 * @Date 2023/6/8 15:01
 */
public class myKMeans extends RandomizableClusterer {
    // 聚类中心的数量
    private int m_NumClusters = 2;

    // 不同聚类中心的集合
    private Instances m_ClusterCentroids;

    // 聚类的最大迭代次数
    private int m_MaxIterations = 500;

    // 追踪收敛前完成的迭代次数
    private int m_Iterations = 0;

    // 构造函数
    public myKMeans() {
        super();
        // 设置随机种子
        m_SeedDefault = 10;
        setSeed(m_SeedDefault);
    }


    /*
     * @Author YFMan
     * @Description //基类定义的接口,必须要实现
     * @Date 2023/6/8 16:37
     * @Param []
     * @return weka.core.Capabilities
     **/
    @Override
    public Capabilities getCapabilities() {
        Capabilities result = super.getCapabilities();
        result.disableAll();
        result.enable(Capabilities.Capability.NO_CLASS);

        // attributes
        result.enable(Capabilities.Capability.NOMINAL_ATTRIBUTES);
        result.enable(Capabilities.Capability.NUMERIC_ATTRIBUTES);
        result.enable(Capabilities.Capability.MISSING_VALUES);

        return result;
    }

    /*
     * @Author YFMan
     * @Description //进行聚类
     * @Date 2023/6/8 16:38
     * @Param [data 用于聚类的数据集]
     * @return void
     **/
    @Override
    public void buildClusterer(Instances instances) throws Exception {
        // 迭代次数
        m_Iterations = 0;

        // 初始化聚类中心
        m_ClusterCentroids = new Instances(instances, m_NumClusters);

        // 每个样本属于哪个聚类中心
        int[] clusterAssignments = new int[instances.numInstances()];

        // 伪随机数生成器
        Random RandomO = new Random(getSeed());
        int instIndex;
        HashSet<Instance> initC = new HashSet<>();

        // 初始化聚类中心,随机选择 m_NumClusters 个样本作为聚类中心
        for (int j = instances.numInstances() - 1; j >= 0; j--) {
            instIndex = RandomO.nextInt(j + 1);

            if (!initC.contains(instances.instance(instIndex))) {
                m_ClusterCentroids.add(instances.instance(instIndex));
                initC.add(instances.instance(instIndex));
            }
            instances.swap(j, instIndex);

            if (m_ClusterCentroids.numInstances() == m_NumClusters) {
                break;
            }
        }

        boolean converged = false;
        // 用于存储每个聚类中心的样本集合
        Instances[] tempI = new Instances[m_NumClusters];
        while (!converged) {
            m_Iterations++;
            converged = true;
            // 计算每个样本 属于哪个聚类中心
            for (int i = 0; i < instances.numInstances(); i++) {
                Instance toCluster = instances.instance(i);
                int newC = clusterInstance(toCluster);
                // 如果样本所属的聚类中心发生变化,则说明还没有收敛
                if (newC != clusterAssignments[i]) {
                    converged = false;
                }
                clusterAssignments[i] = newC;
            }

            // 重新计算聚类中心
            m_ClusterCentroids = new Instances(instances, m_NumClusters);
            for (int i = 0; i < m_NumClusters; i++) {
                tempI[i] = new Instances(instances, 0);
            }
            for (int i = 0; i < instances.numInstances(); i++) {
                tempI[clusterAssignments[i]].add(instances.instance(i));
            }
            // 重新计算聚类中心
            for (int i = 0; i < m_NumClusters; i++) {
                // 计算每个属性的平均值
                m_ClusterCentroids.add(calculateCentroid(tempI[i]));
            }
            // 如果迭代次数达到最大值,则强制结束
            if (m_Iterations == m_MaxIterations) {
                converged = true;
            }
        }
    }

    /*
     * @Author YFMan
     * @Description //计算某个聚类中心的中心点
     * @Date 2023/6/8 16:57
     * @Param [instances 聚类中心的样本集合]
     * @return weka.core.Instance 聚类中心的中心点
     **/
    private Instance calculateCentroid(Instances instances) {

        int numInst = instances.numInstances();
        int numAttr = instances.numAttributes();

        Instance centroid = new Instance(numAttr);

        double sum;

        for (int i = 0; i < numAttr; i++) {
            sum = 0;
            for (int j = 0; j < numInst; j++) {
                sum += instances.instance(j).value(i);
            }
            centroid.setValue(i, sum / numInst);
        }

        return centroid;
    }

    /*
     * @Author YFMan
     * @Description //计算两个属性全为数值类型的样本之间的距离(欧式距离)
     * @Date 2023/6/8 16:47
     * @Param [first 第一个样例, second 第二个样例]
     * @return double
     **/
    private double distance(Instance first, Instance second) {
        // 定义欧式距离
        double euclideanDistance = 0;
        // 定义overlapping距离
        double overlappingDistance = 0;

        for (int index = 0; index < first.numAttributes(); index++) {
            if (index == first.classIndex()) {
                continue;
            }
            // 如果是数值类型的属性,则计算欧式距离
            if (first.attribute(index).isNumeric()) {
                double dis = first.value(index) - second.value(index);
                euclideanDistance += dis * dis;
            } else {
                // 如果是标称类型的属性,则计算是否相等
                if (first.value(index) != second.value(index)) {
                    overlappingDistance += 1;
                }
            }
        }

        return Math.sqrt(euclideanDistance) + overlappingDistance;
    }

    /*
     * @Author YFMan
     * @Description //对一个给定的样例进行分类
     * @Date 2023/6/8 16:50
     * @Param [instance 给定的样例]
     * @return int 返回样例所属的聚类中心id
     **/
    @Override
    public int clusterInstance(Instance instance) throws Exception {
        double minDist = Double.MAX_VALUE;
        int bestCluster = 0;
        for (int i = 0; i < m_NumClusters; i++) {
            double dist = distance(instance, m_ClusterCentroids.instance(i));
            if (dist < minDist) {
                minDist = dist;
                bestCluster = i;
            }
        }
        return bestCluster;
    }

    /*
     * @Author YFMan
     * @Description //返回聚类中心的数量
     * @Date 2023/6/8 16:34
     * @Param []
     * @return int
     **/
    @Override
    public int numberOfClusters() throws Exception {
        return m_NumClusters;
    }

    /*
     * @Author YFMan
     * @Description //主函数
     * @Date 2023/6/8 16:33
     * @Param [argv 命令行参数]
     * @return void
     **/
    public static void main(String[] argv) {
        runClusterer(new myKMeans(), argv);
    }
}

到了这里,关于基于weka手工实现K-means的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于weka平台手工实现朴素贝叶斯分类

    B事件发生后,A事件发生的概率可以如下表示: p ( A ∣ B ) = p ( A ∩ B ) P ( B ) (1) p(A|B)=frac{p(Acap B)}{P(B)}tag{1} p ( A ∣ B ) = P ( B ) p ( A ∩ B ) ​ ( 1 ) A事件发生后,B事件发生的概率可以如下表示: p ( B ∣ A ) = p ( A ∩ B ) P ( A ) (2) p(B|A)=frac{p(Acap B)}{P(A)}tag{2} p ( B ∣ A ) = P ( A ) p

    2024年02月13日
    浏览(46)
  • 基于weka手工实现多层感知机(BPNet)

    单层感知机,就是只有一层神经元,它的模型结构如下 1 : 对于权重 w w w 的更新,我们采用如下公式: w i = w i + Δ w i Δ w i = η ( y − y ^ ) x i (1) w_i=w_i+Delta w_i \\\\ Delta w_i=eta(y-hat{y})x_itag{1} w i ​ = w i ​ + Δ w i ​ Δ w i ​ = η ( y − y ^ ​ ) x i ​ ( 1 ) 其中, y y y 为标签, y

    2024年02月17日
    浏览(50)
  • 机器学习(八) — K-means

    1 definition randomly initialize K cluster centroids μ 1 , μ 2 , ⋯ mu_1, mu_2, cdots μ 1 ​ , μ 2 ​ , ⋯ repeat: assign each point to its closest centroid μ mu μ recompute the centroids(average of the closest point) 2 optimazation objective c ( i ) c^{(i)} c ( i ) = index of cluster to which example x ( i ) x^{(i)} x ( i ) is currently assign

    2024年01月21日
    浏览(48)
  • 基于weka手工实现ID3决策树

    相比于logistic回归、BP网络、支持向量机等基于超平面的方法,决策树更像一种算法,里面的数学原理并不是很多,较好理解。 决策树就是一个不断地属性选择、属性划分地过程,直到满足某一情况就停止划分。 当前样本全部属于同一类别了(信息增益为0); 已经是空叶子

    2024年02月14日
    浏览(46)
  • 头歌(educoder)机器学习 --- k-means

    2024年02月06日
    浏览(49)
  • 【机器学习】十大算法之一 “K-means”

      作者主页: 爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主 爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域. https://blog.csdn.net/Code_and516?type=blog 个人简介:打工人。 持续分

    2024年02月10日
    浏览(45)
  • 基于weka手工实现逻辑斯谛回归(Logistic回归)

    逻辑斯谛回归模型其实是一种分类模型,这里实现的是参考李航的《统计机器学习》以及周志华的《机器学习》两本教材来整理实现的。 假定我们的输入为 x x x , x x x 可以是多个维度的,我们想要根据 x x x 去预测 y y y , y ∈ { 0 , 1 } yin {0,1} y ∈ { 0 , 1 } 。逻辑斯谛的模型

    2024年02月15日
    浏览(45)
  • 基于weka平台手工实现(LinearRegression | Ridge Regression,岭回归)

    线性回归主要采用最小二乘法来实现,主要思想如下: X = ( x 11 x 12 ⋯ x 1 d 1 x 21 x 22 ⋯ 5 1 ⋮ ⋮ ⋱ ⋮ ⋮ x m 1 x m 2 ⋯ x m d 1 ) X=left( begin{matrix} x_{11} x_{12} cdots x_{1d} 1 \\\\ x_{21} x_{22} cdots 5 1 \\\\ vdots vdots ddots vdots vdots \\\\ x_{m1} x_{m2} cdots x_{md} 1 \\\\ end{matrix} right) X = ​ x 11 ​ x

    2024年02月12日
    浏览(46)
  • 机器学习第十一课--K-Means聚类

    K-Means算法是最经典的聚类算法,几乎所有的聚类分析场景,你都可以使用K-Means,而且在营销场景上,它就是\\\"King\\\",所以不管从事数据分析师甚至是AI工程师,不知道K-Means是”不可原谅“的一件事情。在面试中,面试官也经常问关于K-Means的问题。虽然算法简单,但也有一些需

    2024年02月07日
    浏览(37)
  • 机器学习——K-Means算法优化(一)代价函数

    在K-Means算法中,对K个质心的选择,容易陷入局部最小值,从而每次聚类得到不同的结果。 使用多次的随机初始化,并计算每一次建模得到的代价函数值,选取最小的代价函数值作为聚类结果,代价函数公式如下 J ( c ( 1 ) , … , c ( m ) , μ 1 , … , μ K ) = 1 m ∑ i = 1 m ∣ ∣ x (

    2024年02月02日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包