首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Kmeans算法学习与SparkMlLib Kmeans算法尝试

K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。该算法接受参数 k ;然后将事先输入的n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。 算法描述: 假设要把样本集分为c个类别,算法描述如下: (1)适当选择c个类的初始中心; (2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类; (3)利用均值等方法更新该类的中心值; (4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。 该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。 ,暂且抛开原始数据是什么形式,假设我们已经将其映射到了一个欧几里德空间上,映射到欧几里得空间上,样例: 从数据点的大致形状可以看出它们大致聚为三个聚类 ,其中两个紧凑一些,剩下那个松散一些。我们的目的是为这些数据分组,以便能区分出属于不同的簇的数据,如果按照分组给它们标上不同的颜色,就是这个样子: 算法的流程: 首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数. k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。 那么样例模板: package main.asiainfo.coc.sparkMLlib import org.apache.spark.mllib.clustering.KMeansimport org.apache.spark.mllib.linalg.Vectorsimport org.apache.spark.{SparkConf, SparkContext} /** * Created by root on 12/15/15. */object kmeans { def main(args: Array[String]): Unit = { val sparkConf = new SparkConf().setMaster("local").setAppName("cocapp") val sc = new SparkContext(sparkConf) // 装载数据集 val data = sc.textFile("/usr/local/spark-1.4.0-bin-2.5.0-cdh5.2.1/ysy.txt") val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))) // 将数据集聚类,2个类,20次迭代,进行模型训练形成数据模型 val numClusters = 2 val numIterations = 20 val model = KMeans.train(parsedData, numClusters, numIterations) // 打印数据模型的中心点 println("Cluster centers:") for (c <- model.clusterCenters) { println(" " + c.toString) } // 使用误差平方之和来评估数据模型 val cost = model.computeCost(parsedData) println("Within Set Sum of Squared Errors = " + cost) // 交叉评估1,只返回结果 val testdata = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))) val result1 = model.predict(testdata) result1.foreach(println) println("-----------------------") // 交叉评估2,返回数据集和结果 val result2 = data.map { line => val linevectore = Vectors.dense(line.split(' ').map(_.toDouble)) val prediction = model.predict(linevectore) line + " " + prediction } result2.foreach(println) sc.stop() }} 数据模型的中心点: 使用误差平方之和来评估数据模型: 交叉评估1和2:

优秀的个人博客,低调大师

Mahout学习之命令行创建序列文件

一:命令行转换 创建新的工作目录 mkdir lastfm mkdir ./lastfm/original export WORK_DIR=/home/thinkgamer/document/lastfm cd $WORK_DIR 自己准备一个数据集放在original文件夹下,例如将点击打开链接下边的数据保存在synthetic_control.data中进行转换,首先将其放在origiinal文件夹中 进入mahout的安装目录,前提是hadoop环境是启动的 cd /usr/local/hadoop/mahout bin/mahout seqdirectory -i $WORK_DIR/original -o $WORK_DIR/sequencesfile 然后进入$WORK_DIR目录下有一个sequencesfile文件夹 cd $WORK_DIR cd sequencesfile ls 会显示如下: part-m-00000 _SUCCESS 命令行查看part-m-00000的文件内容为: bin/mahout seqdumper -i $WORK_DIR/sequencesfile/part-m-00000 | more0 二:mapreduce转换 具体请参考mahout运行canopy程序中的程序:点击打开链接 三:命令行转换为文本文件 bin/mahout seqdumper -i $WORK_DIR/sequencesfile/part-m-00000 -o $WORK_DIR/clusteranalyzer mahout版本不同如果上边的不好使,换用下边的 bin/mahout seqdumper -s $WORK_DIR/sequencesfile/part-m-00000 -o $WORK_DIR/clusteranalyzer

优秀的个人博客,低调大师

HBase学习总结(2):HBase介绍及其基本操作

(HBase是一种数据库:Hadoop数据库,它是一种NoSQL存储系统,专门设计用来快速随机读写大规模数据。在已成功安装并正常启动的前提下,本文介绍HBase的基本操作。) 一、HBase简介 什么是HBase(Hadoop Database)呢?有以下两种常见的说法: 第一,它是一种稀疏的、分布式的、持久化的、多维有序映射,它基于行键(row key)、列键(column key)和时间戳(timestamp)建立索引。 第二,它是一种键值(key value)存储,面向列族的数据库,有时也是一种存储多时间戳版本映射的数据库。 以上两种描述都是对的。但从根本上来说,HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,是一个可以随机访问的存储和检索数据的平台。大家可以按照需要写入数据,然后再按照需要读取数据。 HBase有如下特点: 第一,它不介意数据类型,允许动态的、灵活的数据模型,并不限制存储的数据的种类。因此,它可以自如地存储结构化和半结构化的数据。 第二,它不用SQL语言,也不强调数据之间的关系。 第三,它不允许跨行的事务,可以在一行的某一列存储一个整数,而在另一行的同一列存储字符串。 第四,它被设计成在一个服务器集群上运行,而不是单台服务器。这意味着一种强大的、可扩展的数据的使用方式。 从HBase的特点可以看出,HBase的设计与目标都与传统的关系型数据库不同。 二、HBase的基本操作 在已成功安装并正常启动HBase的前提下,我们可以使用HBase Shell,通过命令行方式与HBase进行交互。 1.启动HBase Shell 转到HBase解压包的“bin”目录下,使用命令“./hbase shell”或“sh hbase shell”命令即可启动HBase Shell。启动之后的信息如下: HBase Shell; enter 'help<RETURN>' for list of supported commands. Type "exit<RETURN>" to leave the HBase Shell Version 1.0.1, r66a93c09df3b12ff7b86c39bc8475c60e15af82d, Fri Apr 17 22:14:06 PDT 2015 hbase(main):001:0> 为了验证HBase是否安装成功,我们可以输入“list”查看HBase中所有的表。该命令的执行情况如下: hbase(main):001:0> list TABLE 0 row(s) in 0.2390 seconds => [] 由于是首次登录,因此HBase中包含了0个表。 2.创建表 HBase使用表作为顶级结构来存储数据,写数据到HBase,也就是写数据到表。下面创建一个有一个列族(“cf”)的表“mytable”: hbase(main):002:0> create 'mytable', 'cf' 0 row(s) in 0.3250 seconds => Hbase::Table - mytable hbase(main):003:0> list TABLE mytable 1 row(s) in 0.0090 seconds => ["mytable"] 使用“list”命令,我们可以看到,表创建成功。 3.写数据 表创建好之后,就需要写入一些数据。例如,我们想往表里写入“hello hbase”,那么我们就在“mytable”表的“first”行中的“cf:info”列对应的数据单元中插入“hello hbase”。命令执行如下: hbase(main):004:0> put 'mytable', 'first', 'cf:info', 'hello hbase' 0 row(s) in 0.0970 seconds 我们还可以继续多增加几个值,如下: hbase(main):005:0> put 'mytable', 'second', 'cf:name', 'zhou' 0 row(s) in 0.0180 seconds hbase(main):006:0> put 'mytable', 'third', 'cf:nation', 'China' 0 row(s) in 0.0080 seconds 现在表里面有3行和3个数据单元。在使用列的时候,大家并没有提前定义这些列,也没有定义往每个列中存储的数据类型。因此,HBase是一种无模式的数据库。 4.读数据 HBase有两种方式读取数据:get和scan。get方式可以读取一行的数据信息,scan方式可以读取表中所有行的数据信息。 get命令执行如下: hbase(main):008:0> get 'mytable', 'first' COLUMN CELL cf:info timestamp=1435548279711, value=hello hbase 1 row(s) in 0.0770 seconds 该命令输出了该行所有的数据单元。 scan命令执行如下: hbase(main):009:0> scan 'mytable' ROW COLUMN+CELL first column=cf:info, timestamp=1435548279711, value=hello hbase second column=cf:name, timestamp=1435548751549, value=zhou third column=cf:nation, timestamp=1435548760826, value=China 3 row(s) in 0.0320 seconds 该命令返回了所有数据。HBase返回行的顺序,是按照行的名字排序的。HBase称之为行键(rowkey)。 5.删除表 要想删除一张表,需要先将其“disable”掉,然后再“drop”掉。命令执行如下: hbase(main):010:0> disable 'mytable' 0 row(s) in 1.2380 seconds hbase(main):011:0> drop 'mytable' 0 row(s) in 0.1770 seconds hbase(main):012:0> list TABLE 0 row(s) in 0.0070 seconds => [] HBase还有很多技巧,但是其他所有的东西都是建立在上面那些基本操作基础之上的。大家一定要好好体会。 本人微信公众号:zhouzxi,请扫描以下二维码:

优秀的个人博客,低调大师

PCA人脸识别学习及C语言实现

人脸识别主要方法: .Eigenfaces,PCA(Principal Component Analysis),Turk and Pentland,1991 .Fisherfaces,LDA(Linear Discriminant Analysis),Belhumeur, Hespanha and Kriegman,1997 .LBPH,Local Binary Pattern Histograms,Ahonen, Hadid and Pietikäinen,2004 本文的目的,是结合人脸识别体验一把PCA,体会其内涵:降维。另外文献说,PCA的识别效果一般比神经网络ANN好。本文有20张人脸用于训练,10张人脸用于测试。 训练样本和测试样本来自:http://cswww.essex.ac.uk/mv/allfaces/faces94.zip 1.PCA人脸识别方法 将PCA方法用于人脸识别,其实是假设所有的人脸都处于一个低维线性空间,而且不同的人脸在这个空间中具有可分性。其具体做法是由高维 图像空间经PCA变换后得到一组新的正交基,对这些正交基做一定的取舍,保留其中的一部分生成低维的人脸空间,也即是人脸的特征子空间。PCA人脸识别算法步骤包括: a.人脸图像预处理 【我没做,人脸大小都是高200,宽180】 b.读入人脸库,训练形成特征子空间 【特征值、特征向量的求法,采用我上一篇文章的QR算法】 c.把训练图像和测试图像投影到上一步骤中的特征子空间上 【矩阵相乘】 d.选择一定的距离函数进行判别 【欧氏距离,挑最小的匹配】 2.PCA人脸识别流程 a.读入人脸库,读入每一个二维的人脸图像并转化为一维的向量,每个人选定一定数量的人脸照片构成训练集【共20张】,则训练集是一个36000*20的矩阵。测试集共10张图像,每次选一张,则测试集是一个36000*1的矩阵。 样本集: 测试集: 代码: void load_data(double *T,IplImage *src,int k) { int i,j; //一副图像压缩成一维的,存在T的一列里 for (i=0;i<IMG_HEIGHT;i++) { for (j=0;j<IMG_WIDTH;j++) { T[(i*IMG_WIDTH+j)*TRAIN_NUM+k-1]= (double)(unsigned char)src->imageData[i*IMG_WIDTH+j]; } } } b.计算 PCA变换的生成矩阵Q。首先计算训练集的协方差矩阵X,其中x1,x2,...,xn为第i副图像的描述,即xi为一个36000*1的列向量。 , 由于这个矩阵太大36000*36000,求特征值和特征向量比较坑,所以改为求P=XTX的特征向量和特征值,且有如下性质: 设e是矩阵P的特征值λ对应的特征向量,则有: 这里,X*e也是矩阵Q的特征值λ对应的特征向量,可以如此变换。 代码: void calc_mean(double *T,double *m) { int i,j; double temp; for (i=0;i<IMG_WIDTH*IMG_HEIGHT;i++) { temp=0; for (j=0;j<TRAIN_NUM;j++) { temp = temp + T[i*TRAIN_NUM+j]; } m[i] = temp/TRAIN_NUM; } } void calc_covariance_matrix(double *T,double *L,double *m) { int i,j,k; double *T1; //T = T -m for (i=0;i<IMG_WIDTH*IMG_HEIGHT;i++) { for (j=0;j<TRAIN_NUM;j++) { T[i*TRAIN_NUM+j] = T[i*TRAIN_NUM+j] - m[i]; } } T1 = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*TRAIN_NUM); //L = T' * T matrix_reverse(T,T1,IMG_WIDTH*IMG_HEIGHT,TRAIN_NUM); matrix_mutil(L,T1,T,TRAIN_NUM,IMG_HEIGHT*IMG_WIDTH,TRAIN_NUM); free(T1); } c.计算生成矩阵P的特征值和特征向量,并挑选合适的特征值和特征向量,构造特征子空间变化矩阵。这里P是实对称矩阵,可以采用上一篇的方法,先进行Household变换将P变成三对角矩阵,然后使用QR迭代算法求解特征值和特征向量,迭代次数60,误差eps=0.000001,代码: void cstrq(double a[],int n,double q[],double b[],double c[]) { int i,j,k,u,v; double h,f,g,h2; for (i=0; i<=n-1; i++) for (j=0; j<=n-1; j++) { u=i*n+j; q[u]=a[u];} for (i=n-1; i>=1; i--) { h=0.0; if (i>1) for (k=0; k<=i-1; k++) { u=i*n+k; h=h+q[u]*q[u];} if (h+1.0==1.0) { c[i]=0.0; if (i==1) c[i]=q[i*n+i-1]; b[i]=0.0; } else { c[i]=sqrt(h); u=i*n+i-1; if (q[u]>0.0) c[i]=-c[i]; h=h-q[u]*c[i]; q[u]=q[u]-c[i]; f=0.0; for (j=0; j<=i-1; j++) { q[j*n+i]=q[i*n+j]/h; g=0.0; for (k=0; k<=j; k++) g=g+q[j*n+k]*q[i*n+k]; if (j+1<=i-1) for (k=j+1; k<=i-1; k++) g=g+q[k*n+j]*q[i*n+k]; c[j]=g/h; f=f+g*q[j*n+i]; } h2=f/(h+h); for (j=0; j<=i-1; j++) { f=q[i*n+j]; g=c[j]-h2*f; c[j]=g; for (k=0; k<=j; k++) { u=j*n+k; q[u]=q[u]-f*c[k]-g*q[i*n+k]; } } b[i]=h; } } for (i=0; i<=n-2; i++) c[i]=c[i+1]; c[n-1]=0.0; b[0]=0.0; for (i=0; i<=n-1; i++) { if ((b[i]!=0.0)&&(i-1>=0)) for (j=0; j<=i-1; j++) { g=0.0; for (k=0; k<=i-1; k++) g=g+q[i*n+k]*q[k*n+j]; for (k=0; k<=i-1; k++) { u=k*n+j; q[u]=q[u]-g*q[k*n+i]; } } u=i*n+i; b[i]=q[u]; q[u]=1.0; if (i-1>=0) for (j=0; j<=i-1; j++) { q[i*n+j]=0.0; q[j*n+i]=0.0;} } return; } //q:特征向量,b:特征值 int csstq(int n,double b[],double c[],double q[],double eps,int l) { int i,j,k,m,it,u,v; double d,f,h,g,p,r,e,s; c[n-1]=0.0; d=0.0; f=0.0; for (j=0; j<=n-1; j++) { it=0; h=eps*(fabs(b[j])+fabs(c[j])); if (h>d) d=h; m=j; while ((m<=n-1)&&(fabs(c[m])>d)) m=m+1; if (m!=j) { do { if (it==l) { printf("fail\n"); return(-1); } it=it+1; g=b[j]; p=(b[j+1]-g)/(2.0*c[j]); r=sqrt(p*p+1.0); if (p>=0.0) b[j]=c[j]/(p+r); else b[j]=c[j]/(p-r); h=g-b[j]; for (i=j+1; i<=n-1; i++) b[i]=b[i]-h; f=f+h; p=b[m]; e=1.0; s=0.0; for (i=m-1; i>=j; i--) { g=e*c[i]; h=e*p; if (fabs(p)>=fabs(c[i])) { e=c[i]/p; r=sqrt(e*e+1.0); c[i+1]=s*p*r; s=e/r; e=1.0/r; } else { e=p/c[i]; r=sqrt(e*e+1.0); c[i+1]=s*c[i]*r; s=1.0/r; e=e/r; } p=e*b[i]-s*g; b[i+1]=h+s*(e*g+s*b[i]); for (k=0; k<=n-1; k++) { u=k*n+i+1; v=u-1; h=q[u]; q[u]=s*q[v]+e*h; q[v]=e*q[v]-s*h; } } c[j]=s*p; b[j]=e*p; } while (fabs(c[j])>d); } b[j]=b[j]+f; } for (i=0; i<=n-1; i++) { k=i; p=b[i]; if (i+1<=n-1) { j=i+1; while ((j<=n-1)&&(b[j]<=p)) { k=j; p=b[j]; j=j+1;} } if (k!=i) { b[k]=b[i]; b[i]=p; for (j=0; j<=n-1; j++) { u=j*n+i; v=j*n+k; p=q[u]; q[u]=q[v]; q[v]=p; } } } return(1); } void matrix_reverse(double *src,double *dest,int row,int col) //转置 { int i,j; for(i = 0;i < col;i++) { for(j = 0;j < row;j++) { dest[i * row + j] = src[j * col + i]; } } } void matrix_mutil(double *c,double *a,double *b,int x,int y,int z) //矩阵乘法 { int i,j,k; for (i=0;i<x;i++) { for (k=0;k<z;k++) { for (j=0;j<y;j++) { c[i*z+k] +=a[i*y+j]*b[j*z+k]; } } } } 挑选合适的特征值和特征向量,其实就是挑特征值大于1的【关于挑选,可以排序选前k个,也可以设阈值】: void pick_eignevalue(double *b,double *q,double *p_q,int num_q) { int i,j,k; k=0;//p_q的列 for (i=0;i<TRAIN_NUM;i++)//col { if (b[i]>1) { for (j=0;j<TRAIN_NUM;j++)//row { p_q[j*num_q+k] = q[j*TRAIN_NUM+i];//按列访问q,按列存储到p_q } k++; } } } d.把训练图像和测试图像投影到特征空间中。每一幅人脸图像投影到子空间以后,就对应与子空间的一个点。同样,子空间中的任一点也对应于一副图像。这些子空间的点在重构以后的图像很像人脸,所以他们被成为特征脸Eigenface。有了这样一个由特征脸组成的降维子空间,任何一副人脸图像都可以向其做投影并获得一组坐标系数,这组系数表明了该图像在子空间中的位置,这样原来的人脸图像识别问题就转化为依据子空间的训练样本点进行分类的问题。 【非必要步骤,特征脸如何重构,即 X*e,X大小为36000*20,e大小为20*k,每次只需将36000行的一列数据按照图像大小按行存储即可,这样就有k张特征脸图像】: double *temp; IplImage *projected; char res[20]={0}; //file name temp = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*num_q);//按列存取 projected = cvCreateImage(cvSize(IMG_WIDTH,IMG_HEIGHT),IPL_DEPTH_8U,1); //求特征脸 matrix_mutil(temp,T,p_q,IMG_WIDTH*IMG_HEIGHT,TRAIN_NUM,num_q); for (i=0;i<num_q;i++) { sprintf(res,"%d.jpg",i); for (j=0;j<IMG_HEIGHT;j++) { for (k=0;k<IMG_WIDTH;k++) { projected->imageData[j*IMG_WIDTH+k] = (unsigned char)abs(temp[(j*IMG_WIDTH+k)*num_q+i]); } } cvSaveImage(res,projected); } 结果: 回到原题,我们已经对P使用QR算法求的特征向量和特征值,通过X*e得到了Q的特征向量eigenvector大小36000*k,它构成了降维子空间。接下来,分别让样本集和测试集的图像投影到该子空间中,即:eigenvector ' * X 等等,然后得到一组坐标系数。 计算Q的特征向量和样本集像子空间投影的代码: void get_eigenface(double *p_q,double *T,int num_q,double *projected_train,double *eigenvector) { double *temp; double tmp; int i,j,k; //IplImage *projected; //char res[20]={0}; //file name projected = cvCreateImage(cvSize(IMG_WIDTH,IMG_HEIGHT),IPL_DEPTH_8U,1); //temp = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*num_q);//按列存取 memset(eigenvector,0,sizeof(double)*IMG_HEIGHT*IMG_WIDTH*num_q); memset(projected_train,0,sizeof(double)*TRAIN_NUM*num_q); //求特征脸 //matrix_mutil(temp,T,p_q,IMG_WIDTH*IMG_HEIGHT,TRAIN_NUM,num_q); /*for (i=0;i<num_q;i++) { sprintf(res,"%d.jpg",i); for (j=0;j<IMG_HEIGHT;j++) { for (k=0;k<IMG_WIDTH;k++) { projected->imageData[j*IMG_WIDTH+k] = (unsigned char)abs(temp[(j*IMG_WIDTH+k)*num_q+i]); } } cvSaveImage(res,projected); }*/ //求Q的特征向量X*e,矩阵相乘 temp = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*num_q); matrix_mutil(temp,T,p_q,IMG_HEIGHT*IMG_WIDTH,TRAIN_NUM,num_q); //投影到子空间 matrix_reverse(temp,eigenvector,IMG_WIDTH*IMG_HEIGHT,num_q); matrix_mutil(projected_train,eigenvector,T,num_q,IMG_WIDTH*IMG_HEIGHT,TRAIN_NUM); free(temp); } 读取测试图像,并投影到子空间的代码: //读取测试图像 test_img = cvLoadImage(".\\TestDatabase\\4.jpg",CV_LOAD_IMAGE_GRAYSCALE); projected_test = (double *)malloc(sizeof(double)*num_q*1);//在特征空间投影后的测试样本 for (i=0;i<IMG_HEIGHT;i++) { for (j=0;j<IMG_WIDTH;j++) { T_test[i*IMG_WIDTH+j] = (double)(unsigned char)test_img->imageData[i*IMG_WIDTH+j] - m[i*IMG_WIDTH+j]; } } //将待测数据投影到特征空间 memset(projected_test,0,sizeof(double)*num_q); matrix_mutil(projected_test,eigenvector,T_test,num_q,IMG_WIDTH*IMG_HEIGHT,1); e.把投影到特征子空间中的测试图像和样本集进行比较,确定待识别样本所属类别。本文使用欧氏距离计算坐标之间的距离: //计算projected_test与projected_train中每个向量的欧氏距离 Euc_dist = (double *)malloc(sizeof(double)*TRAIN_NUM); for (i=0;i<TRAIN_NUM;i++) { temp = 0; for (j=0;j<num_q;j++) { temp = temp + (projected_test[j]-projected_train[j*TRAIN_NUM+i])*(projected_test[j]-projected_train[j*TRAIN_NUM+i]); } Euc_dist[i] = temp; //printf("%f \n",temp); } //寻找最小距离 double min = Euc_dist[0]; int label; for (i=0;i<TRAIN_NUM;i++) { if (min>=Euc_dist[i]) { min = Euc_dist[i]; label = i; } } printf("%d.jpg is mathcing!",label+1); 实验结果: 即测试集中的4.jpg和样本集中的7.jpg对应匹配 下面给出主函数及各个头文件声明: My_Matrix.h: #include <math.h> #include <stdio.h> void cstrq(double a[],int n,double q[],double b[],double c[]); int csstq(int n,double b[],double c[],double q[],double eps,int l); void matrix_mutil(double *c,double *a,double *b,int x,int y,int z); void matrix_reverse(double *src,double *dest,int row,int col); Process.h: #include "cv.h" #include "highgui.h" #define TRAIN_NUM 20 #define IMG_HEIGHT 200 #define IMG_WIDTH 180 void load_data(double *T,IplImage *src,int k); void calc_mean(double *T,double *m); void calc_covariance_matrix(double *T,double *L,double *m); void pick_eignevalue(double *b,double *q,double *p_q,int num_q); void get_eigenface(double *p_q,double *T,int num_q,double *projected,double *eigenvector); main.cpp: // face_recognition.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "Process.h" #include "My_Matrix.h" int _tmain(int argc, _TCHAR* argv[]) { double *T,*L,*m,*b,*q,*c,*p_q,*projected_train,*T_test,*projected_test,*eigenvector,*Euc_dist; double eps,temp; int i,j,flag,iteration,num_q; char res[20]; IplImage *tmp_img,*test_img; T = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*TRAIN_NUM); //原始数据 T_test = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*1); //测试数据 m = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH); //平均值 L = (double *)malloc(sizeof(double)*TRAIN_NUM*TRAIN_NUM); //L=T'*T,协方差矩阵 b = (double *)malloc(sizeof(double)*TRAIN_NUM); //L的特征值 q = (double *)malloc(sizeof(double)*TRAIN_NUM*TRAIN_NUM); //L特征值对应的特征向量 c = (double *)malloc(sizeof(double)*TRAIN_NUM); //实对称三对角矩阵的次对角线元素 eps = 0.000001; memset(L,0,sizeof(double)*TRAIN_NUM*TRAIN_NUM); //存储图像数据到T矩阵 for (i=1;i<=TRAIN_NUM;i++) { sprintf(res,".\\TrainDatabase\\%d.jpg",i); tmp_img = cvLoadImage(res,CV_LOAD_IMAGE_GRAYSCALE); load_data(T,tmp_img,i); } //求T矩阵行的平均值 calc_mean(T,m); //构造协方差矩阵 calc_covariance_matrix(T,L,m); //求L的特征值,特征向量 iteration = 60; cstrq(L,TRAIN_NUM,q,b,c); flag = csstq(TRAIN_NUM,b,c,q,eps,iteration); //数组q中第j列为数组b中第j个特征值对应的特征向量 if (flag<0) { printf("fucking failed!\n"); }else { printf("success to get eigen value and vector\n"); } //对L挑选合适的特征值,过滤特征向量 num_q=0; for (i=0;i<TRAIN_NUM;i++) { if (b[i]>1) { num_q++; } } p_q = (double *)malloc(sizeof(double)*TRAIN_NUM*TRAIN_NUM); //挑选后的L的特征向量,仅过滤,未排序 projected_train = (double *)malloc(sizeof(double)*TRAIN_NUM*num_q); //投影后的训练样本特征空间 eigenvector = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*num_q);//Pe=λe,Q(Xe)=λ(Xe),投影变换向量 pick_eignevalue(b,q,p_q,num_q); get_eigenface(p_q,T,num_q,projected_train,eigenvector); //读取测试图像 test_img = cvLoadImage(".\\TestDatabase\\4.jpg",CV_LOAD_IMAGE_GRAYSCALE); projected_test = (double *)malloc(sizeof(double)*num_q*1);//在特征空间投影后的测试样本 for (i=0;i<IMG_HEIGHT;i++) { for (j=0;j<IMG_WIDTH;j++) { T_test[i*IMG_WIDTH+j] = (double)(unsigned char)test_img->imageData[i*IMG_WIDTH+j] - m[i*IMG_WIDTH+j]; } } //将待测数据投影到特征空间 memset(projected_test,0,sizeof(double)*num_q); matrix_mutil(projected_test,eigenvector,T_test,num_q,IMG_WIDTH*IMG_HEIGHT,1); //计算projected_test与projected_train中每个向量的欧氏距离 Euc_dist = (double *)malloc(sizeof(double)*TRAIN_NUM); for (i=0;i<TRAIN_NUM;i++) { temp = 0; for (j=0;j<num_q;j++) { temp = temp + (projected_test[j]-projected_train[j*TRAIN_NUM+i])*(projected_test[j]-projected_train[j*TRAIN_NUM+i]); } Euc_dist[i] = temp; //printf("%f \n",temp); } //寻找最小距离 double min = Euc_dist[0]; int label; for (i=0;i<TRAIN_NUM;i++) { if (min>=Euc_dist[i]) { min = Euc_dist[i]; label = i; } } printf("%d.jpg is mathcing!",label+1); return 0; } 这里面 ,矩阵操作有点头大,再梳理一遍: 1.将20副高200,宽180的图像,存入矩阵T中,36000*20 2.计算T的协方差矩阵L,20*20 3.求P的特征值b,20*1,特征向量q,20*20【q中的第j列向量即为b中第j个特征值对应的特征向量】,经过挑选后的特征向量num_q,20*k 4.构造特征子空间,即计算 T*p_q,得到eigenvector,36000*k,也是k副特征脸 5.将样本集图像投影到特征子空间,即计算eigenvector ' * T,得到一组坐标系数,projected_train,k*20,每一列为对应图像在子空间中的坐标 6.同理操作,得到测试图像在子空间中的坐标,projected_test,k*1 7.分别计算projected_tes和projected_train的坐标距离,选最小的匹配。 完整代码,下载地址:http://download.csdn.net/detail/jinshengtao/6870069

优秀的个人博客,低调大师

11 种值得学习的前沿编程语言:Mojo、MoonBit……

InfoWorld 整理了 11 种他们认为值得关注、以及值得花时间研究的前沿编程语言。其中有老牌语言,也有近两年才诞生的后起之秀。“即使这些新兴语言无法解决所有问题,但你仍然可以通过研究它们学到一些东西,并将它们应用于你目前常用的编程语言中。” 具体包括: Coq 其结构有助于处理具有复杂组合或具有大量限制或规则的多层级问题。它并不适合每个人或所有问题,但它是处理出现的一些更复杂问题的好方法。 Observable Observable 实际上是一种用于构建数据可视化展示或仪表板的机制。关键是你可以使用它将许多库和其他作为服务或 API 运行的代码包整合在一起。有些人可能称 Observable 为一种领域特定语言,官方文档将其描述为“framework”。或者我们应该将其视为“stack”——经过充分完善,各个模块可以相对和谐地运行,从而提供动态的遥测数据。 Plang Plang 的创造者们将大语言模型直接连接到编译器上,并安排它在无需等待用户剪切和粘贴代码的情况下运行代码。你只需要输入一些基本的、大致的指令,Plang 就会完成剩下的工作。“即使它不能完全解决问题,它也可能让你离目标只有10%的距离。” Python 超集:Mojo 和 Eng Mojo 和 Erg 是两种以 Python 为基础的语言,它们添加了静态类型和内存安全等额外功能,以加快最终产品的速度并使其更加强大。 这两种语言在重要方面有所不同。Erg 的团队实施了一项更复杂、更雄心勃勃的战略,同时也更加严格。这是一种希望进一步推动函数式编程的语言,因此它偏离了标准 Python 方法。 Mojo 更接近标准 Python,创建者似乎也瞄准了系统级工作。编译器对内存安全的关注增强了 Mojo 提供快速性能的能力,正如其网站所宣称的那样“可以一直扩展到底层硬件”。 AI 社区已经在许多应用中使用 Python,而 Mojo 希望支持更大模型所需的更高性能。这两种语言都是利用你的 Python 知识来应对更复杂任务的好方法。 Programming at the edge:MoonBit 和 Wing MoonBit 和 Wing 使得开发者更容易编写出快速启动并尽可能快地完成的可执行代码。 MoonBit 强调最终以 WebAssembly 形式交付的可执行文件的大小。它提供了一种轻量级的静态类型对象和函数方法的混合体,然后依靠智能编译器一次性优化整个程序,充分利用每个提高速度的机会。有些人将其描述为“data-oriented”,在这种情况下,这意味着它旨在处理无尽的字节流。 Wing 致力于帮助云编程人员,它提供许多抽象概念来处理云计算所需的琐事和繁琐工作。理想情况下,开发人员无需担心定义网络、身份管理和控制访问等问题。代码最终会被编译为 JavaScript,然后通过 JIT 编译器运行。 内存所有权:Rust、Zig、Jakt、Odin 和 Mojo 最近, Rust 等语言因其内存模型而备受关注,该模型为每个值赋予一个且只有一个 official owner。其他人可以通过“borrowing”来访问某个值,但控制权仍归 official owner 所有。当所有者被销毁时,内存就会被回收。 Rust 的这种内存管理方式有时被称为内存安全,有时也被称为“ownership and borrowing”。在其他语言中也有所体现,例如 Zig、Jakt、Odin 和 Mojo。所有这些语言都以它们最喜欢的语法呈现了内存所有权概念。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册