




已阅读5页,还剩35页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Opencv2.4.9源码分析Expectation Maximization一、原理 期望极大算法(EM,Expectation Maximization)是一种能够得到极大似然参数估计的迭代方法。虽然EM算法在不同的领域被更早的提出,但它是由Dempster等人于1977年被正式命名并给出解释。对于一个除了拥有未知参数和可观测变量外,还包含隐含变量的统计模型来说,是无法用极大似然方法直接得到参数的,这是因为我们不能像极大似然法那样,同时对未知参数和隐含变量求导来求解似然函数。但该模型可以应用EM算法得到,它是通过可观测变量分别求解两个方程,即把第一个方程的解代入第二个方程中,再把第二个方程的解代入第一个方程中,依次类推直到收敛为止。虽然EM算法不能保证得到全局极值点,但可以通过一些方法得到改善,如选取不同的初始值,比较最终的结果。下面我们就来详细推导EM算法。给定一组相互独立且同分布的训练样本Xx1,x2,xn,每个样本都是一个d维的向量,即每个样本都具有d个特征属性,xiRd,设p(X|)为被参数控制的概率密度函数,如X服从高斯正态分布,则表示均值和标准差,即XN(, 2):式中,p(xi| )jp(xi,yj|)表示观测到的变量xi的概率分布为所有类标签yi(i1,K)下xi的概率之和。式5中包含了“和的对数(ln)”的形式,因此我们还是应用导数为0的方法求最大值就不那么容易了。很明显,如果Y已知,则通过完整数据Z的似然函数L(; X, Y)ln p(X, Y| )可以很容易的得到参数。L(; X, Y)其实是一个X和是常数,Y是随机变量的函数。基于引入的隐含变量,EM算法给出了一种非常有效的处理极大似然参数估计的迭代方法。每次迭代都包括两个步骤:期望步骤(E-Step)和极大步骤(M-Step)。在E-Step中,需要计算在给定X和当前参数估计下,关于Y的完整数据的对数似然函数ln p(X, Y| )的期望值,其定义为:式69的结果再代入式66式68,这样就实现了一次次迭代的过程。在第一次迭代之前,我们需要初始化参数。这里有两种初始化参数的方法:第一种是只初始化p(k|xi,(0),然后由式66式68分别得到k(1),k(1)和k(1),也就是该种方法是从M-Step开始执行;第二种是初始化k(0),k(0)和k(0),然后由式69得到p(k|xi,(0),也就是该种方法是从E-Step开始执行。这两种参数初始化的方法效果是相同的。当然在第二种方法中,k(0),k(0),和k(0)也可以由k-means算法估计得到。有两种方法用来结束EM算法的迭代:一种是按照迭代的次数;另一种是判断迭代是否足够收敛,而收敛是通过两次迭代中对数似然函数是否足够接近来判断的,即两个对数似然函数之差小于某一极小值时,我们认为迭代收敛了,则EM算法结束。下式为高斯混合模型的对数似然函数:二、源码分析 OpenCV所实现的EM算法是对高斯混合模型的参数估计。与前面介绍过的其他的机器学习算法不同,EM算法是非监督的学习算法,它不需要样本的响应值(即类别标签或函数值)作为输入。相反,它计算的是高斯混合模型参数的极大似然估计。 EM类实现了EM算法,该类的构造函数为:cpp view plain copy 在CODE上查看代码片派生到我的代码片EM:EM (int nclusters = EM:DEFAULT_NCLUSTERS, int covMatType = EM:COV_MAT_DIAGONAL, const TermCriteria& termCrit = TermCriteria (TermCriteria:COUNT+TermCriteria:EPS, EM:DEFAULT_MAX_ITERS, FLT_EPSILON) ) nclusters表示高斯混合模型的高斯成分数量,即式27中的K,该参数的缺省值为EM:DEFAULT_NCLUSTERS=5,有些EM算法可以通过优化得到该值,但OpenCV没有实现该功能,所以只能事前确定该值。covMatType表示对协方差矩阵的一种限制,也就是协方差矩阵的形式,可以选取下列三个值:EM:COV_MAT_SPHERICAL、EM:COV_MAT_DIAGONAL和EM:COV_MAT_GENERIC,其中EM:COV_MAT_DIAGONAL为缺省值。EM:COV_MAT_SPHERICAL表示协方差矩阵是一个标量乘以单位矩阵,即skI,所以对协方差矩阵的估计只需要确定sk即可;EM:COV_MAT_DIAGONAL表示协方差矩阵是一个对角线元素为正数的对角矩阵,这时只需要对d个参数进行估计即可,d为样本特征属性的数量;EM:COV_MAT_GENERIC表示协方差矩阵是一个对称的正数矩阵,很显然,此时需要估计d2/2个参数,除非样本数据庞大,否则不建议设置该参数。termCrit表示EM算法迭代的终止条件,终止条件可以是依据迭代次数termCrit.maxCount,也可以依据对数似然函数值的变化量termCrit.epsilon,也可以两者结合。从输入样本中实现高斯混合模型参数估计的函数有三个,它们的原型分别为:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool EM:train(InputArray samples, OutputArray logLikelihoods=noArray(), OutputArray labels=noArray(), OutputArray probs=noArray() bool EM:trainE(InputArray samples, InputArray means0, InputArray covs0=noArray(), InputArray weights0=noArray(), OutputArray logLikelihoods=noArray(), OutputArray labels=noArray(), OutputArray probs=noArray() bool EM:trainM(InputArray samples, InputArray probs0, OutputArray logLikelihoods=noArray(),OutputArray labels=noArray(), OutputArray probs=noArray() train函数是从E-Step开始迭代,它所需要的初始参数均值k,权值因子k和协方差矩阵k是由k-means算法估计得到。trainE函数是从E-Step开始迭代,我们需要提供初始的高斯参数中的均值k,而权值因子k和协方差矩阵k可以不用初始化,也由k-means算法估计得到。trainM函数是从M-Step开始迭代,我们需要提供初始的后验概率p(k|xi,(0)。在这三个函数中,输入参数的含义分别为:samples表示输入样本,我们从这些样本中估计出高斯混合模型的参数,该变量为单通道的矩阵形式,行代表一个样本,列代表特征属性,如果该矩阵的数据类型不是CV_64F,则程序内部会自动把它转换为该类型。means0表示初始化的均值k,它是单通道的矩阵形式,矩阵的大小为Kd,K为高斯混合成分数量,d为样本特征属性的数量,如果该矩阵的数据类型不是CV_64F,则程序内部会自动把它转换为该类型。covs0表示初始化的协方差矩阵k,它是单通道的矩阵形式,矩阵的大小为dd,如果该矩阵的数据类型不是CV_64F,则程序内部会自动把它转换为该类型。weights0表示初始化的权值因子k,它是单通道的浮点型矩阵形式,矩阵的大小可以是1K,也可以是K1。probs0表示初始化的第i个样本属于第k个高斯成分的后验概率p(k|xi,(0),它是单通道的浮点型矩阵形式,矩阵的大小为nK,n为样本的数量。logLikelihoods表示可选的输出矩阵,该矩阵包含每个样本的对数似然值,矩阵的大小为n1,数据类型为CV_64FC1。labels表示可选的输出变量,表示最终的每个样本的类别标签,即它最有可能属于的那个高斯成分的索引值,公式的表达形式为:labelsi= argmaxk p(k|xi,(t),它是n1的CV_32C1形式。probs表示可选的输出矩阵,该矩阵为最终结果的后验概率p(k|xi, (t),它是nK的CV_32C1形式。 下面我们就分别给出这三个函数:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool EM:trainE(InputArray samples, InputArray _means0, InputArray _covs0, InputArray _weights0, OutputArray logLikelihoods, OutputArray labels, OutputArray probs) Mat samplesMat = samples.getMat(); /得到样本数据 vector covs0; /协方差矩阵 _covs0.getMatVector(covs0); /均值和权值因子 Mat means0 = _means0.getMat(), weights0 = _weights0.getMat(); /设置均值、权值因子、和协方差矩阵 setTrainData(START_E_STEP, samplesMat, 0, !_means0.empty() ? &means0 : 0, !_covs0.empty() ? &covs0 : 0, !_weights0.empty() ? &weights0 : 0); return doTrain(START_E_STEP, logLikelihoods, labels, probs); /进入EM算法 cpp view plain copy 在CODE上查看代码片派生到我的代码片bool EM:trainM(InputArray samples, InputArray _probs0, OutputArray logLikelihoods, OutputArray labels, OutputArray probs) Mat samplesMat = samples.getMat(); /得到样本数据 Mat probs0 = _probs0.getMat(); /得到后验概率 /设置后验概率 setTrainData(START_M_STEP, samplesMat, !_probs0.empty() ? &probs0 : 0, 0, 0, 0); return doTrain(START_M_STEP, logLikelihoods, labels, probs); /进入EM算法 我们重点讲解train函数:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool EM:train(InputArray samples, OutputArray logLikelihoods, OutputArray labels, OutputArray probs) Mat samplesMat = samples.getMat(); /得到样本矩阵 /调用setTrainData函数,设置训练用的数据,该函数在后面给出详细解释 /在train函数调用setTrainData函数,要设置第一个参数为START_AUTO_STEP,第二个参数为输入的样本矩阵,后四个参数probs0,means0,covs0和weights0,由于这四个参数在doTrain函数中是用k-means算法得到的,所以无需初始化,即设它们为0 setTrainData(START_AUTO_STEP, samplesMat, 0, 0, 0, 0); /调用doTrain函数,进入EM算法的迭代过程中,该函数在后面给出详细解释 /doTrain函数的第一个参数的含义与前一个setTrainData函数相同 return doTrain(START_AUTO_STEP, logLikelihoods, labels, probs); 设置训练样本数据:cpp view plain copy 在CODE上查看代码片派生到我的代码片void EM:setTrainData(int startStep, const Mat& samples, const Mat* probs0, const Mat* means0, const vector* covs0, const Mat* weights0) /startStep表示EM算法迭代是从E-Step和M-Step中的哪一步开始迭代,该参数用于区分是train函数,trainE函数还是trainM函数调用的它,如果是train函数调用的它,则该参数为START_AUTO_STEP,如果是trainE函数调用的它,则该参数为EM:START_E_STEP,如果是trainM函数调用的它,则该参数为EM:START_M_STEP /samples表示输入的样本 /probs0,means0,covs0和weights0分别为初始化的后验概率p(k|xi, (0),均值k,协方差矩阵k和权值因子k clear(); /清空一些全局变量 /检查样本数据和初始化参数是否正确 checkTrainData(startStep, samples, nclusters, covMatType, probs0, means0, covs0, weights0); /当startStep为START_AUTO_STEP,或者startStep为START_E_STEP并且没有初始化covs0或weights0时,isKMeansInit置1,表示需要用到k-means算法估计相应的初始化参数 bool isKMeansInit = (startStep = EM:START_AUTO_STEP) | (startStep = EM:START_E_STEP & (covs0 = 0 | weights0 = 0); / Set checked data /把samples复制为trainSamples,并根据isKMeansInit设置trainSamples的数据类型 preprocessSampleData(samples, trainSamples, isKMeansInit ? CV_32FC1 : CV_64FC1, false); / set probs /当初始化了probs0,并且startStep为EM:START_M_STEP时,需要设置probs参数 if(probs0 & startStep = EM:START_M_STEP) /把probs0复制为trainProbs,并使trainProbs的数据类型为CV_64FC1 preprocessSampleData(*probs0, trainProbs, CV_64FC1, true); /预处理初始化的后验概率值,使其归一化 preprocessProbability(trainProbs); / set weights /当初始化了weights0,并且startStep为EM:START_E_STEP且初始化了covs0时,需要设置weights0参数 if(weights0 & (startStep = EM:START_E_STEP & covs0) /转换数据类型为CV_64FC1 weights0-convertTo(weights, CV_64FC1); /把矩阵weights转换为1K的形式 weights.reshape(1,1); /预处理初始化的权值因子,使其归一化 preprocessProbability(weights); / set means /当初始化了means0,并且startStep为EM:START_E_STEP时,把means0复制为means,并根据isKMeansInit设置means的数据类型 if(means0 & (startStep = EM:START_E_STEP/* | startStep = EM:START_AUTO_STEP*/) means0-convertTo(means, isKMeansInit ? CV_32FC1 : CV_64FC1); / set covs /当初始化了covs0,并且startStep为EM:START_E_STEP且初始化了weights0时,需要设置covs if(covs0 & (startStep = EM:START_E_STEP & weights0) /covs为全局变量,被定义为vector类型,用于表示不同高斯成分的协方差矩阵的向量集,即Kdd covs.resize(nclusters); /设置covs的向量大小为K /复制,并且转换数据类型为CV_64FC1 for(size_t i = 0; i size(); i+) (*covs0)i.convertTo(covsi, CV_64FC1); 执行EM算法迭代:cpp view plain copy 在CODE上查看代码片派生到我的代码片bool EM:doTrain(int startStep, OutputArray logLikelihoods, OutputArray labels, OutputArray probs) /startStep表示EM算法迭代是从E-Step和M-Step中的哪一步开始迭代,该参数用于区分是train函数,trainE函数还是trainM函数调用的它,如果是train函数调用的它,则该参数为START_AUTO_STEP,如果是trainE函数调用的它,则该参数为EM:START_E_STEP,如果是trainM函数调用的它,则该参数为EM:START_M_STEP /logLikelihoods,labels,和probs分别为训练结束后输出得到的对数似然函数,类别标签和后验概率 int dim = trainSamples.cols; /得到样本特征属性的数量 / Precompute the empty initial train data in the cases of EM:START_E_STEP and START_AUTO_STEP /如果为EM:START_E_STEP或START_AUTO_STEP,并且在没有定义协方差矩阵的情况下,所需的初始化参数可以由k-means算法估计得到 if(startStep != EM:START_M_STEP) /确保在没有给出协方差矩阵covs的情况下,调用clusterTrainSamples函数,进行相关参数的k-means算法估计 if(covs.empty() CV_Assert(weights.empty(); /确保weights有值 clusterTrainSamples(); /该函数在后面给出详细的介绍 /在前面的clusterTrainSamples函数内,会调用decomposeCovs函数,下面if语句的作用是在前面没有执行clusterTrainSamples函数的情况下,调用decomposeCovs函数,也就是保证decomposeCovs函数一定要被调用一次,且只能是一次 if(!covs.empty() & covsEigenValues.empty() ) CV_Assert(invCovsEigenValues.empty(); decomposeCovs(); /该函数在后面给出详细的介绍 /如果是EM:START_M_STEP,需要先执行一次M-Step,由p(k|xi, (0)得到k(1),k(1)和k(1), if(startStep = EM:START_M_STEP) mStep(); /该函数在后面给出详细的介绍 / trainLogLikelihood和prevTrainLogLikelihood分别表示对数似然函数值和前一次迭代的对数似然函数值 double trainLogLikelihood, prevTrainLogLikelihood = 0.; for(int iter = 0; ; iter+) /进入EM算法的迭代 eStep(); /执行E-Step,该函数在后面给出详细的介绍 /得到该次迭代后的对数似然函数值 trainLogLikelihood = sum(trainLogLikelihoods)0; /如果超出了最大迭代次数,则退出EM算法的迭代 if(iter = maxIters - 1) break; /计算前后两次的对数似然函数值的差 double trainLogLikelihoodDelta = trainLogLikelihood - prevTrainLogLikelihood; /如果这个差值太小,说明已收敛,则退出EM迭代 if( iter != 0 & (trainLogLikelihoodDelta -DBL_EPSILON | trainLogLikelihoodDelta epsilon * std:fabs(trainLogLikelihood) break; mStep(); /执行M-Step,该函数在后面给出详细的介绍 prevTrainLogLikelihood = trainLogLikelihood; /更新上一次对数似然函数值 /如果对数似然函数是一个比较大的负数,说明EM算法计算不对,则退出函数 if( trainLogLikelihood = -DBL_MAX/10000. ) clear(); return false; / postprocess covs /后处理协方差矩阵,因为对于EM:COV_MAT_SPHERICAL和EM:COV_MAT_DIAGONAL类型,我们并没有真正得到协方差矩阵,而仅仅得到了它们的特征值,现在我们需要从特征值还原回协方差矩阵,它们的协方差矩阵都是对角线矩阵 covs.resize(nclusters); /定义大小 for(int clusterIndex = 0; clusterIndex nclusters; clusterIndex+) /遍历高斯成分 /EM:COV_MAT_SPHERICAL类型 if(covMatType = EM:COV_MAT_SPHERICAL) covsclusterIndex.create(dim, dim, CV_64FC1); /定义大小 /设置单位矩阵,即skI,sk为covsEigenValuesclusterIndex.at(0) setIdentity(covsclusterIndex, Scalar(covsEigenValuesclusterIndex.at(0); /EM:COV_MAT_DIAGONAL类型 else if(covMatType = EM:COV_MAT_DIAGONAL) /设置对角线矩阵,对角线上的元素为特征值 covsclusterIndex = Mat:diag(covsEigenValuesclusterIndex); /如果我们需要EM算法迭代后的类别标签、后验概率、对数似然函数,则复制相应的值 if(labels.needed() trainLabels.copyTo(labels); if(probs.needed() trainProbs.copyTo(probs); if(logLikelihoods.needed() trainLogLikelihoods.copyTo(logLikelihoods); /释放内存 trainSamples.release(); trainProbs.release(); trainLabels.release(); trainLogLikelihoods.release(); return true; /返回 执行k-means算法的参数估计:cpp view plain copy 在CODE上查看代码片派生到我的代码片void EM:clusterTrainSamples() int nsamples = trainSamples.rows; /得到样本的数量 / Cluster samples, compute/update means / Convert samples and means to 32F, because kmeans requires this type. /把样本和均值的数据类型转换为32F型 Mat trainSamplesFlt, meansFlt; if(trainSamples.type() != CV_32FC1) trainSamples.convertTo(trainSamplesFlt, CV_32FC1); else trainSamplesFlt = trainSamples; if(!means.empty() if(means.type() != CV_32FC1) means.convertTo(meansFlt, CV_32FC1); else meansFlt = means; Mat labels; /表示样本的分类标签 /调用kmeans函数,执行k-means算法 kmeans(trainSamplesFlt, nclusters, labels, TermCriteria(TermCriteria:COUNT, means.empty() ? 10 : 1, 0.5), 10, KMEANS_PP_CENTERS, meansFlt); / Convert samples and means back to 64F. /再次把样本和均值的数据类型转换回64F型 CV_Assert(meansFlt.type() = CV_32FC1); if(trainSamples.type() != CV_64FC1) Mat trainSamplesBuffer; trainSamplesFlt.convertTo(trainSamplesBuffer, CV_64FC1); trainSamples = trainSamplesBuffer; meansFlt.convertTo(means, CV_64FC1); / Compute weights and covs /定义权值因子weights的矩阵形式,大小为1K,数据类型为CV_64FC1,初始化为0 weights = Mat(1, nclusters, CV_64FC1, Scalar(0); covs.resize(nclusters); /covs的向量大小为K for(int clusterIndex = 0; clusterIndex nclusters; clusterIndex+) /遍历所有高斯成分 Mat clusterSamples; /表示某一高斯成分的样本 /遍历所有样本,对样本进行分类 for(int sampleIndex = 0; sampleIndex nsamples; sampleIndex+) /如果当前样本属于当前的高斯成分 if(labels.at(sampleIndex) = clusterIndex) const Mat sample = trainSamples.row(sampleIndex); /提取当前样本数据 clusterSamples.push_back(sample); /把当前样本放入clusterSamples中 CV_Assert(!clusterSamples.empty(); /确保当前高斯成分中有样本 /调用calcCovarMatrix函数,计算当前高斯成分的协方差矩阵和均值 calcCovarMatrix(clusterSamples, covsclusterIndex, means.row(clusterIndex), CV_COVAR_NORMAL + CV_COVAR_ROWS + CV_COVAR_USE_AVG + CV_COVAR_SCALE, CV_64FC1); /计算当前高斯成分的权值因子,等于当前高斯成分的样本数除以全部样本数 weights.at(clusterIndex) = static_cast(clusterSamples.rows)/static_cast(nsamples); /奇异值分解协方差矩阵,该函数在后面给出详细的介绍 decomposeCovs(); 奇异值分解协方差矩阵,得到特征值,和特征向量:cpp view plain copy 在CODE上查看代码片派生到我的代码片void EM:decomposeCovs() /covs为全局变量,数据类型为vector,表示不同高斯成分的协方差矩阵的向量集, CV_Assert(!covs.empty(); /确保covs不能为空 /covsEigenValues为全局变量,数据类型为vector,表示不同高斯成分的协方差矩阵的特征值矩阵(即式84中的W)的向量集,定义该向量集的大小为K covsEigenValues.resize(nclusters); /如果covMatType为EM:COV_MAT_GENERIC,则协方差矩阵的奇异值分解是用式84,它需要特征向量矩阵U if(covMatType = EM:COV_MAT_GENERIC) / covsRotateMats为全局变量,数据类型为vector,表示不同高斯成分的协方差矩阵的特征向量矩阵的向量集,定义该向量集的大小为K covsRotateMats.resize(nclusters); /invCovsEigenValues为全局变量,数据类型为vector,表示covsEigenValues的逆矩阵(即式85中的W-1)的向量集,定义该向量集的大小为K invCovsEigenValues.resize(nclusters); /遍历所有的高斯成分,计算每个高斯成分中协方差矩阵的特征值和特征向量 for(int clusterIndex = 0; clusterIndex nclusters; clusterIndex+) CV_Assert(!covsclusterIndex.empty(); /确保当前高斯成分的协方差矩阵有值 /执行SVD类,对当前高斯成分的协方差矩阵进行奇异值分解 SVD svd(covsclusterIndex, SVD:MODIFY_A + SVD:FULL_UV); /如果covMatType为EM:COV_MAT_SPHERICAL if(covMatType = EM:COV_MAT_SPHERICAL) /得到协方差矩阵的最大特征值 double maxSingularVal = svd.w.at(0); /在COV_MAT_SPHERICAL下,covsEigenValues大小为K11,covsEigenValuesclusterIndex存储最大特征值,即COV_MAT_SPHERICAL所需的标量sk covsEigenValuesclusterIndex = Mat(1, 1, CV_64FC1, Scalar(maxSingularVal); /如果covMatType为EM: COV_MAT_DIAGONAL else if(covMatType = EM:COV_MAT_DIAGONAL) covsEigenValuesclusterIndex = svd.w; /协方差矩阵的特征值矩阵 /如果covMatType为EM:COV_MAT_GENERIC else /EM:COV_MAT_GENERIC covsEigenValuesclusterIndex = svd.w; /协方差矩阵的特征值矩阵 covsRotateMatsclusterIndex = svd.u; /协方差矩阵的特征向量矩阵 /该语句的作用是避免特征值过小 max(covsEigenValuesclusterIndex, minEigenValue, covsEigenValuesclusterIndex); /得到invCovsEigenValues invCovsEigenValuesclusterIndex = 1./covsEigenValuesclusterIndex; 执行EM算法的E-Step,由k(t),k(t)和k(t),得到p(k|xi,(t):cpp view plain copy 在CODE上查看代码片派生到我的代码片void EM:eStep() / Compute probs_ik from means_k, covs_k and weights_k. /创建trainProbs,trainLabels和trainLogLikelihoods的大小,分别为nK,n1,n1,它们的含义分别为训练过程中得到后验概率、样本的类别标签和对数似然函数 trainProbs.create(trainSamples.rows, nclusters, CV_64FC1); trainLabels.create(trainSamples.rows, 1, CV_32SC1); trainLogLikelihoods.create(trainSamples.rows, 1, CV_64FC1); /得到式83中的lnk-ln(|k|)/2,该函数在后面给出详细的介绍 computeLogWeightDivDet(); /
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年湖南衡阳市公安局警务辅助人员招聘120人考前自测高频考点模拟试题及1套完整答案详解
- 2025江苏苏宿工业园区社区卫生服务招聘10人考前自测高频考点模拟试题及答案详解(历年真题)
- 2025贵州省科学技术协会招聘直属事业单位工作人员模拟试卷及答案详解(历年真题)
- 2025湖南长沙仲裁委员会调解员招聘100人考前自测高频考点模拟试题附答案详解
- 抗疫知识培训学习课件
- 企业售后服务服务标准化体系
- 2025广东中山市高校毕业生三支一扶计划招募60人模拟试卷及答案详解(夺冠)
- 2025年聊城幼儿师范学校公开招聘工作人员(70人)考前自测高频考点模拟试题(含答案详解)
- 2025江苏连云港经济技术开发区第二批招聘事业单位工作人员13人考前自测高频考点模拟试题有答案详解
- 2025福建厦门市集美区海凤实验幼儿园非在编人员招聘1人模拟试卷及答案详解(典优)
- (二模)2025年5月济南市高三高考针对性训练英语试卷(含答案解析)
- 舞蹈基本功课件
- 中国当代知名作家鲁迅生平介绍课件
- 古籍数字化与人工智能-全面剖析
- 高中体考笔试试题及答案
- 《资治通鉴》与为将之道知到课后答案智慧树章节测试答案2025年春武警指挥学院
- 2025年无线电装接工(中级)职业技能考试题(附答案)
- 2024年秋季新北师大版七年级上册数学全册教案设计
- (高清版)DB32∕T 4443-2023 罐区内在役危险化学品(常低压)储罐管理规范
- 医院培训课件:《输液泵》
- 量子通信金融应用研究报告
评论
0/150
提交评论