C均值聚類算法、感知器算法C++實現,Fisher線性判別MATLAB實現

模式識別課作業

C均值聚類步驟:

  1. 選取隨機類心
  2. 根據集合中點與各類心最小距離,對集合每個元素分類
  3. 將分類後各類元素的均值作爲新的類心
  4. 若類心不再更新,則結果收斂,算法結束
#include<bits/stdc++.h>
using namespace std;
int N;	//輸入數據個數 
int C;	//類別個數 
struct Node {
	double x, y;
	Node (double x = 0, double y = 0) : x(x), y(y) {
	}
}centers[100], preCenters[100], datas[1000]; 
vector<Node> cluster[100];	//當前聚類結果 

bool equals(Node x, Node y)		//判斷兩點是否相等 
{
	return fabs(x.x-y.x) < 0.0001 && fabs(x.y-y.y) < 0.0001;
}
bool check()	//判斷聚類結果是否收斂 
{
	for (int i = 0; i < C; i++) {
		if (!equals(preCenters[i], centers[i]))
			return false;
	}
	return true;
}
void updateCluster() //更新聚類集合 
{
	for (int i = 0; i < C; i++)
		cluster[i].clear();
	for (int i = 0; i < N; i++) {
		double minDis = 1e9;
		int index = 0;
		for (int j = 0; j < C; j++) {
			double dis = sqrt(pow(datas[i].x-centers[j].x, 2)+pow(datas[i].y-centers[j].y, 2));
			if (dis < minDis) {
				minDis = dis;
				index = j;
			}
		}
		cluster[index].push_back(datas[i]);
	}
}
void updateCenter() //更新類心集合 
{
	for (int i = 0; i < C; i++) {
		double sumX = 0, sumY = 0;
		int len = cluster[i].size();
		for (int j = 0; j < len; j++) {
			sumX += cluster[i][j].x;
			sumY += cluster[i][j].y;
		}
		if (len != 0)
			centers[i] = Node(sumX/len, sumY/len);
	}
}
int main() {
	freopen("Iris.txt", "r", stdin);
	C = 3;	
	N = 0;
	double x, y;
	while (cin >> x >> y) {
		datas[N++] = Node(x, y);	//讀取數據
	}
	for (int i = 0; i < C; i++)
		centers[i] = datas[i];		//隨機初始化類心 
	while (true) {
		updateCluster();
		updateCenter();
		printf("當前類心:(%f, %f)、(%f, %f)、(%f, %f)\n", centers[0].x, centers[0].y, centers[1].x, centers[1].y, centers[2].x, centers[2].y);
		if (check()) {
			break;
		} 
		memcpy(preCenters, centers, sizeof(centers));
	}
	freopen("C均值聚類結果.txt", "w", stdout);
	for (int i = 0; i < C; i++) {
		printf("第%d類類心:(%f, %f),該類中數據個數:%d\n", i, centers[i].x, centers[i].y, cluster[i].size());
		for (int j = 0; j < cluster[i].size(); j++) {
			printf("(%f, %f)\n", cluster[i][j].x, cluster[i][j].y);
		}
	}
	return 0;
}

感知器算法步驟:
在這裏插入圖片描述
在這裏插入圖片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500+10;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int N;	//總樣本個數 
int C;	//類別個數 
int D;	//樣本維度 
int p;	//增量 
int w[maxn][maxn];	//權矢量 
int x[maxn][maxn];	//訓練樣本 
int getDis(int k, int x[])	//求解判別函數 
{
	int dis = 0;
	for (int i = 0; i <= D; i++)
		dis += w[k][i]*x[i];
	return dis;
}
void updateWeight(int k, int x[], int mod)	//更新權矢量 
{
	for (int i = 0; i <= D; i++) {
		if (mod == 1)
			w[k][i] += p*x[i];
		else
			w[k][i] -= p*x[i];
	}
}
int main()
{
	freopen("感知器算法.txt", "r", stdin);
	cin >> C >> D >> p;	//輸入類別個數、樣本維度、增量 
	for (int i = 0; i < C; i++) {	
		for (int j = 0; j < D; j++) {
			cin >> x[i][j];	//輸入各類樣本 
		}
		x[i][D] = 1;	//分量增廣化 
	} 
	for (int i = 0; i < C; i++)
		for (int j = 0; j <= D; j++)
			w[i][j] = 0;				//增廣權矢量賦初值 
	int cnt = 0;
	while (true) {
		bool ok;
		for (int i = 0; i < C; i++) {
			cnt++;
			ok = true;
			int maxD = getDis(i, x[i]);
			for (int j = 0; j < C; j++) {
				if (j != i) {
					int d = getDis(j, x[i]);
					if (d >= maxD) {	//錯分 
						ok = false;
						updateWeight(j, x[i], 2);
					}
				}
			}
			if (!ok)
				updateWeight(i, x[i], 1);
			printf("第%d次遍歷權矢量求解結果:\n", cnt);
			for (int i = 0; i < C; i++) {
				for (int j = 0; j <= D; j++)
					printf("%d ", w[i][j]);
				cout << "\n";
			}
		}
		if (ok) {
			cout << "所求解矢量爲:\n";
			for (int i = 0; i < C; i++) {
				for (int j = 0; j <= D; j++)
					printf("%d ", w[i][j]);
				cout << "\n";
			}
			break;
		}
	}
	return 0;
}

Fisher線性判別步驟:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

x1 = importdata('x1.txt');
x2 = importdata('x2.txt');
x = importdata('x.txt');
m1 = mean(x1);
m2 = mean(x2);
len1 = length(x1);
len2 = length(x2);
n = 4;
S1 = 0;
S2 = 0;
for i = 1:len1
    xk = x1(i,:)-m1;
    S1 = S1 + xk*xk';
end
for i = 1:len2
    xk = x2(i,:)-m2;
    S2 = S2 + xk*xk';
end
Sw = S1 + S2;
u = inv(Sw)*(m1-m2);
M1 = u'*m1;
M2 = u'*m2;
yt = (M1+M2)/2;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章