模式识别课作业
C均值聚类步骤:
- 选取随机类心
- 根据集合中点与各类心最小距离,对集合每个元素分类
- 将分类后各类元素的均值作为新的类心
- 若类心不再更新,则结果收敛,算法结束
#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;