老师发布作业链接:(429条消息) 【22-23 春学期】AI作业4-无监督学习_HBU_David的博客-优快云博客
用自己的语言,解释概念、回答相关问题、编程实现算法
-
K均值聚类
-
K均值聚类是生成式还是判别式方法?
-
KNN VS. K-means
-
主成分分析
-
LDA VS. PCA
-
奇异值分解(SVD)
-
特征人脸方法(Eigenface)
-
潜在语义分析 (LSA)
-
期望最大化算法(EM)
-
K-means是最简单的EM算法?
-
编程实现EM算法
1. K均值聚类是一种无监督的聚类算法,是一种生成式方法。
2. KNN和K-means都是机器学习中的非监督学习方法。KNN是一种基于样本距离的分类算法,而K-means是一种聚类算法,是一种基于数据分布的算法。
3. 主成分分析(PCA)是一种降维算法,它可以找到数据中的主要方向,并将数据转换到与这些主要方向相关的坐标轴上。
4. LDA和PCA都是降维算法。LDA是一种线性判别分析方法,可以将数据投影到一个新的空间中,使得不同类别的数据点更加分开;PCA是一种主成分分析方法,可以在保留较高方差的前提下,减少数据的维度。
5. 奇异值分解(SVD)是将一个矩阵分解成三个矩阵的乘积:原矩阵=左奇异矩阵×奇异值矩阵×右奇异矩阵。SVD在矩阵压缩、图像压缩等领域有广泛应用。
6. 特征人脸方法(Eigenface)是一种人脸识别技术,该方法提取人脸图像的主要特征,并将其表示为基于特征向量的向量空间。
7. 潜在语义分析(LSA)是一种文本分析方法,通过对词汇在文本中的出现频率进行分析,找出其中的潜在语义,以实现文本的分类、聚类等操作。
8. 期望最大化算法(EM)是一种迭代算法,用于估计具有隐含变量的概率模型参数。该算法将未知参数看做隐含变量,通过迭代求解,逐步逼近参数的最大似然估计。
9. K-means可以看做是最简单的EM算法,它将每个数据点视为一个高斯分布的均值,通过迭代求解,将数据点分配到近似的均值中心,以实现数据聚类。
10. 实现EM算法的步骤主要包括初始化隐含变量、迭代求解隐含变量和参数估计。具体实现中,需要用到高斯混合模型的数学公式,其中包括对数似然函数、E步骤和M步骤等。
11.下面是C语言实现EM算法的代码示例。其中,为了简化代码,假设数据样本是由2个正态分布组成,且每个正态分布的均值和方差已知。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 定义数据样本的结构体
typedef struct {
double x;
double y;
} data_t;
// 定义高斯分布的结构体
typedef struct {
double mean;
double variance;
} gaussian_t;
// 计算正态分布的概率密度函数
double norm_pdf(double x, double mean, double variance) {
double std_dev = sqrt(variance);
double exponent = exp(-0.5 * pow((x - mean) / std_dev, 2));
return 1 / (sqrt(2 * M_PI) * std_dev) * exponent;
}
// 计算E步骤,返回数据样本属于每个分布的概率
void e_step(data_t* data_set, int num_samples, gaussian_t* gaussians, int num_gaussians, double* prob) {
int i, j;
double sum, pdf_val;
for (i = 0; i < num_samples; i++) {
sum = 0;
for (j = 0; j < num_gaussians; j++) {
pdf_val = norm_pdf(data_set[i].x, gaussians[j].mean, gaussians[j].variance);
sum += pdf_val;
prob[i*num_gaussians+j] = pdf_val;
}
for (j = 0; j < num_gaussians; j++) {
prob[i*num_gaussians+j] /= sum;
}
}
}
// 计算M步骤,返回每个高斯分布的新均值和方差
void m_step(data_t* data_set, int num_samples, gaussian_t* gaussians, int num_gaussians, double* prob) {
int i, j;
double sum, w_sum;
gaussian_t gaussian;
for (j = 0; j < num_gaussians; j++) {
sum = 0;
w_sum = 0;
for (i = 0; i < num_samples; i++) {
sum += prob[i*num_gaussians+j] * data_set[i].x;
w_sum += prob[i*num_gaussians+j];
}
gaussian.mean = sum / w_sum;
sum = 0;
for (i = 0; i < num_samples; i++) {
sum += prob[i*num_gaussians+j] * pow(data_set[i].x - gaussian.mean, 2);
}
gaussian.variance = sum / w_sum;
gaussians[j] = gaussian;
}
}
int main() {
// 初始化数据集
const int num_samples = 1000;
data_t data_set[num_samples];
for (int i = 0; i < num_samples; i++) {
if (i 2 == 0) {
data_set[i].x = 2 + (double)rand()/RAND_MAX*0.5;
data_set[i].y = 3 + (double)rand()/RAND_MAX*0.5;
} else {
data_set[i].x = 10 + (double)rand()/RAND_MAX*0.5;
data_set[i].y = 10 + (double)rand()/RAND_MAX*0.5;
}
}
// 初始化高斯分布
const int num_gaussians = 2;
gaussian_t gaussians[num_gaussians];
gaussians[0].mean = 1;
gaussians[0].variance = 1;
gaussians[1].mean = 9;
gaussians[1].variance = 1;
// 初始化概率数组
double prob[num_samples*num_gaussians];
// EM算法迭代
const int max_iter = 100;
double prev_likelihood = -INFINITY;
double likelihood;
int iter = 0;
while (iter < max_iter) {
// E步骤
e_step(data_set, num_samples, gaussians, num_gaussians, prob);
// 计算对数似然函数
likelihood = 0;
for (int i = 0; i < num_samples; i++) {
sum = 0;
for (int j = 0; j < num_gaussians; j++) {
sum += norm_pdf(data_set[i].x, gaussians[j].mean, gaussians[j].variance);
}
likelihood += log(sum);
}
if (likelihood - prev_likelihood < 0.0001) {
break;
}
prev_likelihood = likelihood;
// M步骤
m_step(data_set, num_samples, gaussians, num_gaussians, prob);
iter++;
}
// 打印聚类结果
for (int i = 0; i < num_gaussians; i++) {
printf("Gaussiand: mean2f, variance2f\n", i+1, gaussians[i].mean, gaussians[i].variance);
}
return 0;
}