opencv3中的机器学习算法之:EM算法

不同于其它的机器学习模型,EM算法是一种非监督的学习算法,它的输入数据事先不需要进行标注。相反,该算法从给定的样本集中,能计算出高斯混和参数的最大似然估计。也能得到每个样本对应的标注值,类似于kmeans聚类(输入样本数据,输出样本数据的标注)。实际上,高斯混和模型GMM和kmeans都是EM算法的应用。

在opencv3.0中,EM算法的函数是trainEM,函数原型为:

 bool trainEM(InputArray samples, OutputArray logLikelihoods=noArray(),OutputArray labels=noArray(),OutputArray probs=noArray())

四个参数:

samples: 输入的样本,一个单通道的矩阵。从这个样本中,进行高斯混和模型估计。

logLikelihoods: 可选项,输出一个矩阵,里面包含每个样本的似然对数值。

labels: 可选项,输出每个样本对应的标注。

probs: 可选项,输出一个矩阵,里面包含每个隐性变量的后验概率

这个函数没有输入参数的初始化值,是因为它会自动执行kmeans算法,将kmeans算法得到的结果作为参数初始化。

这个trainEM函数实际把E步骤和M步骤都包含进去了,我们也可以对两个步骤分开执行,OPENCV3.0中也提供了分别执行的函数:

bool trainE(InputArray samples, InputArray means0,
                        InputArray covs0=noArray(),
                        InputArray weights0=noArray(),
                        OutputArray logLikelihoods=noArray(),
                        OutputArray labels=noArray(),
                        OutputArray probs=noArray())
 bool trainM(InputArray samples, InputArray probs0,
                        OutputArray logLikelihoods=noArray(),
                        OutputArray labels=noArray(),
                        OutputArray probs=noArray())
trainEM函数的功能和kmeans差不多,都是实现自动聚类,输出每个样本对应的标注值。但它比kmeans还多出一个功能,就是它还能起到训练分类器的作用,用于后续新样本的预测。

预测函数原型为:
Vec2d predict2(InputArray sample, OutputArray probs) const

sample: 待测样本

probs : 和上面一样,一个可选的输出值,包含每个隐性变量的后验概率

返回一个Vec2d类型的数,包括两个元素的double向量,第一个元素为样本的似然对数值,第二个元素为最大可能混和分量的索引值。

在本文中,我们用两个实例来学习opencv中的EM算法的应用。

一、opencv3.0中自带的例子,既包括聚类trianEM,也包括预测predict2

代码:

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;

//使用EM算法实现样本的聚类及预测
int main()
{
    const int N = 4;    //分成4类
    const int N1 = (int)sqrt((double)N);
    //定义四种颜色,每一类用一种颜色表示
    const Scalar colors[] =
    {
        Scalar(0, 0, 255), Scalar(0, 255, 0),
        Scalar(0, 255, 255), Scalar(255, 255, 0)
    };

    int i, j;
    int nsamples = 100;   //100个样本点
    Mat samples(nsamples, 2, CV_32FC1);  //样本矩阵,100行2列,即100个坐标点
    Mat img = Mat::zeros(Size(500, 500), CV_8UC3);  //待测数据,每一个坐标点为一个待测数据
    samples = samples.reshape(2, 0);

    //循环生成四个类别样本数据,共样本100个,每类样本25个
    for (i = 0; i < N; i++)
    {

        Mat samples_part = samples.rowRange(i*nsamples / N, (i + 1)*nsamples / N);

        //设置均值
        Scalar mean(((i%N1) + 1)*img.rows / (N1 + 1),
            ((i / N1) + 1)*img.rows / (N1 + 1));
        //设置标准差
        Scalar sigma(30, 30);
        randn(samples_part, mean, sigma);  //根据均值和标准差,随机生成25个正态分布坐标点作为样本
    }
    samples = samples.reshape(1, 0);
    // 训练分类器
    Mat labels;  //标注,不需要事先知道
    Ptr<EM> em_model = EM::create();
    em_model->setClustersNumber(N);
    em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
    em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 300, 0.1));
    em_model->trainEM(samples, noArray(), labels, noArray());

    //对每个坐标点进行分类,并根据类别用不同的颜色画出
    Mat sample(1, 2, CV_32FC1);
    for (i = 0; i < img.rows; i++)
    {
        for (j = 0; j < img.cols; j++)
        {
            sample.at<float>(0) = (float)j;
            sample.at<float>(1) = (float)i;
            //predict2返回的是double值,用cvRound进行四舍五入得到整型
            //此处返回的是两个值Vec2d,取第二个值作为样本标注
            int response = cvRound(em_model->predict2(sample, noArray())[1]);
            Scalar c = colors[response];  //为不同类别设定颜色
            circle(img, Point(j, i), 1, c*0.75, FILLED);
        }
    }

    //画出样本点
    for (i = 0; i < nsamples; i++)
    {
        Point pt(cvRound(samples.at<float>(i, 0)), cvRound(samples.at<float>(i, 1)));
        circle(img, pt, 2, colors[labels.at<int>(i)], FILLED);
    }

    imshow("EM聚类结果", img);
    waitKey(0);

    return 0;
}

结果:

二、只用trainEM实现自动聚类功能,进行图片中的目标检测

代码:

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;

int main()
{
    const int MAX_CLUSTERS = 5;
    Vec3b colorTab[] =
    {
        Vec3b(0, 0, 255),
        Vec3b(0, 255, 0),
        Vec3b(255, 100, 100),
        Vec3b(255, 0, 255),
        Vec3b(0, 255, 255)
    };
    Mat data, labels;
    Mat pic = imread("d:/woman.png");
    for (int i = 0; i < pic.rows; i++)
    for (int j = 0; j < pic.cols; j++)
    {
        Vec3b point = pic.at<Vec3b>(i, j);
        Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
        data.push_back(tmp);
    }

    int N =3;  //聚成3类
    Ptr<EM> em_model = EM::create();
    em_model->setClustersNumber(N);
    em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
    em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 300, 0.1));
    em_model->trainEM(data, noArray(), labels, noArray());

    int n = 0;
    //显示聚类结果,不同的类别用不同的颜色显示
    for (int i = 0; i < pic.rows; i++)
    for (int j = 0; j < pic.cols; j++)
    {
        int clusterIdx = labels.at<int>(n);
        pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
        n++;
    }
    imshow("pic", pic);
    waitKey(0);

    return 0;
}

测试图片

测试结果:

时间: 12-07

opencv3中的机器学习算法之:EM算法的相关文章

【机器学习】K-means聚类算法与EM算法

初始目的 将样本分成K个类,其实说白了就是求一个样本例的隐含类别y,然后利用隐含类别将x归类.由于我们事先不知道类别y,那么我们首先可以对每个样例假定一个y吧,但是怎么知道假定的对不对呢?怎样评价假定的好不好呢? 我们使用样本的极大似然估计来度量,这里就是x和y的联合分布P(x,y)了.如果找到的y能够使P(x,y)最大,那么我们找到的y就是样例x的最佳类别了,x顺手就聚类了.但是我们第一次指定的y不一定会让P(x,y)最大,而且P(x,y)还依赖于其他未知参数,当然在给定y的情况下,我们可以调

在opencv3中实现机器学习之:利用正态贝叶斯分类

opencv3.0版本中,实现正态贝叶斯分类器(Normal Bayes Classifier)分类实例 #include "stdafx.h" #include "opencv2/opencv.hpp" using namespace cv; using namespace cv::ml; int main(int, char**) { int width = 512, height = 512; Mat image = Mat::zeros(height, wi

简单易学的机器学习算法——EM算法

一.机器学习中的參数预计问题 在前面的博文中,如"简单易学的机器学习算法--Logistic回归"中,採用了极大似然函数对其模型中的參数进行预计,简单来讲即对于一系列样本,Logistic回归问题属于监督型学习问题,样本中含有训练的特征 X_i" title="X_i" >以及标签.在Logistic回归的參数求解中.通过构造样本属于类别和类别的概率: 这样便能得到Logistic回归的属于不同类别的概率函数: 此时,使用极大似然预计便可以预计出模型

EM算法及其推广的要点

1.EM算法是含有隐变量的变量的概率模型极大似然估计或极大后验概率估计的迭代算法,含有隐变量的概率模型的数据表示为$P(Y,Z|\theta)$.这里,$Y$是观测变量的数据,$Z$是隐变量的数据,$\theta$是模型参数.EM算法通过迭代求解观测数据的对数似然函数$L(\theta)=logP(Y|\theta)$的极大化,实现极大似然估计.每次迭代包括两步:E步,求期望,即求$logP(Y|\theta)$关于$P(Y|\theta^{(i)})$的期望: $Q(\theta,\theta

EM算法概念

EM算法是一种非常经典的alternative optimizing算法.alternative optimizing的思想就是对于一个最优化问题,可以计算分为两步或者参数分为两个,就可以随机任意的选择一个起始值或位置,固定一个参数A,以另一个参数B进行优化,然后固定参数B,以参数A进行优化,直到收敛未知.前面博文中所讲述的K-means也就这样的一个过程,或者meanshift均值漂移也是这样的一个思想.今天学习的一个算法也是这样一个概念.这里依然做一个入门级的概念理解指导,不做原理性的深入,

EM算法原理以及高斯混合模型实践

EM算法有很多的应用: 最广泛的就是GMM混合高斯模型.聚类.HMM等等. The EM Algorithm 高斯混合模型(Mixtures of Gaussians)和EM算法 EM算法 求最大似然函数估计值的一般步骤: (1)写出似然函数: (2)对似然函数取对数,并整理: (3)求导数,令导数为0,得到似然方程: (4)解似然方程,得到的参数即为所求. 期望最大化算法(EM算法): 优点: 1. 简单稳定: 2. 通过E步骤和M步骤使得期望最大化,是自收敛的分类算法,既不需要事先设定类别也

机器学习中的EM算法详解及R语言实例(1)

最大期望算法(EM) K均值算法非常简单(可参见之前发布的博文),详细读者都可以轻松地理解它.但下面将要介绍的EM算法就要困难许多了,它与极大似然估计密切相关. 1 算法原理 不妨从一个例子开始我们的讨论,假设现在有100个人的身高数据,而且这100条数据是随机抽取的.一个常识性的看法是,男性身高满足一定的分布(例如正态分布),女性身高也满足一定的分布,但这两个分布的参数不同.我们现在不仅不知道男女身高分布的参数,甚至不知道这100条数据哪些是来自男性,哪些是来自女性.这正符合聚类问题的假设,除

【机器学习】EM算法详细推导和讲解

[机器学习]EM算法详细推导和讲解 今天不太想学习,炒个冷饭,讲讲机器学习十大算法里有名的EM算法,文章里面有些个人理解,如有错漏,还请读者不吝赐教. 众所周知,极大似然估计是一种应用很广泛的参数估计方法.例如我手头有一些东北人的身高的数据,又知道身高的概率模型是高斯分布,那么利用极大化似然函数的方法可以估计出高斯分布的两个参数,均值和方差.这个方法基本上所有概率课本上都会讲,我这就不多说了,不清楚的请百度. 然而现在我面临的是这种情况,我手上的数据是四川人和东北人的身高合集,然而对于其中具体的

MapReduce——并行期望最大值化算法(EM在高斯混合分布中的应用)

首先给出期望最大值化算法在高斯混合分布中的应用,我们用<Pattern Recognition and Machine Learning>中第九章中的符号: 假设有个观测数据组成的集合,个高斯分布, E步: ,,. M 步: , , , ,. ----------------------------------------------------- 并行的期望最大值化算法: 假设有个观测数据组成 的集合,个高斯分布,首先把这个观测数据,分成份(可以是不等分也可以是等分),假设这个子集,分别有

机器学习笔记—EM 算法

EM 算法所面对的问题跟之前的不一样,要复杂一些. EM 算法所用的概率模型,既含有观测变量,又含有隐变量.如果概率模型的变量都是观测变量,那么给定数据,可以直接用极大似然估计法,或贝叶斯估计法来估计模型参数,但是,当模型含有隐变量时,情况就复杂一些,相当于一个双层的概率模型,要估计出两层的模型参数,就需要换种方法求解.EM 算法是通过迭代的方法求解. 监督学习是由训练数据 {(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))} 学习条件概率分布 P(Y|X) 或决策