QT+VS实现Kmeans++

1、Kmeans++的原理如下:

(1)首先选取样本中任一数据点作为第一个聚类中心;

(2)计算样本每一个数据点至现所有聚类中心的最近距离,并记录下来;

(3)逐一挑选所有数据点最近距离之中的最大值,即最远距离,最大值对应的数据点为待求聚类中心;

(4)剔除已选为聚类中心的样本点,重新计算(2)、(3)步骤,得到指定的最终的聚类中心点数。

2、实现结果如下:

 

 

注:当噪点太多时,初始K个聚类中心的计算会出现偏差,从而导致整个聚类结果出现偏差。

3、原始数据读入格式如下:

点号-X坐标-Y坐标(非此格式的数据无法正常读入,程序会报错)

4、根据Kmeans++选择k个初始聚类中心的Kmeans聚类算法整体代码如下:

//Kmeans.cpp文件
#include "Kmeans.h"Kmeans::Kmeans(QWidget *parent): QWidget(parent)
{start = false;//dd = blank;dd = to2K;ui.setupUi(this);connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(onBtReadData()));connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(onBtCalKmeans()));connect(ui.pushButton_3, SIGNAL(clicked()), this, SLOT(onBtReadK()));
}void Kmeans::onBtReadData()
{K = ui.lineEdit->text().toInt();p.clear();//打开文件对话框QString fileName = QFileDialog::getOpenFileName(this, tr("打开"));QFile file(fileName);bool isOpen = 1;if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){isOpen = 0;QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));}//逐行读取文本文件QTextStream stream(&file);while (!stream.atEnd()){Pointp pt;QString str = stream.readLine();QStringList list = str.split(",");pt.no = list.at(0);pt.x = list.at(1).toDouble();pt.y = list.at(2).toDouble();p.push_back(pt);}file.close();//判断是否读取完毕if (stream.atEnd()&&isOpen){QMessageBox box;box.setText("数据读取完毕");box.exec();}
}void Kmeans::onBtReadK()
{QString fileName = QFileDialog::getOpenFileName(this, tr("打开"));QFile file(fileName);bool isOpen = 1;if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){isOpen = 0;QMessageBox::StandardButton btnValue = QMessageBox::information(this, tr("提示"), tr("打开失败!"));}QTextStream stream(&file);while (!stream.atEnd()){QString str = stream.readLine();QStringList list = str.split(",");Pointp k1;k1.no = list.at(0);k1.x = list.at(1).toDouble();k1.y = list.at(2).toDouble();k.push_back(k1);}//判断是否读取完毕if (stream.atEnd() && isOpen){QMessageBox box;box.setText("数据读取完毕");box.exec();}dd = readK;
}void Kmeans::toK()
{//随机选取k个初始聚类中心for (int i = 0; i < K; i++){Pointp k1;k1.no = i + 1;k1.x = p.at(i).x;k1.y = p.at(i).y;k.push_back(k1);}
}int Kmeans::onBtCalKmeans()
{K = ui.lineEdit->text().toInt();if (S.size()&&p.size()==S.size()){QMessageBox box;box.setText("已经计算完成");box.exec();return 0;}//if (dd == to2K)//{//    toK();//}CalK();CalDis();//SCalcentroid();//用到S,得dis//CKmeans();//用到dis,得new k.int iCount = 0;while (iCount < K){if (dis.size()){for (int i = 0; i < k.size(); i++){for (int j = 0; j < dis.size(); j++){if (k.at(i).no == dis.at(j).noK){//qDebug() <<"k:" <<k.at(i).no<< k.at(i).x << k.at(i).y;//qDebug() <<"dis:" <<dis.at(i).noK.toInt()<< dis.at(j).sx << dis.at(j).sy<<endl;double detaX = k.at(i).x - dis.at(j).sx;double detaY = k.at(i).y - dis.at(j).sy;double sk = sqrt(detaX * detaX + detaY * detaY);//qDebug() << sk;if (sk == 0){iCount++;}else{CKmeans();}}}}}dis.clear();S.clear();CalDis();Calcentroid();}start = true;qDebug() << "S" << S.size();drawPoint();//drawK();QMessageBox box;box.setText("计算完成");box.exec();qDebug() << "k" << k.size();//for (int i = 0; i < S.size(); i++)//{//    qDebug() << "S:" <<S.at(i).no<< S.at(i).noK;//}return 1;
}Kmeans::~Kmeans()
{}//计算质心
void Kmeans::Calcentroid()
{centroid s;for (int i = 0; i < k.size(); i++){s.sx = 0; s.sy = 0; int iCt = 0;for (int j = 0; j < S.size(); j++){if (k.at(i).no == S.at(j).noK){s.sx = s.sx + S.at(j).x;s.sy = s.sy + S.at(j).y;iCt++;}}s.noK = k.at(i).no;s.sx = s.sx / iCt;s.sy = s.sy / iCt;dis.push_back(s);}
}//计算每个对象至聚类中心的距离
void Kmeans::CalDis()
{for (int i = 0; i < p.size(); i++){double s0 = 0; QString no; Dis ss; int t = 0;double x1 = p.at(i).x;double y1 = p.at(i).y;//double x = k.at(0).x;//double y = k.at(0).y;//s0 = sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y));for (int j = 0; j < k.size(); j++){double x2 = k.at(j).x;double y2 = k.at(j).y;double s1 = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));t++;if (t == 1){s0 = s1;no = k.at(j).no;}if (s1 < s0){s0 = s1;no = k.at(j).no;}}ss.s = s0;ss.no = p.at(i).no;ss.x = p.at(i).x;ss.y = p.at(i).y;ss.noK = no;S.push_back(ss);}}//将新的质心坐标赋值给k
void Kmeans::CKmeans()
{for (int i = 0; i < k.size(); i++){for (int j = 0; j < dis.size(); j++){if (k.at(i).no == dis.at(j).noK){k.at(i).x = dis.at(j).sx;k.at(i).y = dis.at(j).sy;}}}
}//绘图函数
void Kmeans::drawPoint()
{QPicture pp;pp.setBoundingRect(ui.label_2->rect());QPainter painterP(&pp);QPen pen;painterP.setRenderHint(QPainter::Antialiasing, true);Pointp p1;p1.no = p.at(0).no;p1.x = p.at(0).x;p1.y = p.at(0).y;for (int i = 1; i < p.size(); i++){if (p1.x > p.at(i).x){p1.x = p.at(i).x;}if (p1.y > p.at(i).y){p1.y = p.at(i).y;}}double xmin = p1.x;double ymin = p1.y;for (int i = 1; i < p.size(); i++){if (p1.x < p.at(i).x){p1.x = p.at(i).x;}if (p1.y < p.at(i).y){p1.y = p.at(i).y;}}double xmax = p1.x;double ymax = p1.y;int w=ui.label_2->width();int h=ui.label_2->height();double a = w/(xmax -xmin);double b1 = h/(ymax -ymin);for (int i = 0; i < k.size(); i++){int r = qrand() % 256;int g = qrand() % 256;int b = qrand() % 256;QColor color = QColor(r, g, b);for (int j = 0; j < S.size(); j++){if (k.at(i).no == S.at(j).noK){pen.setColor(color);painterP.setPen(pen);int radius = 5;double x = S.at(j).x;double y = S.at(j).y;x = (x - xmin)*a;y = (y - ymin)*b1;painterP.drawEllipse(x - radius, y - radius, radius * 2, radius * 2);}}}ui.label_2->setPicture(pp);
}void Kmeans::CalK()
{k.push_back(p.at(0));CalDistance();while (k.size() != K){qDebug() << k.size() << k.at(k.size() - 1).no;S.clear();CalDistance();for (auto& val : k){qDebug() << "CalK.k1" << val.no << val.x << val.y;}std::vector<Pointp> vk; int t3 = k.size();while (vk.size() != t3){Pointp p9 = k.at(0); int t2 = 0;for (int i = 1; i < k.size(); i++){Pointp p2 = k.at(i);if (p9.no.toInt() < k.at(i).no.toInt()){p9 = k.at(i);t2 = i;}}k.erase(k.begin() + t2);//删除下标为t2的元素;vk.push_back(p9);}for (int i = vk.size() - 1; i >= 0; i--){k.push_back(vk.at(i));}for (auto& val : k){qDebug() <<"CalK.k" << val.no << val.x << val.y;}int cv = 1;for (auto& val : k){S.erase(S.begin() + (val.no.toInt() - cv));//删除下标为val.number的元素;cv++;}double s0 = 0;Pointp kk;kk = { 0,0,0 };for (auto& valS : S){if (s0 <= valS.s){s0 = valS.s;kk.no = valS.no;kk.x = valS.x;kk.y = valS.y;}}k.push_back(kk);}int count = 1;for (auto& val : k){val.no = count;count++;//qDebug() << val.no << val.x << val.y;}
}void Kmeans::drawK()
{QPicture pp;pp.setBoundingRect(ui.label_2->rect());QPainter painterP(&pp);QPen pen;painterP.setRenderHint(QPainter::Antialiasing, true);Pointp p1;p1.no = p.at(0).no;p1.x = p.at(0).x;p1.y = p.at(0).y;for (int i = 1; i < p.size(); i++){if (p1.x > p.at(i).x){p1.x = p.at(i).x;}if (p1.y > p.at(i).y){p1.y = p.at(i).y;}}double xmin = p1.x;double ymin = p1.y;for (int i = 1; i < p.size(); i++){if (p1.x < p.at(i).x){p1.x = p.at(i).x;}if (p1.y < p.at(i).y){p1.y = p.at(i).y;}}double xmax = p1.x;double ymax = p1.y;int w = ui.label_2->width();int h = ui.label_2->height();double a = w / (xmax - xmin);double b1 = h / (ymax - ymin);QColor color = QColor(123,223,46);for (int i = 0; i < k.size(); i++){pen.setColor(color);pen.setWidth(3);painterP.setPen(pen);int radius = 10;double x = k.at(i).x;double y = k.at(i).y;x = (x - xmin) * a;y = (y - ymin) * b1;painterP.drawEllipse(x - radius, y - radius, radius * 2, radius * 2);}ui.label_2->setPicture(pp);
}void Kmeans::CalDistance()
{Dis ss;for (auto& valP : p){double s0 = 0; int c = 1;double x1 = valP.x;double y1 = valP.y;for (auto& valK : k){double x2 = valK.x;double y2 = valK.y;x2 = x2 - x1;y2 = y2 - y1;double s = sqrt(x2 * x2 + y2 * y2);if (c == 1){s0 = s;ss.no = valP.no;ss.noK = valK.no;ss.x = valP.x;ss.y = valP.y;ss.s = s;c++;}if (s0 == 0){ss.no = valP.no;ss.noK = valK.no;ss.x = valP.x;ss.y = valP.y;ss.s = s;break;}if (s < s0){s0 = s;ss.no = valP.no;ss.noK = valK.no;ss.x = valP.x;ss.y = valP.y;ss.s = s;}}S.push_back(ss);}
}
#pragma once#include <QtWidgets/QWidget>
#include "ui_Kmeans.h"
#include<QFileDialog>
#include<QFile>
#include<QMessageBox>
#include<QTextStream>
#include<vector>
#pragma execution_character_set("UTF-8")
#include<qDebug>
#include<QPainter>
#include<QColor>
#include<QColorDialog>
#include<QPicture>
#include <algorithm>struct Pointp
{double x;double y;QString no;
};struct Dis
{double x;double y;QString no;QString noK;double s;
};struct centroid
{QString noK;double sx;double sy;
};enum Pd
{readK,to2K,blank
};class Kmeans : public QWidget
{Q_OBJECTpublic:Kmeans(QWidget *parent = nullptr);~Kmeans();public slots:void onBtReadData();int onBtCalKmeans();void onBtReadK();public:std::vector<Pointp> p;//原始数据点std::vector<Pointp> k;//各簇质心坐标int K;std::vector<Dis> S;std::vector<centroid> dis;bool start;Pd dd;public:void Calcentroid();void CKmeans();void CalDis();void drawPoint();void CalK();void drawK();void toK();void CalDistance();private:Ui::KmeansClass ui;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247637.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024.1.28 GNSS 学习笔记

1.基于 地球自转改正卫地距 以及 伪距码偏差 重构定位方程&#xff1a; 先验残差计算公式如下所示&#xff1a; 2.观测值如何定权&#xff1f;权重如何确定&#xff1f; 每个卫星的轨钟精度以及电离层模型修正后的误差都有差异&#xff0c;所以我们不能简单的将各个观测值等权…

qemu 抓取linux kernel vmcore

一、背景 在qemu调试linux kernel时 有时我们会遇到dump 情况&#xff0c;这时可以通过gdb 方式连接分析dump&#xff0c; 但实际中我们用得更多的是离线dump 分析&#xff0c;分析的文件通常是vmcore&#xff08;linux kernel panic 生成的coredump文件&#xff09;或者ramdu…

算法沉淀——二分查找(leetcode真题剖析)

算法沉淀——二分查找 01.二分查找02.在排序数组中查找元素的第一个和最后一个位置03.搜索插入位置04.x 的平方根05.山脉数组的峰顶索引06.寻找峰值07.寻找旋转排序数组中的最小值08.LCR 173. 点名 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元…

wordpress找不回密码怎么办?4种方法设置新密码

有些WordPress站长太久不登录后台了&#xff0c;所以就忘记了管理员登录密码&#xff0c;这种情况我们应该怎么找回密码呢&#xff1f;或者设置一个新密码呢&#xff1f;下面boke112百科就跟大家分享4种方法设置WordPress新密码。 方法一、登录页面的“忘记密码&#xff1f;”…

在Windows上安装与配置Apache服务并结合内网穿透工具实现公网远程访问本地内网服务

文章目录 前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpolar web ui管理界面3.2 创建公网地址 4. 固定公网地址 前言 Apache作为全球使用较高的Web服务器…

Linux服务器配置与管理(第二次实验)

实验目的及具体要求 目的 1.掌握基于命令行的文件操作 2.掌握基于命令行的目录操作 3.掌握用户账户的命令行操作 4.掌握组账户的命令行操作 5.熟悉磁盘分区操作 6.掌握调整优先级的方法 具体要求 1.掌握基于命令行的文件和目录操作 ①创建测试目录 ②创建文件 ③复…

代码随想录算法训练营DAY6 | 哈希表(1)

DAY5休息一天&#xff0c;今天重启~ 哈希表理论基础&#xff1a;代码随想录 Java hash实现 &#xff1a;java 哈希表-CSDN博客 一、LeetCode 242 有效的字母异位词 题目链接&#xff1a;242.有效的字母异位词 思路&#xff1a;设置字典 class Solution {public boolean isAnag…

设计模式:简单工厂模式

工厂设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。工厂模式属于创建型模式&#xff0c;它在创建对象时提供了一种封装机制&#xff0c;将实际创建对象的代码与使用代码分离。 …

腾讯云幻兽帕鲁服务器创建教程,附4核16G服务器价格表

腾讯云0基础搭建帕鲁服务器4C16G14M服务器稳定无卡顿&#xff0c;先下载SteamCMD&#xff0c;并运行&#xff1b;然后下载Palserver&#xff0c;修改服务ini配置&#xff0c;启动PalServer&#xff0c;进入游戏服务器。腾讯云百科txybk.com分享腾讯云创建幻兽帕鲁服务器教程&am…

LabVIEW准分子激光器控制系统

LabVIEW准分子激光器控制系统是为了实现准分子激光光源在工业、医疗和科研领域的应用集成及其功能的扩展。系统由PC端和激光器端两部分构成&#xff0c;通过光隔离的RS232通讯连接&#xff0c;以实现稳定可靠的控制与通信。 系统主要由微控制单元&#xff08;MCU&#xff09;主…

【算法专题】动态规划综合篇

动态规划7.0 1. 最长公共子序列2. 不相交的线3. 不同的子序列4. 通配符匹配5. 正则表达式匹配6. 交错字符串7. 两个字符串的最小ASCII删除和8. 最长重复子数组 1. 最长公共子序列 题目链接 -> Leetcode -1143.最长公共子序列 Leetcode -1143.最长公共子序列 题目&#xf…

堆的概念,性质及其实现

1.堆的概念及结构 如果有一个关键码的集合K { &#xff0c; &#xff0c; &#xff0c;…&#xff0c; }&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足&#xff1a; < 且 < ( > 且 > ) i 0&#xff0c;1&#x…

Java RC4加密算法

一、RC4加密算法 在密码学中&#xff0c;RC4&#xff08;来自Rivest Cipher 4的缩写&#xff09;是一种流加密算法&#xff0c;密钥长度可变。它加解密使用相同的密钥&#xff0c;因此也属于对称加密算法。 百度百科 - RC4&#xff1a;https://baike.baidu.com/item/RC4/34545…

JavaEE 网络原理

JavaEE 网络原理 文章目录 JavaEE 网络原理1. 网络互连1.1 局域网LAN1.2 广域网WAN 2. 网络通信基础2.1 IP地址2.2 端口号 3. 网络协议3.1 概念3.2 五元组3.3 协议分层3.4 TCP/IP 五层模型3.5 封装和分用 1. 网络互连 随着时代的发展&#xff0c;需要多个计算机协同工作来完成…

Docker安装RcoketMQ

1、Docker安装RcoketMQ-4.9.4 在同级文件夹创建目录config&#xff0c;并在里面创建文件broker.conf&#xff0c;文件内容如下&#xff1a; brokerClusterNameDefaultCluster brokerNamebroker-a brokerId0 deleteWhen04 fileReservedTime48 brokerRoleASYNC_MASTER flushDis…

Java项目:基于SSM框架实现的高校毕业生就业管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm817基于SSM框架实现的高校毕业生就业管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调…

Qlik Sense : IntervalMatch(离散匹配)

什么是IntervalMatch IntervalMatch 前缀用于创建表格以便将离散数值与一个或多个数值间隔进行匹配&#xff0c;并且任选匹配一个或多个额外关键值。 语法&#xff1a; IntervalMatch (matchfield)(loadstatement | selectstatement ) IntervalMatch (matchfield,keyfield…

Docker部署Stable-Diffusion-webui

前排提示&#xff1a;如果不想折腾&#xff0c;可直接跳到最后获取封装好的容器&#xff0c;一键运行 :D 前言 乘上AI生成的快车&#xff0c;一同看看沿途的风景。 启一个miniconda容器 docker run -itd -v 宿主机内SD项目路径:/tmp --gpus all --ipc host -p 7860:7860 con…

正则匹配 | 正则实际应用探索分享

这并不是一篇教正则基础的文章&#xff0c;其正则式不能对您进行使用后的结果负责&#xff0c;请以研究的眼光看待本篇文章。 技术就是懒人为了更好的懒才会想办法搞的东西&#xff0c;我最近因为某些原因需要频繁删除注释 我就想到通过替换的正则功能快速删除文件中的简单注…

RT-Thread: STM32 SPI使用流程

1.添加驱动 ①点开设置界面 ②勾选看门 SPI 驱动 ③点击保存 ④查看添加的驱动文件 drv_spi.c 2.打开驱动头文件定义 ①打开配置文件 ②打开定义 3.打开需要开启的SPI总线 打开 drivers 目录下的 board.h 用SPI搜索&#xff0c;找到如下文字&#xff0c;打开对应的宏。 /*-…