OpenCV机器学习(3)期望最大化(Expectation-Maximization, EM)算法cv::ml::EM
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
cv::ml::EM 是 OpenCV 机器学习模块中的一部分,用于实现期望最大化(Expectation-Maximization, EM)算法。EM 算法是一种迭代方法,通常用于估计有限混合模型(如高斯混合模型,GMM)的参数。它在数据聚类、密度估计等领域有着广泛应用。
主要特点
- 混合模型:支持高斯混合模型(Gaussian Mixture Model, GMM),可以用于数据点的概率分布建模。
- 参数估计:通过 EM 算法自动估计模型参数(均值、协方差矩阵等)。
- 分类功能:不仅可以用于聚类,还可以用于预测新样本属于哪个类别。
- 自定义选项:允许用户指定组件数量、初始参数猜测、终止条件等。
常用成员函数
以下是一些常用的 cv::ml::EM 类成员函数:
创建和设置模型:
- create():创建一个新的 EM 模型实例。
- setClustersNumber(int val):设置混合模型中的成分(即高斯分布)的数量。
- setTermCriteria(TermCriteria val):设置 EM 训练过程的终止标准(如最大迭代次数或最小对数似然改善量)。
- setCovarianceMatrixType(int val):设置协方差矩阵的类型(如对角矩阵、球形等)。
训练模型:
- trainE(const Ptr& data):使用期望步骤训练模型,并返回对数似然值。
- trainM(const Mat& samples):使用最大化步骤训练模型(较少直接使用)。
预测:
- predict2(InputArray sample, OutputArray probs):对新样本进行预测,并返回每个类别的概率分布。
保存与加载模型:
- save(const String& filename):将模型保存到文件。
- load(const String& filename):从文件加载模型。
使用步骤
- 准备数据:准备好你的训练数据集,包括特征向量。
- 初始化 EM 模型:使用 cv::ml::EM::create() 创建一个新的 EM 模型实例,并根据需要设置参数。
- 训练模型:调用 trainE() 方法,传入你的训练数据来进行模型训练。
- 评估模型:可以通过计算对数似然值来评估模型性能,或者在独立的测试集上评估模型性能。
- 预测新数据:使用训练好的模型对新的未见过的数据进行预测,并获取其所属类别的概率分布。
代码示例
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
using namespace cv;
using namespace cv::ml;
using namespace std;
int main() {
// 准备训练数据
Mat samples = (Mat_<float>(4, 2) <<
0.5, 1.0,
1.0, 1.5,
2.0, 0.5,
1.5, 0.0);
// 创建并配置 EM 模型
Ptr<EM> em_model = EM::create();
em_model->setClustersNumber(2); // 设置混合模型中的成分数量
em_model->setCovarianceMatrixType(EM::COV_MAT_DIAGONAL); // 协方差矩阵类型
em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 300, 0.1));
// 使用 TrainData::create 将样本数据封装成 TrainData 对象
Ptr<TrainData> tdata = TrainData::create(samples, ROW_SAMPLE, Mat());
// 训练模型
bool ok = em_model->train(tdata);
if (ok) {
// 保存模型
em_model->save("em_model.yml");
// 对新样本进行预测
Mat sample = (Mat_<float>(1, 2) << 1.6, 0.7);
Mat probs;
int response = em_model->predict(sample, probs);
cout << "The predicted response for the sample is: " << response << endl;
cout << "Probabilities: " << probs << endl;
} else {
cerr << "Training failed!" << endl;
}
return 0;
}
运行结果
The predicted response for the sample is: 0
Probabilities: [0.9983411783982278, 0.001658821601772262]