MATLAB进行模式识别的实验
一.实验一习题:我猜测是根据最大似然估计法先求出那两个参数的值,然后代入,得到的是只关于x的函数,然后把文本里的1000个数据导入,画图。首先,我先把txt的数据读取到矩阵里面,方便后续处理,用到的函数:(1).这里有一个比较详细的fopen的具体用法,本实验只需要fopen(‘name.txt’,‘rt’);//r是只读,t是以文本形式打开文件。(2)feof读取到文末结束:函数feof(fid
一.实验一习题:
我猜测是根据最大似然估计法先求出那两个参数的值,然后代入,得到的是只关于x的函数,然后把文本里的1000个数据导入,画图。
首先,我先把txt的数据读取到矩阵里面,方便后续处理,用到的函数:
(1).这里有一个比较详细的fopen的具体用法,本实验只需要fopen(‘name.txt’,‘rt’); //r是只读,t是以文本形式打开文件。
(2)feof读取到文末结束:
函数feof(fid) 用法:文件指针 fid 到达文件末尾时返回“真”值;否则返回“假”;
~feof 是在 feof 前加了“非”,是逻辑表达式:文件指针到达文件末尾时 该表达式值为“假”;否则为“真”;
用法简单来说就是:
while ~feof 表示 若 未读到文件末尾 则 继续 循环
while feof 表示 若 未读到文件末尾 则 终止 循环,所以只循环一次就终止
把数据读到矩阵里的代码:
第一种很简单:
fid = fopen('C:\Users\Administrator\Desktop\A.txt','rt');
sizeA =[1000 1];
data = fscanf(fid,'%f',sizeA);
第二种也还好:可以判断读取的数据是否为空,不读取为空的数据
k=0;
%如果数据为空,则不读取
if(fid == 0)
return
end
% 从第一个读取到最后一个数据
while~feof(fid) %读取到文件末尾则停止循环
curr =fscanf(fid,'%f',1);
if~isempty(curr)
k = k+1;
data(k) = curr;
end
end
clear k; %清除缓存
clear curr;
fclose(fid);
最终都能达到,把数据读取到data矩阵里面
然后第二部就是求两个参数的最大似然估计:
- 对 ln p(x)进行求和
- 用结果分别对两个参数求偏导数,并且计算等于0时另一个参数的数值
- 代入两个参数的数值,并且代入data里的数据,画图
写完之后一直报错,什么sym不正确之类的,查了查也没查明白,最后来回改了改试一试,发现
原因是,在让 f1函数 等于 f函数 的求和的步骤里,不能写成f1(a,th) = f1(a,th) + f(a,th)
要写成f1 = f1 + f(a,th) 就不报错了。。。。
然后就是求a和th数值的代码:
fid1 = fopen('C:\Users\Administrator\Desktop\A.txt','rt');
sizeA =[1000 1];
data = fscanf(fid1,'%f',sizeA);
k=0;
%如果数据为空,则不读取
if(fid1 == 0)
return
end
% 从第一个读取到最后一个数据
while~feof(fid1) %读取到文件末尾则停止循环
curr =fscanf(fid1,'%f',1);
if~isempty(curr)
k = k+1;
data(k) = curr;
end
end
clear curr;
clear fid;
clear k; %清除缓存
fclose(fid1);
for i = 1: 1000
x(i) = data(i); %数组
end
%x(1); %第一个数值
syms a th
for j = 1:1000
xj = data(j);
%p(x) = (ax(2*pi)^(1/2))^(-1) * exp (-((2*a^2)^(-1))* (lnx - th)^2);//函数
f(a,th) = log10((a * xj *(2*pi)^(1/2))^(-1) * exp (-((2*a^2)^(-1))* (log10(xj) - th)^2)); %外加ln
%这两段都是求和用的
if( j == 1)
f1 = f(a,th);
end
if( j~=1)
f1 = f1 + f(a,th);
end
end
[a,th]=solve([diff(f1,th)==0,diff(f1,a)==0 ],[a,th]); %分别求偏导数等于0,求两个参数
发现是个矩阵?
下一步是代入两个参量,然后画图,
实验一(2)正太分布的求法,其实都一样,只不过是p(x) 的式子变了。
因为想用txt里的数据去画图,而不是直接 x=1:10:100 这种方法去画图,于是先研究了把数据的散点图画出来,为了方便输入算式(主要是因为用matlab对正态分布的最大似然估计求偏导数过程中,操作代码有bug竟然求a出个负数于是放弃,直接手算求导再用matlab当作计算求和工具罢了)
%手动求导数,最终求出了u的算式,最大似然估计值为u,然后才有下面这步
sum = 0;
for n = 1:1000
sum = data(n) +sum ;
end
u = sum /1000;
%手动求导数,最终求出了a的算式,最大似然估计值为a_zhengtai,然后才有下面这步
zum = 0;
for k = 1:1000
zum = (data(k)-u)^2 + zum;
end
a_zhengtai = (zum/1000)^1/2;
%用lognpdf来画图,lognpdf是用来计算X中的元素在mu、sigma参数指定的对数正态分布下的概率密度函数值
for i =1:1000
x_zt = data(i);
y_zt = lognpdf(x_zt,u,a_zhengtai);
hold on
scatter(x_zt,y_zt);
% plotyy(x_zt,y_zt,'plot');这个是百度的,但是不知道怎么用,只画出一个点
plot(x_zt,y_zt,'-o');
end
结果为:
然后我想要把它们连成线,查了查
散点图如何绘制成连线图?
gplot的用法
简单总结就是 gplot(linjie_juzhen,XYCoords,’-or’);
1.
邻接矩阵就是一个nn的矩阵,比如说你用了1000个数据点,你就要有10001000的矩阵代表它们连接的关系,例如,第一个点和第二个点连接,同时第二个点也和第一个点连接,那么就赋值
linjie_juzhen(1,2) =linjie_juzhen(2,1) = 1
其他没有连接关系的两点值为0,例如 linjie_juzhen(3,5)=linjie_juzhen(5,3) = 0
假设这些点是从左到右依次画出来的,那么就让(i,j+1) 和(i,j-1)都等于0。
2.
XYCoords是n*2的矩阵,是点坐标(x,y)的从上到下排列
需要把这个矩阵的值写好。
可能用到的:矩阵的转置:A的转置用 A.’
3.
后面那一项就是表明连接的线的样式,上面的用法里有
yju=[1000,1];
for p = 1:1000
x_zt = data(p);
yju(p) = lognpdf(x_zt,u,a_zhengtai);
end
linjie_juzhen = [1000,1000]; %先定义好大小为1000*1000,但是这个是连接相邻节点的,如果不排序是不行的,因为txt里是乱的
for i =1: 1000
for j =1:1000
if(j == i+1 && j<=1000)
linjie_juzhen(i,j) = 1;
elseif(j == i-1 && j>=0)
linjie_juzhen(i,j) = 1;
else
linjie_juzhen(i,j+1) = 0;
end
end
end
XYCoords = [1000,2];
for i =1:1000
for j =1:2
if(j==1)
XYCoords(i,j) = data(i);
end
if(j == 2)
XYCoords(i,j) = yju(i);
end
end
end
gplot(linjie_juzhen,XYCoords,'-or');
结果为:
很明显,数据的自变量并不是从小到大依次排列的。。
然后下面的就懒得做了。。
更多推荐
所有评论(0)