模式識別中分級聚類演算法
阿新 • • 發佈:2019-02-09
分級聚類原理
具體原理參見清華大學出版社出版張學工編著的模式識別一書或者任意一本模式識別書。其分類規則有最大、最小、均值分類。本練習實現最小規則分類,即根據類間最小距離的最小值判定為一類。
C++程式碼
1.cluster.cpp
// cluster.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Point.h"
#include "ClassItem.h"
#include "iostream"
#include "cmath"
vector<Point> points;
vector<ClassItem> clas;
void outPutPoint(vector<Point> point){ //用於輸出點
vector<Point>::iterator it = point.begin();
while (it != point.end()){
cout<<it->x<<" "<<it->y<<" "<<it->z<<endl;
it++;
}
}
void outPutClass(vector<ClassItem> clas){
cout<<"輸出類"<<endl;
// vector<ClassItem>::iterator it = clas.begin();
auto it = clas.begin();
while (it!= clas.end()){
// vector<int>::iterator its = (it->getItem()).begin();
auto its = it->getItem().begin();
while (its != (it->getItem()).end()){
cout<<*its<<" ";
its++;
}
cout<<"類中包含的數目"<<it->getNum()<<endl;
it++;
}
}
double calDistance(int index1,int index2){//計算距離(兩個點之間)
double dis;
dis = pow((points[index1].x-points[index2].x),2)+pow((points[index1].y-points[index2].y),2)
+pow((points[index1].z-points[index2].z),2);
return dis;
}
void julei(int cl1,int cl2){
clas[cl1].addNum(clas[cl2].getNum());
clas[cl2].setNum(0);
ClassItem::CLASSNUM--;
vector<int> cl2Item = clas[cl2].getItem();
vector<int>::iterator it = cl2Item.begin();
while(it!= cl2Item.end()){
clas[cl1].getItem().push_back(*it);
it++;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int m_x[] = {3,0,2,2,2};
int m_y[] = {1,2,3,0,1};
int m_z[] = {3,4,2,3,3};
for(int i = 0; i!= 5;++i){
ClassItem cla;
cla = ClassItem(1,i);
clas.push_back(cla); //構造類的向量
Point point;
point= Point(m_x[i],m_y[i],m_z[i]);//構造點的陣列
points.push_back(point);
}
while(ClassItem::CLASSNUM!= 2){
//判斷距離求得最小距離
double minDis = pow(10,3);
int cl1,cl2;
for(int i = 0;i!= 4;++i){
for(int j = i+1;j != 5;++j){
if(clas[i].getNum()!= 0 && clas[j].getNum()!= 0){
vector<int> item1 = clas[i].getItem();
vector<int> item2 = clas[j].getItem();
vector<int>::iterator it1 = item1.begin();
vector<int>::iterator it2 = item2.begin();
while(it1 != item1.end()){
while(it2 != item2.end()){
double distance = calDistance(*it1,*it2);
it2++;
if(distance < minDis){
cl1 = i;
cl2 = j;
minDis = distance;
}
}
it1++;
}
}
}
}
//聚類
julei(cl1,cl2);
}
outPutPoint(points);//輸出點測試
outPutClass(clas); //輸出類的測試。
while(1);
return 0;
}
2.ClassItem.cpp
#include "stdafx.h"
#include "ClassItem.h"
int ClassItem::CLASSNUM = 5; //總類數,當有合併的時候減1
void ClassItem::addNum(int num){
this->num +=num;
}
void ClassItem::addPoint(int index){
item.push_back(index);
}
//建構函式
ClassItem::ClassItem(void)
{
}
ClassItem::ClassItem(int num, int index){ //用於初始化用
this->num = num;
this->item.push_back(index);
}
int ClassItem::getNum(){
return num;
}
void ClassItem::setNum(int num){
this->num = num;
}
vector<int> &ClassItem::getItem(){
return item;
}
ClassItem::~ClassItem(void)
{
}
3.Point.cpp
#include "stdafx.h"
#include "Point.h"
Point::Point(int x,int y,int z){
this->x = x;
this->y = y;
this->z = z;
}
Point::Point(void)
{
}
Point::~Point(void)
{
}
注意
1.具體類的標頭檔案就不上了
問題
1.在ClassItem.cpp中定義的getItem函式
vector<int> &ClassItem::getItem(){
return item;
}
首先定義的時候沒有加上引用符號,從而造成了錯誤,但是這個錯誤真心不好找,打印出class時,系統提示迭代器不匹配。搗鼓了很久才有些許理解,可能是因為沒有引用的時候本身沒有被修改,所以當列印的時候item還沒有被建立。所以產生了錯誤。具體原因不是很清楚,如果哪位大神知道還請不吝賜教。
結果
可見點被分成了兩類,1,3,4,5點為一類,2點為一類