东北大学数据科学基础(MATLAB)-笔记
(本地用typora写的md笔记,导入图片得建一个picGo图床,嫌麻烦,所以如有需要带完整图片的笔记,参见:课件,参见:东北大学数据科学基础MATLAB学习PPT.zip)文章目录一. acknowledge重点:**画图**/MATLAB可视化技术三. 数模算法章(Matlab's *optimization* *tool* *box*,优化工具箱)1. 退火算法四.课程进度向量化编程&
(本地用typora写的md笔记,导入图片得建一个picGo图床,嫌麻烦,所以如有需要带完整图片的笔记,参见:
课件,参见:东北大学数据科学基础MATLAB学习PPT.zip)
一. 零散知识
- MATLAB用于编程,Typora提纲,Latex再编排(关于排版问题,github上有模板)
- 更多信息,吹爆:https://zhuanlan.zhihu.com/p/394139440
ipython
是一个python
的交互式shell
,比默认的python shell
好用得多,支持变量自动补全,自动缩进,支持bash shell
命令,内置了许多很有用的功能和函数。"i"指interactive,
MATLAB运算汇总设计到的运算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pCfoHbLD-1651042249324)(data:,)]
(要求:理解数学背景 和 算法原理,能利用它解决应用问题)
-
a=b’行列转换;a=1:5;b=1:2:10;生成向量linspace,数值的等间隔;logspace指数等间隔
-
广播,向量与矩阵相加
-
abs(),sqart(),exp(),reminder()
-
.mat文件的生成(内存变量文件)
-
矩阵:列优先
-
x = 1:5;等价于x=linespace(1,5,5)
-
单元矩阵:用大括号括起来:非单位矩阵
-
D = sub2ind(size(A),[1,2,2,2,],[1,1;3,2])与[i,j] = ind2sub([3,3],[1,3,5])
-
置空矩阵=删除元素;
-
reshape(x,3,4)
-
B= A(😃,将A元素堆叠起来,成为一个列向量’‘’''等价于reshape(A,6,1)
-
右除/,\左除(原 矩阵有乘法,且乘法不具有交换律,有逆运算,与此处除法? )
-
A^2
-
abs(‘MATLAB’)和double(‘MATLAB’)
-
1、.m文件:.m文件是保存一段代码的文件,类似于C语言中的一个函数体; 这也是MATLAB中最常见的文件保存格式之一。
2、.mat文件:.mat文件是MATLAB的数据存储的标准格式。也就是操作产生的数据的一个集合包,可以把一次处理的结果保存,供下一次使用。
-
MATLAB中两种类型的数据:
- 数值型数据
- 字符型数据(使用上用特殊性)
-
字符串:
>>xm='I''m a teacher.'//如果有 >>subch=ch(1:5) subch = I'm a %取倒序字符串 >>revch=ch(end:-1:1) revch = .rehcaet a m'I %小写变大写 >>k=find(ch>='a'&ch<='z') k = 3 5 7 8 9 10 11 12 13 14 >>ch(k)=ch(k)-('a'-'A')%{或者用32%} ch = I'M A TEACHER. %统计字符串中共小写字母的个数 length(k)
- 练习中明显发现了MATLAB语言更接近自然语言,其内置大量数以千计的函数,相当于让程序员帮我们完成了很多工作,其简洁性是以语言底层事先的冗余性为代价的;且更接近自然语言,决定了它相对运行效率低,有着同python等脚本语言,解释型语言类似的 语言规则随意性,故而其很多操作语句逻辑性不强,隐藏了极其复杂的底层实现;却新手友好!没有指针,引用,内存分配,平台无关
- MATLAB 是一个模型设计仿真工具,验证了模型之后,会再去用其它语言实现,这是一直以来 MATLAB 的工作模式;它缺少良好的软件工程文化,针对没有太多选择,且需要快速上手解决具体工程问题的非CS工科学生来说,是不得已也最完美的选择;但python也极其完美
- 在学习C,C++,Java之后,深刻明白了它们在工程领域的优越性!确实,越底层,学习曲线越陡峭,但越强大越可自定义.而MATLAB的便利性,这些偏底层的语言也已经通过 各种软件工程方法(如特定的框架,易于引用的外部方法库和jar包,智能IDE)
- 为了弥补这种解释型语言(写一句执行一句,一旦错了,就要全部重敲,还不能保存,且每次执行一个任务时敲入长长的命令序列是很烦人的。)有两种方法可以使MATLAB的力量得到扩展——脚本和函数。这两种方法都用像emacs一样的文本编辑器中编写的.m文件。m文件的好处在于它可以保存命令,还可以轻易地修改命令而无需重新敲入整个命令行。
-
MATLAB中三种注释方法
%该行被注释,不执行 %% 此部分作为自定义程序块,非常方便阅读 %% %{ 这 是 块注释 %}
-
">>"代表命令行提示符 后面还有.m文件,一次性运行
-
syms可以定义一些符号,用来进行符号运算,如:syms a=1/2,可以避免把a由1/2–>0.5;
-
syms是定义符号变量
sym是将字符或者数字转换为字符
比如
syms x y %就是定了符号变量x y以后x y就可以直接使用了,有他们运算出来的结果也是符号变量
当然上面的也可以x=sym(‘x’),y=sym(‘y’)
sys(‘a+b’)%就是将a+b转化为符号表达式
理解:syms S;
S=sum(sym(2).1)
syms与sym的选用,以得到S的精确值而非对数表示
%当然,S=sum(sym(2).2)也可以,因为右边运算的结果也是符号表达,S类型自然也会被MATLAB分配为符号变量.
%MATLAB真是门不严谨的语言啊,没有逻辑可言,全凭撸起袖子干
二. 重点:画图/MATLAB可视化技术
本章在数学建模中的美化,形象描述数据上具有重大作用!
(上课课件PPT(全面))[http://neucsecg.neu.edu.cn/userfiles/file/2020/1604300417168078858.pdf]
-
clear;clc; 清空工作区,并清屏
-
绘制
-
plot(x,y1,‘-b’,x,y2,‘-r’); 绘制二维直角坐标 plot(x,y,z) 绘制三维直角坐标
-
极坐标polar(x,y,‘-*’); 极坐标
-
-
mesh,surf绘制立体曲面
clear;clc;
[X,Y]=meshgrid(-4:0.1:4,-4:0.1:4);
Z=cos(X).*sin(Y);
surf(X,Y,Z) or mesh(X,Y,Z)xlabel(‘x’);
ylabel(‘Y’)
zlabel(‘T’) -
其他必知的操作:
-
在matlab figure界面中,可以找到tool,属性选择器,可以对camera,刻度等属性进行选择,该界面还可以生成代码
这些属性通过plot的各项属性(property)一样能实现
-
figure界面参数:
-
线性,描点类型,颜色参数
-
分隔:(当然,属性选择器中分隔属性选择后,生成代码即可)
-
- subplot绘制分隔
-
- axes绘制分隔
-
-
叠加绘图
hold on: 开启保持,之后的绘图将叠加显示
hold off: 关闭保持,之后的绘图将覆盖显示
-
点线式基本命令
-
函数绘图:
输入函数,写明定义域即可,自动对函数变化密集处密集取点,相当智能
fplot(@(x)sin(1./x),[0 0.1]);
-
特殊二维图形:
-
平面化绘图建议:
-
-
-
wordcloud技术:分析文件中各字符出现次数:中英文词频统计(MATLAB)
-
先学matlab,入门简单,处理直观,程序不复杂,没有python那么多条条框框。单纯从问题描述里说的各种数据处理,matlab的方便之处就无可替代。
缺点一就是文本处理始终没有python方便。这里指的是纯汉字或者英语那种,文件里都是数字或者excel文件的话读取和输出还是很方便的。
缺点二是想运行程序必须安装有matlab,动则10G。如果只是在一台电脑上运行,那就没什么问题。
等到有一定的熟练度以后,可以再学python。python门槛确实高于matlab,毕竟想要创建一个矩阵还要先导入numpy,画个图导入matplotlib,诸如此类等等,新手可能完全不懂,会陷入复杂的细节漩涡。所以才建议matlab学会后再入手,起码有个基础。
python优点在于用途广泛,免费。matlab能干的事python大部分也能干,无非就是略微复杂点。python能干的matlab也不一定能干,就是文本、文件处理方面。拓展性也更强。但是python的版本问题,以及各种数值类型等的bug确实也让人头疼,不建议纯新手学。
如果只学一个,那肯定是matlab。
如果想循序渐进,先matlab,再python是最好的选择。这个过程可以花几年的时间慢慢过渡,毕竟不管matlab还是python只是一个工具,当你的编程能力逐渐应付不了需求的时候,会自然而然学习更好的工具。
-
20210919,学会了如何应用MATLAB自带工具箱中的退火算法进行求解最小值(最大值) 模仿视频
-
矩阵范数
-
针对数 组,自定义函数:
%???????????0 sp=0 %????mc_pi????pi n=input('input:'); sp=mc_pi(n); %???????sp disp(sp) %??????????????(??) matrix=[0]; if n>100 for x=(n-100):5:n z=mc_pi(x); cat(1,matrix,z); end disp(matrix); sp1=std(matrix); disp('std='); disp(sp1); end function p=mc_pi(n) %??n????????p?????pi? %????????????pi s=0; for k=1:n x=rand(1); y=rand(1); if (x^2+y^2)<=1 s=s+1; end end p=s/n*4; end
由于y=z=mc_pi(x);其值不能为向量,含恨!!!
%???????????0 sp=0 %????mc_pi????pi n=input('input:'); sp=mc_pi(n); %???????sp disp(sp) %??????????????(??) matrix=[]; if n>100 for x=(n-100):5:n z=[mc_pi(x)]; cat(2,matrix,z); end disp(matrix); sp1=std(matrix); disp('std='); disp(sp1); end function p=mc_pi(n) %??n????????p?????pi? %????????????pi s=0; for k=1:n x=rand(1); y=rand(1); if (x^2+y^2)<=1 s=s+1; end end p=s/n*4; end
pseudoinverse 伪逆—>pinv
inverse逆—>inv
-
>> A[4,:]=[]
错误: 表达式无效。调用函数或对变量进行索引时,请使用圆括号。否
则,请检查不匹配的分隔符。WA!
>> A(4,:)=[]
AC!
>> A([1 2],:)=A([2 1,:]) %换行操作%
-
左除与右除
>> A/B*B %A右除B右乘B=A%
ans =
12.0000 34.0000 -4.0000
34.0000 7.0000 87.0000
3.0000 65.0000 7.0000>> B*(B\A) % B左乘(A左除B)=A%
ans =
12.0000 34.0000 -4.0000
34.0000 7.0000 87.0000
3.0000 65.0000 7.0000 -
对于.m文件,
A=[1,2,3;4,5,6]; B=[1,2,3;4,5,6]'; %有分号时无输出,无分号时有输出 C=A*B
-
MATLAB支持
function [x,y]= fun(y,x) end
但是
function [x,y]= fun(x,y) x=y; y=x; end %两个x无法区分
-
交换两行(列)
使用
a([n m],:)=a([m n],:) 1
其中m,n是需要交换的两行,列也同理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AiX7QaDZ-1651042249329)(C:\Users\31219\Documents\Typora Markdown\杂项\数据分析-MATLAB.assets\image-20211011204548821.png)]
(矩阵任意两个元素则不可交换位置,只能利用temp第三方,直接进行元素赋值来达成)
以及数组A 第k和k+1个元素交换位置:
A([k,k+1])=A([k+1,k]);
-
.mat文件:.mat文件是matlab的数据存储的标准格式。也就是操作产生的数据的一个集合包,可以把一次处理的结果保存,供下一次使用。与.m(既可以是脚本文件 也可以是函数文件)不同: 也与.mlx(实时代码or实时脚本文件)
-
for的循环体为矩阵时:
s=0; a=[2,3,4;5,6,7;8,9,10]; for k=a s=s+k; end disp(s)
运行结果(自己跑)证明是一列运行一次,就和运行向量(1*n矩阵)一样
-
if的条件为一个完全非0的矩阵时,条件成立
三. 数模算法章(Matlab’s optimization tool box,优化工具箱)
自带工具箱可直接通过app图形化界面调用
非自带工具箱
非自带工具箱,需另外下载,然后按照一定的步骤导入,导入后一般不能像上面工具箱一样,通过界面操作,一般都通过函数使用。由于工具箱的导入有几个小的细节需要注意,所以在我的其他经验中,关于如何导入工具箱,我也进行了详细的介绍MATLAB绘图:
1. 退火算法
算法特点
• 与遗传算法、粒子群优化算法和蚁群算法等不同,模拟退火算法不属于群优化算法,不需要初始化种群操作。• 收敛速度较慢。因为1)它初始温度一般设定得很高,而终止温度设定得低,这样才符合物体规律,认为物质处于最低能量平衡点;2)它接受恶化解,并不是全程都在收敛的过程中。这一点可以类比GA中的变异,使得它不是持续在收敛的,所以耗时更多一些。
• 温度管理(起始、终止温度)、退火速度(衰减函数)等对寻优结果均有影响。比如T的衰减速度如果太快,就会导致可能寻找不到全局最优解。
- SA算法的Metropolis准则允许接受一定的恶化解,具体来讲,是以一定概率来接受非最优解。举个例子,相当于保留一些“潜力股”,使解空间里有更多的可能性。对比轮盘赌法,从概率论来讲,它是对非最优解给予概率0,即全部抛弃。
四.课程进度
向量化编程&如何不使用for循环
1.求完数:除了本身外所有因数相加和为本身
m=100;
for k=2:m
cout=-k;
for l=1:sqrt(k)
if mod(k,l)==0
cout=cout+l+k/l;
end
end
if(cout==k)
disp('完数是:');
disp(k);
end
end
转换为向量化编程,关键在于累加
sum之累加是针对一个已有的向量而言的,然而这个向量还不存在,需要靠if ,for得到,而非一个已有的向量,如此,不还是要借助for循环吗?
敲代码寻方案
不用for的写法:
- 求pi值
syms k;
%因为和式含参数,而非一个向量,所以要用symsum,不能用sum
symsum((-1)^(k+1)/(2*k-1),1,inf)
可惜由于运算限制,得到了一个超几何函数!只能弃用这种方法
向量化编程:
n=input('input:');
k=1:n;
sum((-1).^(k+1)/(2.*k-1))*4
- 判断一个数是否为素数
一般思路:
m=input('input:');
%法一
~sum(rem(m,2:sqrt(m)))
%法二
isempty(rem(m,2:sqrt(m))
%法三
all(rem(m,2:sqrt(m))
-
如何将数组倒过来
行向量就用fliplr函数 列向量就用flipud函数
用fliplr,如
x=[1 2 3 4 5];
fliplr(x)
ans =54321 -
Lab2A:寻找二进制字符串中最长的“1”序列 %此处代码不可修改 s=input('请输入仅有0和1组成的二进制字符串','s'); %填写代码计算最长的1序列,即连续的1的长度 % 不能使用循环,结果存入y strs = split(s, '0'); %cellfun函数能对每一个元胞元素进行相同的操作,取每一个元胞元素的长度,并用max求最大值 y=max(cellfun(@length, strs)); disp(y); %显示结果y
n=input('请输入矩阵阶n');
A=fix(1000*rand(n));
%计算对角线上的连续素数个数
% 不使用循环,结果存入y
B=diag(A)'
bo=[0 isprime(B) 0]; %让起始和最后的元素与中间的操作统一
pos=find(bo==0);
jian=diff(pos)
y=max(jian-1);
disp(y)
-
向量化编程技巧:
-
将向量视为基本单位,对于’. + 运算符’能解决的问题,可以直接解决,这是最简单的一类:输入n个数,输出n个数
%% for n=1:10 n*5 end %% n=1:10; n.*5
-
需要涉及向量间元素的运算,这类问题往往需要借助 MATLAB现成函数来解决,这是较简单的一类:输入n个数,未必输出n个数
%% s=0; for k=1:10 s=1+k; end %% n=1:10; sum(n)
-
需要对向量单个元素进行判断的问题,这种问题中应用的技巧被称为masking,用矩阵切片代替判断
%% s=0; for k=1:10 if mod(k,2)==0; s=s+k; end %% %利用masking判断 n=1:10; n=n(mod(n,2)==0)
-
需要对矩阵元素进行某种函数运算,且该函数支持输入向量,那直接上就行,这是最简单的情况
%% judgement=[]; for k=1:10 judgement=[judgement,isprime(k)]; end %% %若该函数支持输入向量 judgement=[isprime(1:10)];
-
若该函数不支持输入向量(因为该函数的实现环节中有不支持向量的运算),则使用
%% %如果用strs=['1','2','3'],那strs将是字符串'123',而非 字符串组:'1','2','3' strs={'1','2','3'} %cell元胞数组的每个元素都是cell,可以存放不同类型的数据,取cell元胞数组的元素,可以用strs{1,2} for k=1:length(strs) length(strs(k)) end %% %利用fun系列函数cellfun来实现该功能 strs={'1','2','3'} cellfun(@length,strs);
fun系列函数:
bsxfun, arrayfun, cellfun, spfun, structfun
对自定义函数,如:f=@(x,y) x2+y2;
arrayfun(f,n)而不能用arrayfun(@f,n),否则无法识别f
对MATLAB现成函数,则带@
-
lab2A:寻找最长1序列
- 利用split切割连续的1序列,
- 再用cellfun对元胞元素进行求length操作,
- 用max求1序列长度最大值
元胞数组不能比较数组元素是否相等,但我们可以用strcmp(A, B)!
完整代码:
Lab2A:寻找二进制字符串中最长的“1”序列
%此处代码不可修改
s=input('请输入仅有0和1组成的二进制字符串','s');
%填写代码计算最长的1序列,即连续的1的长度
% 不能使用循环,结果存入y
strs = split(s, '0');
%cellfun函数能对每一个元胞元素进行相同的操作,取每一个元胞元素的长度,并用max求最大值
y=max(cellfun(@length, strs));
disp(y); %显示结果y
lab2B:找到n阶方阵中对角线上的连续素数个数
说明:详见代码:
Lab2B:找到n阶方阵中对角线上的连续素数个数
%此处代码不可修改
n=input('请输入矩阵阶n');
A=fix(1000*rand(n));
%计算对角线上的连续素数个数
% 不能使用循环,结果存入y
%求对角线,并转置
B=diag(A)'
s=isprime(B)
%将求得的10101...数组转换为字符数组
s=num2str(s);
%将s字符数组中的空格进行替换为空
s=strrep(s,' ','');
%对字符数组进行分割
s=split(s,'0');
%cellfun函数能对每一个元胞元素进行相同的操作,取每一个元胞元素的长度,并用max求最大值
y=max(cellfun(@length, s));
%此处代码不可修改
disp(y);
Lab2C:判定n是否为完数,并找到小于n的所有完数
运行结果:
代码:(说明见注释)
Lab2C:判定n是否为完数,并找到小于n的所有完数
%此处代码不可修改
n=input('请输入整数n');
% 判定n是否为完数
% 不能使用循环,结果存入s(保存logical值即可)
n1=1:n-1;
n1=n1(mod(n,n1)==0);
if sum(n1)==n
s=true;
else
s=false;
end
% 找到n以下的所有完数
% 不能使用循环,结果存入y
f=@(x)sum(divisors(x));
solvePerfectNumber=@(x)arrayfun(f,x);
%n以下,理解从1到n-1
n2=1:n-1;
y=n2(solvePerfectNumber(n2)==2*n2);
%此处代码不可修改
disp(s)
disp(y)
附加说明:
第一问判断n是否为完数时,也可用sum(divisors(x))直接求,但我采用了masking切片的方法(收qq群大佬启发)
在求0到100所以完数过程中, 由于
f=@(x)sum(divisors(x));
不支持直接输入数组进行运算,(由divisors源码得知,divisors函数只支持标量运算)
所以此处使用了arrayfun,以此对数组元素进行操作
这个求完数的方法,太妙了!divisors难以用在数组上,而这种主动sum(find(rem(k)==0))自己找因数,比我强太多,这就是基础啊
他妙在自定义函数f只对单个数进行处理,这样比对多个数进行处理棒多了
常规思路
f=@(x)sum(find(rem(x,1:x-1)==0)); //求所有因数的和
n=1:1000;
n=n(f(n)==n)//矩阵切片判断 代替 for循环if判断
但会报错:
错误使用 rem
矩阵维度必须一致。出错 @(x)sum(find(rem(x,1:x-1)==0))
因为f的实现决定了它不支持向量(或者叫一阶矩阵)的运算
于是引用arrayfun函数来处理
f=@(x)sum(find(rem(x,1:x-1)==0));
n=1:1000;
n=n(arrayfun(f,n)==n) //arrayfun(f,n)代替f(n)
or
f=@(x)sum(find(rem(x,1:x-1)==0))==x;
n=1:1000;
a=find(arrayfun(f,n)==1)
or
f=@(x)sum(find(rem(x,1:x-1)==0));
n=1:1000;
n=n(arrayfun(f,n)==n)
数据可视化
实验1.分区绘图
load carsmall
subplot(2,2,1);
histogram(MPG,Model_Year)
subplot(2,2,3);
boxplot(MPG,Model_Year)
subplot(1,2,2);
scatter(MPG,Model_Year,'k')选用了carmall的数组,绘制了MPG与Model_Year的关系
实验2:绘图标注
figure1 = figure;
axes1 = axes('Parent',figure1,...
'Position',[0.126057529610829 0.190058479532164 0.778942470389171 0.734941520467838]);
xlim(axes1,[-43.206190624563 44.6398093754371]);
ylim(axes1,[-130.488472719394 133.049527280606]);
hold(axes1,'on');
x=linspace(-30,30);
plot(x,x.*exp(sin(x)));
annotation(figure1,'textarrow',[0.455160744500846 0.456006768189509],...
[0.645153846153846 0.523076923076923],'String',{'y=x*exp(sin(x))'});
实验3:surf和mesh绘图surf:
[x,y]=meshgrid(-0.25:0.01:0.25,-0.25:0.01:0.25);
%以0.1为步长建立平面数据网格
r1=1./sqrt((x-0.3).^2+y.^2);
r2=1./sqrt((x+0.3).^2+y.^2);
V=1./(4*pi)/(8.854*10.^-12)*2*10^-10*(2./r1+4./r2);
surf(x,y,V)mesh:t = linspace(0,2*pi,20);
X = sin(t);
Y = cos(t);
Z = cos(2.*t);
surf(X,Y,Z);实验4三维点线图(含视角调整)
实验4三维点线图(含视角调整)
t = linspace(0,2*pi,20);
h = linspace(0,2, 20)';
X = sin(t);
Y = cos(t);
Z = cos(2.*t);
plot3(X,Y,Z);
view(-37.5,30);
实验5:实验动画绘图:
t = 0:0.005:6;
y=sin(2*pi*t);
plot(t,y)
hold on
index = 1;
scatter(t(index),y(index),'Marker','o','MarkerEdgeColor','blue');
for index=2:length(t)
hold on;
plot(t,y,'Color','blue')
pause(0.05);
scatter(t(index-1),y(index-1),'Marker','o','MarkerEdgeColor','white');
scatter(t(index),y(index),'Marker','o','MarkerEdgeColor','blue');
end
数据探索性分析
- 集中趋势&离中趋势
- 分布分析&频度分析
- 频度分析(周期性分析)
- 对比分析
- 相对数分析
- 相对数对比
- 数据变换(简单函数变换,规范化)
- 相关性分析(绘制散点图矩阵)
[m n]=size(gt.m1)
mt=[ones(m,n) gt.m1; 2.*ones(m,n) gt.m2; 3.*ones(m,n) gt.m3]
histogram2(mt(:,1),mt(:,2))
解释:
for i=2:1:6
cor = corrcoef(data(:,i),data(:,1)); >> corr(i) = cor(1,2); >> disp(['corrcoef of active power and data index ’ num2str(i) ‘ is ’ num2str(corr(i))]); >> end >>[m,index]=max(corr); >> disp(['the max corr is ’ num2str(index) ’ ’ num2str(m)]);
lab4:
1.housing数据导入工作区
2.人口相关数据显示
disp(['The maximum of population is ' num2str(max(housing.population))]);
disp(['The minimum of population is ' num2str(min(housing.population))]);
disp(['The mean of population is ' num2str(mean(housing.population))]);
3.人口直方图,50柱块
histogram(housing.population,50)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgyCesLn-1651042249343)(数据分析-MATLAB.assets/image-20211106142012167.png)]
4.查看地理位置(使用了地理气泡图)
histogram(housing.population,50)
5.查看total_bedrooms属性,将缺失值用中位数替代,并计算平均值
temp = housing.total_bedrooms; %用temp拷贝total_bedrooms
temp(isnan(temp(:,1)))=[]; %去掉temp中NaN数据
md=median(temp); %计算去掉无效数据后的中位数
housing.total_bedrooms(isnan(housing.total_bedrooms(:,1)))=md; %将total_bedrooms中的无效数据用该中位数替代
mean(housing.total_bedrooms) %计算替代缺失值后的平均值
6…数据集里有9 个属性都是数值类数据,请计算出median_house_value 和其他8 种属性的相关系数,然后根据结果指出和房价最为相关的属性是什么?
data = table2array(housing); %表转换为矩阵,这样进行协方差处理时才不会出错
for i=1:1:8 %比较除median_house_value外的八个数据与median_house_value的关系
cor = corrcoef(data(:,i),data(:,9));
corr(i) = cor(1,2);
disp(['corrcoef of housing property and data index ' num2str(i) ‘ is ' num2str(corr(i))]);
end
[m,index]=max(corr);
disp(['the max corr is ' num2str(index) ' ' num2str(m)]);
data index 8对应的属性是median_income,说明median_income与median_house_value最相关,也符合生活常识
MOOC作业:
1.对数据集进行离群值检测。
for k=1:1:3
subplot(2,2,k);
boxplot(table2array(car(:,k)));
end
subplot(2,2,4)
boxplot(table2array(car(:,5)));
2.鸢尾花数据集处理:
鸢尾花数据集是Matlab软件中自带的一个经典数据集。数据集中包含不同品种的花的四个形状指标:萼片长度、萼片宽度、花瓣长度、花瓣宽度。在Matlab 中使用load fisheriris命令加载数据集后,编写程序计算如下问题:
1)按species分离不同类别的样本;
2)计算各类别中4个指标的均值、方差、标准差、偏度、峰度等;
3)作出个指标数据直方图并检验该数据是否服从正态分布。
第(1)(2)问:
已经问过老师,第(1)(2)是一起的,按species分离不同类别的样本 指 运用向量化编程分别处理不同类别样本 :
代码:
for k=1:4
disp(['setosa类别中第' num2str(k) '个指标的均值、方差、标准差、偏度、峰度 :']);
f(meas(1:50,k));
disp(' ');
end
for k=1:4
disp(['versicolor类别中第' num2str(k) '个指标的均值、方差、标准差、偏度、峰度 :']);
f(meas(51:100,k));
disp(' ');
end
for k=1:4
disp(['virginica类别中第' num2str(k) '个指标的均值、方差、标准差、偏度、峰度 :']);
f(meas(101:150,k));
disp(' ');
end
运行结果:
setosa类别中第1个指标的均值、方差、标准差、偏度、峰度 :
均值是 5.006
方差是 0.12425
标准差是 0.35249
偏度是 0.11645
峰度是 2.6542
setosa类别中第2个指标的均值、方差、标准差、偏度、峰度 :
均值是 3.428
方差是 0.14369
标准差是 0.37906
偏度是 0.039921
峰度是 3.7442
setosa类别中第3个指标的均值、方差、标准差、偏度、峰度 :
均值是 1.462
方差是 0.030159
标准差是 0.17366
偏度是 0.10318
峰度是 3.8046
setosa类别中第4个指标的均值、方差、标准差、偏度、峰度 :
均值是 0.246
方差是 0.011106
标准差是 0.10539
偏度是 1.2159
峰度是 4.4343
versicolor类别中第1个指标的均值、方差、标准差、偏度、峰度 :
均值是 5.936
方差是 0.26643
标准差是 0.51617
偏度是 0.10219
峰度是 2.4012
versicolor类别中第2个指标的均值、方差、标准差、偏度、峰度 :
均值是 2.77
方差是 0.098469
标准差是 0.3138
偏度是 -0.35187
峰度是 2.5517
versicolor类别中第3个指标的均值、方差、标准差、偏度、峰度 :
均值是 4.26
方差是 0.22082
标准差是 0.46991
偏度是 -0.58816
峰度是 2.9256
versicolor类别中第4个指标的均值、方差、标准差、偏度、峰度 :
均值是 1.326
方差是 0.039106
标准差是 0.19775
偏度是 -0.030236
峰度是 2.5122
virginica类别中第1个指标的均值、方差、标准差、偏度、峰度 :
均值是 6.588
方差是 0.40434
标准差是 0.63588
偏度是 0.11444
峰度是 2.9121
virginica类别中第2个指标的均值、方差、标准差、偏度、峰度 :
均值是 2.974
方差是 0.104
标准差是 0.3225
偏度是 0.35488
峰度是 3.5198
virginica类别中第3个指标的均值、方差、标准差、偏度、峰度 :
均值是 5.552
方差是 0.30459
标准差是 0.55189
偏度是 0.53282
峰度是 2.7435
virginica类别中第4个指标的均值、方差、标准差、偏度、峰度 :
均值是 2.026
方差是 0.075433
标准差是 0.27465
偏度是 -0.12556
峰度是 2.3387
------
第(3)问:(共计4个指标,无需按鸢尾花的种类分类):
subplot(2,2,1);
histogram(meas(:,1))
subplot(2,2,2)
histogram(meas(:,2))
subplot(2,2,3);
histogram(meas(:,3))
subplot(2,2,4);
histogram(meas(:,4))
拟合与回归
重点:线性回归的学习(课件也不错)
-
regression learner APP:首选,
- 可以选用线性简单回归模型,及精细树,高斯回归等高级回归模型,可解决当前遇到的一切拟合问题,
- 得到的拟合模型(可导出查看) 中蕴含了你想要的各系数的信息.
- 得到模型后导出代码,可在其基础上继续编程进行数据处理(如调用trainedModel.Residuals属性查看残差,使用find去除残差过大点),完成包括异常点数据去除等系列问题
- 如此,构成了一套完整简便的回归分析处理方案
- (优势:相比于直接代码编程,省去了记忆线性回归代码流程 及 各种非线性回归模型拟合函数的麻烦)
-
直接根据课件进行代码编程(毫无疑问,工具箱生成代码相对你的编程要更为复杂,进行的处理更多,考虑的细节也更多;所以为了代码的简洁,交作业时,还是照样用代码直接编程吧,也不难),且这样能得到极为简洁的线性回归模型,如下:
==重点:==拟合的学习:
-
curvefit APP确实强大,能选择多种曲线进行拟合,但多数模型似乎都是不能生成函数的,只能生成模型(这些模型中包含各种系数),但对于解题而言,这大概也够了!
但其最多只能处理三元,
-
对于figure图床,其也能进行基本的拟合功能,直接生成曲线,但遗憾不能导出函数
问题:
- 训练完成后导出trainedModel,但是无法找到其函数知识
- 很多使用盲区,是否应该首先去其说明文档查找
-
Lab6a:酒精含量回归预测
(1)请先对数据绘制其血液中酒精含量与酒后时间的散点图
(2)选择多项式函数进行广义线性回归分析,并建立人体血液酒精含量与酒后时间的函数关系。(我采用了六次多项式函数来进行拟合,当然次数越高拟合效果越好,但实验多次后发现六次已经能取得较好拟合效果)
x=Lab6aData.VarName1,y=Lab6aData.VarName2;
p = polyfit(x,y,6);
%使用 polyval 计算可能未包含在原始数据中的其他点处的多项式
x2 = 0:.1:16;
y2 = polyval(p,x2);
plot(x,y,'o',x2,y2)
grid on
s = sprintf('y = (%.1f) x^3 + (%.1f) x^2 + (%.1f) x + (%.1f)',p(1),p(2),p(3),p(4));
text(2,400,s)
-
Lab6b:销售额回归模型(含异常值)
问题描述:
请你帮助公司管理人员根据这些数据找到销售额与其他三个变量之间的关系,以便进行销售额预测,并从中发现是否存在异常点,如果有异常点,请做必要的处理并重新进行回归分析。要求保存各步骤至实验报告,并提交。
首先导入数据,然后开始依次进行:回归–>诊断–>剔除异常值–>重新回归分析
%回归 X = [Lab6bData.VarName2,Lab6bData.VarName3,Lab6bData.VarName4]; mdl = fitlm(X, Lab6bData.VarName5) figure; mdl.plot;
%诊断 Res = mdl.Residuals; Res_stan = Res.Standardized; %标准化残差 figure; plot(Res_stan, 'kx'); refline(0, 1.3); refline(0, -1.3);
%剔除异常值 id = find(abs(Res_stan)>1.3);
%重新回归分析 mdl2 = fitlm(X, Lab6bData.VarName5, 'Exclude', id); figure; mdl2.plot;
-
使用MATLAB自带的fisheriris数据集,编程实现如下要求。
(1)去除setosa类别数据,保留virginica和versicolor两类数据。
(2)将两类数据,共100个样本拆分成训练集和测试集,拆分比例为8:2,即80个样本用于训练,20个样本用于测试。(提示:不同类别的样本分别拆分)
(3)使用训练集数据建立SVM分类器模型,并应用测试集数据进行测试。输出准确率。(注意:答案不唯一,算法流程正确即可)
load fisheriris %去除setosa类别数据 X = meas(51:150,:); % Use all data for fitting Y = species(51:150,:); % Response data %将两类数据,共100个样本拆分成训练集和测试集,拆分比例为8:2 TrainX1 = X(1:40,:); TrainY1 = Y(1:40,:); TestX1 = X(41:50,:); TestY1 = Y(41:50,:); TrainX2 = X(51:90,:); TrainY2 = Y(51:90,:); TestX2 = X(91:100,:); TestY2 = Y(91:100,:); trainX = [TrainX1;TrainX2]; testX = [TestX1;TestX2]; trainY = [TrainY1;TrainY2]; testY = [TestY1;TestY2]; %训练 svmmodel = fitcsvm(trainX,trainY, 'Standardize', true); %预测 result = predict(svmmodel, testX); %评估 accuracy = sum(strcmp(testY,result))/20
分类
完整流程(划分测试集,训练,计算准确率accuracy):以鸢尾花为例
知识点
-
KNN算法(最近邻算法)
-
SVM(支持向量机,属于逻辑回归):最常用,找到使间隔最大化的平面
-
lab1. 对数据集进行合理分割,选取KNN方法进行分类模型训练,并通过调整不同K值分析K取值对模型评价指标(具体指标可自行选择)的影响。
%将数据进行处理,分别得到属性数据 & 标签
X = [Lab5adata.Fe,Lab5adata.Co,Lab5adata.Zn;Lab5adata.Fe1,Lab5adata.Co,Lab5adata.Zn1];
Y = [Lab5adata.VarName2;Lab5adata.VarName7];
[size_r,size_c]=size(X);
%合理分隔为测试集和训练集
TrainX= X(1:size_r*0.75,:);
TrainY= Y(1:size_r*0.75,:);
TestX = X(size_r*0.75+1:size_r,:);
TestY = Y(size_r*0.75+1:size_r,:);
for K=1:5
%训练
knnmodel = fitcknn(TrainX,TrainY,'NumNeighbors',K);
%预测
[predict_trainY] = predict(knnmodel,TrainX);
[predict_testY] = predict(knnmodel,TestX);
%计算并打印训练集和测试集准确率
compare_train = TrainY==predict_trainY;
accuracy_train = sum(compare_train)/size(TrainX,1)*100;
fprintf('K值为%d时训练集准确率:%f\n',K,accuracy_train);
compare_test = TestY==predict_testY;
accuracy_test = sum(compare_test)/size(TestX,1)*100;
fprintf('K值为%d时测试集准确率:%f\n\n',K,accuracy_test);
end
运行结果:
(改图是原来错误代码的运行结果,全都是训练集准确率,没有测试集准确率)
根据运行结果可以初步推测:K较小时,准确率应该会更高
lab2:给出了60位就诊患者的化验指标,其中1 ~ 30号病例是已经确诊为肾炎病人的化验结果;31~60号是正常健康人的结果。请使用SVM算法建立肾炎患者识别模型,并通过选取交叉验证过程中不同的折数,分析对比在不同折数的情况下对模型评价指标(具体指标可自行选择)的影响。
- 编写f.m函数,函数功能:输入k(交叉验证折数)和data(进行处理后的表格数据),可以进行svm分类,并输出k折时训练集和测试集平均准确率
- 对表格数据进行数据处理后,使用f.m函数,输出5到15折下,训练集准确率
f.m代码:
function f(K,data)
lable={'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';
'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';
'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';'yes';
'no';'no';'no';'no';'no';'no';'no';'no';'no';'no';
'no';'no';'no';'no';'no';'no';'no';'no';'no';'no';
'no';'no';'no';'no';'no';'no';'no';'no';'no';'no'};
[data_r,~] = size(data);
%将数据样本随机分割为K部分
indices = crossvalind('Kfold', data_r, K);
accuracy_train_sum=0;
accuracy_test_sum=0;
for i = 1 : K
% 获取第i份测试数据的索引逻辑值
test = (indices == i);
% 取反,获取第i份训练数据的索引逻辑值
train = ~test;
%1份测试,其余训练
testX = data(test,:);
testY = lable(test,:);
trainX = data(train,:);
trainY = lable(train, :);
% 拟合
svmmodel=fitcsvm(trainX,trainY);
%SVM预测
[predict_trainY] = predict(svmmodel,trainX);
[predict_testY] = predict(svmmodel,testX);
% 计算单此预测准确率 并加和
compare_train = strcmp(trainY,predict_trainY);
accuracy_train = sum(compare_train)/size(trainX,1)*100;
accuracy_train_sum=accuracy_train_sum+accuracy_train;
compare_test = strcmp(testY,predict_testY);
accuracy_test = sum(compare_test)/size(testX,1)*100;
accuracy_test_sum=accuracy_test_sum+accuracy_test;
end
fprintf('%d折时训练集平均准确率:%f\n',K,accuracy_train_sum/K);
fprintf('测试集平均准确率:%f\n\n',accuracy_test_sum/K);
调用f.m输出结果:
%数据预处理
data = [Lab5bdata.Zn,Lab5bdata.Cu,Lab5bdata.Fe ,Lab5bdata.Ca,Lab5bdata.Mg,Lab5bdata.K,Lab5bdata.Na];
data(1,:)=[];
%调用f.m输出结果
for k=5:15
f(k,data);
end
运行结果:
聚类
-
要求:把握
-
三个关键概念
- 样本间距离
- 变量间的相似系数
- 类间距离
-
谱系聚类
谱系聚类首先将各样品自成一类,然后把最相似(距离最近或相似系数最大)的样品聚为小类, 再将已聚合的小类按各类之间的相似性(用类间 距离度量)进行再聚合,随着相似性的减弱,最 后将一切子类都聚为一大类,从而得到一个按 相似性大小聚结起来的一个谱系图
-
K均值(K-Means)聚类
K-Means算法是典型的基于距离的非层次聚类 算法,在最小化误差函数的基础上将数据划分 为预定的类数K,采用距离作为相似性的评价指 标,即认为两个对象的距离越近,其相似度就 越大。 K-Means聚类算法中,一般需要度量样本之间 的距离、样本与簇之间的距离以及簇与簇之间 的距离
-
-
课程中的源代码:
-
谱系聚类:
z1=linkage(d, 'single'); %最短距离 H1= dendrogram(z1) %谱系图 T1=cluster(z1,3); figure z2=linkage(d,'centroid'); %重心距离 H2= dendrogram(z2) %谱系图 T2=cluster(z2,3); %根据z2(可以在实时脚本界面查看其数据)orT2?是极其容易绘图的,dendrogram(z2) 只是绘图的方法之一
对于谱系聚类,常用指标:1. 𝑅^2统计量 2. 伪F统计量
1.𝑅^2统计量
Tm=sum(kmax*var(x)); bm=Tm-pm; R=bm./Tm; plot((2:20),R(2:20),'*'); xlabel('分类数'); ylabel('R2值');
2.伪F统计量
F=zeros(kmax,1); for kk=2:kmax F(kk)=bm(kk)/pm(kk)*(n-kk)/(kk-1); end plot((2:20),F(2:20),'*') ; xlabel('分类数'); ylabel('F值');
K-Means聚类:
% 参数初始化 k = 3; % 聚类的类别 iteration =500 ; % 聚类最大循环次数 distance = 'sqEuclidean'; % 距离函数 %% 数据标准化 X = zscore(data); scatter3(X(:,1),X(:,2),X(:,3),'k.') %% 调用kmeans算法 opts = statset('MaxIter',iteration); [IDX,C,~,D] = kmeans(X,k,'distance',distance,'Options',opts); %而根据IDX(可以在实时脚本界面查看其数据)是极容易进行绘图的,下面的Lab7,其绘图代码就是我自己写的! figure; scatter3(X(IDX==1,1),X(IDX==1,2),X(IDX==1,3),'r.') hold on scatter3(X(IDX==2,1),X(IDX==2,2),X(IDX==2,3),'m.') scatter3(X(IDX==3,1),X(IDX==3,2),X(IDX==3,3),'c.') plot3(C(:,1),C(:,2),C(:,3),'ko','MarkerSize',4,'LineWidth',1.5) legend('Cluster 1','Cluster 2','Cluster 3','Centroids',... 'Location','NW')
对于K-means聚类,常用指标:𝐹(𝑇,𝐾)(来源PPT,具体是啥不知道,没查到,反正不是伪F统计量)
q=2:12; for i=1:length(q) [IDX,C,sumd,D]=kmeans(X,q(i)); m=mean(X); a(i)=sum(dist(C,m')); b(i)=(sumd(i)).^0.5; end F=abs(a./b-1); plot(q,F,'-*');
-
-
Lab7
为我国部分省市的城镇居民人均可支配收入来源(单位:元/人),利用该表数据,尝试聚类并回答下面的问题。
- 计算各样品间的欧氏距离、马氏距离和加权平方距离。
- 运用谱系聚类法进行聚类,包括确定最优聚类数,选择合适的类间距离,同时做出谱系图。
- 运用K-Means聚类法进行聚类,并建立最佳聚类数公式。
- 【选做】,在Matlab中还有一种聚类方法称为模糊C均值聚类(fcm),自行查阅资料,学习该聚类方法的使用,并以步骤3确定的最佳聚类数进行模糊C均值聚类。
- 综合分析以上不同的聚类法所得的聚类结果,给出你的对比分析结论。
-
计算各样品间的欧氏距离、马氏距离和加权平方距离。
x= [Lab7Data.VarName2,Lab7Data.VarName3,Lab7Data.VarName4,Lab7Data.VarName5] % Step1:计算距离 distance1 =pdist(x,'euclidean') % 欧氏距离; distance2 =pdist(x,'mahalanobis') % 马氏距离 distance3 =pdist(x,'seuclidean') % 方差加权距离
结果:
-
运用谱系聚类法进行聚类,包括确定最优聚类数,选择合适的类间距离,同时做出谱系图。
% Step2:谱系聚类,选择合适的类间距离
[n,p]=size(x);
kmax=n-1;
pm=zeros(kmax,1);
pm(1)=1;
d=pdist(x);
z1=linkage(d, 'single'); %最短距离
z2=linkage(d,'complete'); %最长距离
z3=linkage(d,'average'); %类平均距离
z4=linkage(d,'centroid'); %重心距离
z5=linkage(d,'ward'); %离差平方和距离
R=[cophenet(z1,d),cophenet(z2,d),cophenet(z3,d),cophenet(z4,d),cophenet(z5,d)]
所以我们选择平均距离.
%根据R方统计量,确定最优聚类数
for k=2:kmax
z1=linkage(d,'average'); %按照平均类间距离创建谱系聚类树
c=cluster(z1,k); %聚类结果
for t=1:k
index_t=find(c==t);
size_t=length(index_t);
a=x(index_t,:);
pm(k)=sum((size_t-1)*var(a))+pm(k);
end
end
Tm=sum(kmax*var(x));
bm=Tm-pm;
R=bm./Tm;
plot((2:30),R(2:30),'*'); xlabel('分类数'); ylabel('R2值')
R方统计量结果:
可以看到,分类数达到5后,统计量增加不再明显,所以可以选择5作为最优聚类数.
x= [Lab7Data.VarName2,Lab7Data.VarName3,Lab7Data.VarName4,Lab7Data.VarName5];
d=pdist(x);
z1=linkage(d,'average'); %按照平均类间距离创建谱系聚类树
c=cluster(z1,5); %聚类结果
% 做出聚类数为5时的谱系图
H1= dendrogram(z1); %绘制谱系聚类树(即谱系图)
-
运用K-Means聚类法进行聚类,并建立最佳聚类数公式。
%% 数据标准化 data = [Lab7Data.VarName2,Lab7Data.VarName3,Lab7Data.VarName4,Lab7Data.VarName5]; X = zscore(data); %一般我们在2-12之间选择分类数 q=2:12; for i=1:length(q) %% 调用kmeans算法 [IDX,C,sumd,D]=kmeans(X,q(i)); m=mean(X); a(i)=sum(dist(C,m')); b(i)=(sumd(i)).^0.5; end F=abs(a./b-1); %画出伪F统计量随分类数变化图 plot(q,F,'-*');
结果图:
所以我们选择6作为最佳聚类数
% 参数初始化
k = 6; % 聚类的类别
iteration =500 ; % 聚类最大循环次数
distance = 'sqEuclidean'; % 距离函数
%% 数据标准化
data = [Lab7Data.VarName2,Lab7Data.VarName3,Lab7Data.VarName4,Lab7Data.VarName5];
X = zscore(data);
Label=categorical(Lab7Data.VarName1);
%% 调用kmeans算法
opts = statset('MaxIter',iteration);
[IDX,C,~,D] = kmeans(X,k,'distance',distance,'Options',opts);
%聚类结果可视化
figure;
plot(1,Label(IDX==1),'r.')
hold on
plot(2,Label(IDX==2),'g.')
plot(3,Label(IDX==3),'b.')
plot(4,Label(IDX==4),'y.')
plot(5,Label(IDX==5),'m.')
plot(6,Label(IDX==6),'c.')
% % plot3(C(:,1),C(:,2),C(:,3),'ko','MarkerSize',4,'LineWidth',1.5)
由于老师给出的数据有4个指标,不像PPT中的只有三个指标,不能利用scatter3画出4维指标的聚类结果,
(1表示聚类1,2表示聚类2…6表示聚类6,相同颜色的点代表同一个省份)
由图可以看出,青海,陕西,贵州,重庆等西部欠发达省份在聚类一,
广东,山东等较发达省份在聚类二,
北京,上海等高度发达省份在聚类三,
…
总体而言,分类还是较为符合实际的.
- 综合分析以上不同的聚类法所得的聚类结果,给出你的对比分析结论。
当聚类数较多时,二者均可取得较好的统计量观测结果
最佳类别数是导致聚类的有效性的核心.
Category ,String ,Cell的转化?呵呵,别做梦了吧!简直要崩溃了!这些方面都完不成,事实无不证明,他们只是在浪费你本就不多的时间!
-
MOOC单元作业八:
附件为MovieLens提供的电影评分数据集,在数据集中,ratings.csv文件中包含了用户对电影的评分,用户和电影都以各自的ID来表示。假定对影片评分相近作为用户之间的相似度衡量标准,请对数据做必要的预处理构造用户-影片的评分矩阵,并计算用户的相似度。之后根据用户相似度对用户做聚类分析,并对结果做出合理解释。(解释结果可参考数据集中其他数据文件)
-
构造用户-影片的评分矩阵
相当于用户是分类对象,由于影片数过多,两个用户评到同一部影片几率过小,我们取一个用户影片所评价过的所有影片评分平均值作为分类指标
-
聚类分析:
data=[ratings.userId,ratings.rating]; %%构造用户-影片的评分矩阵 %初始化评分矩阵 x = zeros(610,1); for k=1:610 %计算每个用户的影片评分平均分,为用户赋值 x(k,1)=(mean(data(data(:,1)==k,2))); end % 参数初始化 k = 3; % 聚类的类别 iteration =500 ; % 聚类最大循环次数 distance = 'sqEuclidean'; % 距离函数 %% 数据标准化 X = zscore(x); % scatter(X(:,1),X(:,2),X(:,3),'k.') %% 调用kmeans算法 opts = statset('MaxIter',iteration); [IDX,C,~,D] = kmeans(X,k,'distance',distance,'Options',opts); %聚类结果可视化 figure; UserId = 1:610; figure; scatter(UserId(IDX==1),x(IDX==1),'r.') hold on scatter(UserId(IDX==2),x(IDX==2),'m.') scatter(UserId(IDX==3),x(IDX==3),'c.') legend('Cluster 1','Cluster 2','Cluster 3','Centroids',... 'Location','NW') xlabel('用户Id'); ylabel('用户平均电影评分')
-
运行结果:
关联规则分析
- 支持度,置信度,提升度
{啤酒}→{尿布}的支持度: 𝑁1/
𝑁4
{尿布}→{啤酒}的支持度: 𝑁1/
𝑁4
{啤酒}→{尿布}的置信度: 𝑁1/
𝑁2
{尿布}→{啤酒}的置信度: 𝑁1/
𝑁3
{啤酒}→{尿布}的提升度: (𝑁1/𝑁2)/
(𝑁3/𝑁4)
{尿布}→{啤酒}的提升度: (𝑁1/𝑁3)
(𝑁2/𝑁4)先购买A对购买B的概率的提升作用,即
置信度(𝑁1/𝑁3)/后者在总销售记录中的比例(𝑁2/𝑁4) 的比值
-
关联规则算法:
目的:以超市销售数据为例,提取关联规则的最大困
难在于当存在很多商品时,可能的商品的组合
(规则的前项与后项)的数目会达到一种令人
望而却步的程度。因而各种关联规则分析的算
法从不同方面入手减小可能的搜索空间的大小
以及减小扫描数据的次数。-
Apriori
关联规则最常用也是最经典的挖掘频繁项集的算法,
其核心思想是通过连接产生候选项及其支持度然后
通过剪枝生成频繁项集在频繁项集𝐿1 、 𝐿2和𝐿3的基础上,计算置信度,
得到相应的关联规则只有>50%的才是有效规则!因为置信度阈值设置为了50%
-
FP-Tree
针对Apriori算法的固有的多次扫描事务数据集的
缺陷,提出的不产生候选频繁项集的方法。
Apriori和FP-Tree都是寻找频繁项集的算法
-
-
案例:教材只给出了Apriori算法的案例实现
- 步骤:
- loadData 加载数据并初始化
2. findFreqItemsets 查找频繁项集
3. generateRules 生成关联规则
- loadData 加载数据并初始化
- 步骤:
商品:评分为5的电影的movieId(因为评分为5的电影也有很多,有极大的可筛选空间)
一个购物篮:每个用户所查看的movie放在同一个购物篮,但老师提供的源数据并非这种形式,所以我们要进行数据处理
Step1:数据处理并把处理后的数据写入index.file,
源数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8PqqolFr-1651042249362)(数据分析-MATLAB.assets/image-20211209191007710.png)]
%数据处理并把处理后的数据写入index.file,以电影ID
userId = ratings.userId;
movieId = ratings.movieId;
rating = ratings.rating;
fid=fopen('input.txt','w');
for k = 1:610
%同一用户ID,且评分大于5的电影,在同一行
index = userId==k & rating==5;
%[m,n] = size(find(index));if(m>0)是为了杜绝空行输入input.txt
[m,n] = size(find(index));
if(m>0)
fprintf(fid,'%d,',movieId(index));
fprintf(fid,'\n');
end
end
fclose(fid);
处理结果(共计五百多行(去除了610行里的空行),仅截取部分):
Step2:使用Apriori算法(调用相关函数,函数在报告最下面)挖掘关联规则(由于样本太过稀疏,我们支持度阈值可以低一些,minSup = 0.05; % 最小支持度;minConf = 0.5;% 最小置信度)
%% 使用Apriori算法挖掘关联规则
clear;
% 参数初始化
inputfile = 'input.txt'; % 属性数据
outputfile='as.txt';% 输出转换后0,1矩阵文件
minSup = 0.05; % 最小支持度
minConf = 0.5;% 最小置信度
nRules = 1000;% 输出最大规则数
sortFlag = 1;% 按照支持度排序
rulefile = 'rules.txt'; % 规则输出文件
%% 调用转换程序 ,把数据转换为0,1矩阵,自定义函数
[transactions,code] = trans2matrix(inputfile,outputfile,',');
%% 调用Apriori关联规则算法,自定义函数
[Rules,FreqItemsets] = findRules(transactions, minSup, minConf, nRules, sortFlag, code, rulefile);
disp('Apriori算法挖掘数据关联规则完成!');
输出结果截取(共计256条规则,):
(仅从规则中截取部分)
从10万条数据中得到了256条规则,可以看到,整体效果较好
调用函数:
trans2matrix: txt文件转矩阵
function [ output,code] = trans2matrix( inputfile,outputfile,splitter )
%% 把输入事务转换为0、1矩阵;每行代表一个事务
% 输入参数:
% inputfile:输入文件,空格分隔每个项目;
% outputfile:输出文件,转换后的0,1矩阵文件;
% splitter: 输入文件项目的间隔符,默认为空格
% 输出参数:
% output : 转换后的0,1 矩阵
% code:编码规则;
if nargin<3
splitter=' ';
end
%% 读入文件, 获得编码规则
code={};
fid= fopen(inputfile);
tline = fgetl(fid);
lines=0;
while ischar(tline)
lines=lines+1; % 记录行数
tline = deblank(tline);
tline = regexp(tline,splitter,'split');
code=[code tline]; % 合并
code = unique(code); % 去除重复记录
% disp(code)
tline = fgetl(fid);
end
disp('编码规则为:')
disp(num2str(1:size(code,2)))
disp( code);
fclose(fid); % 关闭文档
%% 读取文件,根据编码规则对原始数据进行转换
itemsnum= size(code,2);
output=zeros(lines,itemsnum);
fid= fopen(inputfile);
tline = fgetl(fid);
lines=0;
while ischar(tline)
lines=lines+1; % 记录行数
tline = deblank(tline);
tline = regexp(tline,splitter,'split');
[~,icode,~] = intersect(code,tline);% 寻找下标
output(lines,icode')=1;
%disp(output(lines,:))
tline = fgetl(fid);
end
fclose(fid);
%% 把转换后的矩阵写入文件
fid = fopen(outputfile, 'w');
for i=1:lines
fprintf(fid,'%s\n',num2str(output(i,:)));
end
fclose(fid);
end
findRules: 算法核心,找出关联规则
function [Rules,FreqItemsets] = findRules(transactions, minSup, minConf, nRules, sortFlag, code, rulesfile)
%
% This function performs Association Analysis (Apriori Algorithm): Given a set of transactions,
% find rules that will predict the occurrence of an item based on the occurrences of other
% items in the transaction
%
% Rules are of the form A-> B (e.g., {milk, diaper} - > {Coke}), where
% support = minSup (minimum support threshold)
% confidence = minConf (minimum confidence threshold)
%
% Support is the fraction of transactions that contain both A and B:
% Support(A,B) = P(A,B)
%
% Confidence is the fraction of transactions where items in B appear in transactions that contain A:
% Confidence(A,B) = P(B|A)
%
%
% INPUT:
% transactions: M x N matrix of binary transactions, where each row
% represents one transaction and each column represents
% one attribute/item
% minSup: scalar value that represents the minimum
% threshold for support for each rule
% minConf: scalar value that represents the minimum
% threshold for confidence of each rule
% nRules: scalar value indicating the number of rules
% the user wants to find
% sortFlag: binary value indicating if the rules should be
% sorted by support level or confidence level
% 1: sort by rule support level
% 2: sort by rule confidence level
% code (labels): 编码规则 optional parameter that provides labels for
% each attribute (columns of transactions),
% by default attributes are represented
% with increasing numerical values 1:N
%
% fname: optional file name where rules are saved
%
% OUTPUT:
% Rules: 2 x 1 cell array, where the first cell (Rules{1}{:})
% contains the itemsets in the left side of the rule and second
% cell (Rules{2}{:}) contains the itemsets
% in the right side of the rule (e.g., if
% the first rule is {1, 2} -> 3,
% Rules{1}{1} = [1,2], Rules{2}{1} = [3])
% FreqItemsets: A cell array of frequent itemsets of size 1, 2,
% etc., with itemset support >= minSup,
% where FreqItemSets{1} represents itemsets
% of size 1, FreqItemSets{2} itemsets of
% size 2, etc.
% fname.txt: The code creates a text file and stores all the
% rules in the form left_side -> right_side.
%
% author: Narine Manukyan 07/08/2013
% Number of transactions in the dataset
M = size(transactions,1);
% Number of attributes in the dataset
N = size(transactions,2);
if nargin < 7
fname = 'default';
end
if nargin < 6
labels = cellfun(@(x){num2str(x)}, num2cell(1:N));
end
if nargin < 5
sortFlag = 1;
end
if nargin < 4
nRules = 100;
end
if nargin < 3
minConf = 0.5;
end
if nargin < 2
minSup = 0.5;
end
if nargin == 0
error('No input arguments were supplied. At least one is expected.');
end
% Preallocate memory for Rules and FreqItemsets
maxSize = 10^2;
Rules = cell(2,1);
Rules{1} = cell(nRules,1);
Rules{2} = cell(nRules,1);
FreqItemsets = cell(maxSize);
RuleConf = zeros(nRules,1);
RuleSup = zeros(nRules,1);
ct = 1;
% Find frequent item sets of size one (list of all items with minSup)
T = [];
for i = 1:N
S = sum(transactions(:,i))/M;
if S >= minSup
T = [T; i];
end
end
FreqItemsets{1} = T;
%Find frequent item sets of size >=2 and from those identify rules with minConf
for steps = 2:N
% If there aren't at least two items with minSup terminate
U = unique(T);
if isempty(U) || size(U,1) == 1
Rules{1}(ct:end) = [];
Rules{2}(ct:end) = [];
FreqItemsets(steps-1:end) = [];
break
end
% Generate all combinations of items that are in frequent itemset
Combinations = nchoosek(U',steps);
TOld = T;
T = [];
for j = 1:size(Combinations,1)
if ct > nRules
break;
else
% Apriori rule: if any subset of items are not in frequent itemset do not
% consider the superset (e.g., if {A, B} does not have minSup do not consider {A,B,*})
if sum(ismember(nchoosek(Combinations(j,:),steps-1),TOld,'rows')) - steps+1>0
% Calculate the support for the new itemset
S = mean((sum(transactions(:,Combinations(j,:)),2)-steps)>=0);
if S >= minSup
T = [T; Combinations(j,:)];
% Generate potential rules and check for minConf
for depth = 1:steps-1
R = nchoosek(Combinations(j,:),depth);
for r = 1:size(R,1)
if ct > nRules
break;
else
% Calculate the confidence of the rule
Ctemp = S/mean((sum(transactions(:,R(r,:)),2)-depth)==0);
if Ctemp > minConf
% Store the rules that have minSup and minConf
Rules{1}{ct} = R(r,:);
Rules{2}{ct} = setdiff(Combinations(j,:),R(r,:));
RuleConf(ct) = Ctemp;
RuleSup(ct) = S;
ct = ct+1;
end
end
end
end
end
end
end
end
% Store the freqent itemsets
FreqItemsets{steps} = T;
end
% Get rid of unnecessary rows due to preallocation (helps with speed)
FreqItemsets(steps-1:end) = [];
RuleConf = RuleConf(1:ct-1);
RuleSup = RuleSup(1:ct-1);
% Sort the rules in descending order based on the confidence or support level
switch sortFlag
case 1 % Sort by Support level
[V,ind] = sort(RuleSup,'descend');
case 2 % Sort by Confidence level
[V,ind] = sort(RuleConf,'descend');
end
RuleConf = RuleConf(ind);
RuleSup = RuleSup(ind);
for i = 1:2
temp = Rules{i,1};
temp = temp(ind);
Rules{i,1} = temp;
end
disp(['关联规则算法完成,规则数为:' num2str(size(RuleSup,1))]);
% Save the rule in a text file and print them on display
fid = fopen(rulesfile, 'w');
fprintf(fid, '%s (%s, %s) \n', 'Rule', 'Support', 'Confidence');
for i = 1:size(Rules{1},1)
s1 = '';
s2 = '';
for j = 1:size(Rules{1}{i},2)
if j == size(Rules{1}{i},2)
s1 = [s1 code{Rules{1}{i}(j)}];
else
s1 = [s1 code{Rules{1}{i}(j)} ','];
end
end
for k = 1:size(Rules{2}{i},2)
if k == size(Rules{2}{i},2)
s2 = [s2 code{Rules{2}{i}(k)}];
else
s2 = [s2 code{Rules{2}{i}(k)} ','];
end
end
s3 = num2str(RuleSup(i)*100);
s4 = num2str(RuleConf(i)*100);
fprintf(fid, '%s -> %s (%s%%, %s%%)\n', s1, s2, s3, s4);
end
fclose(fid);
disp(['存储规则到文件‘' rulesfile '’完成'])
end
MOOC作业九:
%数据处理并把处理后的数据写入input.file
%导入表格前信息做了排序,1:22063为0,即女,20264:43386为1,即男
fid=fopen('input1.txt','w');
for k = 1:20263
%将所有女性用户中买过的商品所在列的下标打印,(前两列为性别,时间,所以下标从第三列开始.我们最终根据下标就能判断商品种类)
fprintf(fid,'%d,',find(Untitled(k,:)==1));
fprintf(fid,'\n');
end
fclose(fid);
fid=fopen('input2.txt','w');
for k = 20264:43386
%将所有男性用户中买过的商品所在列的下标打印,(前两列为性别,时间,所以下标从第三列开始.我们最终根据下标就能判断商品种类)
fprintf(fid,'%d,',find(Untitled(k,3:)==1));
fprintf(fid,'\n');
end
fclose(fid);
%% 使用Apriori算法挖掘关联规则
clear;
% 参数初始化
inputfile = 'input1.txt'; % 属性数据
outputfile='as.txt';% 输出转换后0,1矩阵文件
minSup = 0.05; % 最小支持度
minConf = 0.5;% 最小置信度
nRules = 1000;% 输出最大规则数
sortFlag = 1;% 按照支持度排序
rulefile1 = 'rules1.txt'; % 规则输出文件
rulefile2 = 'rules2.txt'; % 规则输出文件
%% 调用转换程序 ,把数据转换为0,1矩阵,自定义函数
[transactions,code] = trans2matrix(inputfile,outputfile,',');
%% 调用Apriori关联规则算法,自定义函数
[Rules,FreqItemsets] = findRules(transactions, minSup, minConf, nRules, sortFlag, code, rulefile);
disp('Apriori算法挖掘数据关联规则完成!');
%%调用的相关函数可在matlab官网找到,代码较长,不再附上
运行结果:
得到的部分关联规则:
女性:
由此可见,对女性而言,购买:
133:431066:DINING 餐具
29:102018: CHINESE DESSERT中式甜点
41:102056:VENDOR BREAD供应商自制面包
后,往往会购买:
47:103116:FRESH SOY/FLOUR/RICE PRODUCTS新鲜豆制品/米面制品
得到的部分男性关联规则:
由此可见,对于男性而言,购买:
3:101001:BEVERAGE饮料
103005:CANNED FOOD罐头食品
118:328041:MANS WEAR 男装
往往会购买:
48:213018:LIQUOR酒类
由此可见,这些关联规则还是比较符合实际的
**LAB 9:**综合分析(实则就是数据处理+最常见的聚类)
- 构造各项指标,并进行一定处理:
%提取构造LRFMC指标,具体构造过程为:
L=airdata.LOAD_TIME-airdata.FFP_DATE;
R=airdata.LAST_TO_END;
F=airdata.FLIGHT_COUNT;
M=airdata.SEG_KM_SUM;
C=airdata.avg_discount;
%寻找异常值
find(L<=0)
find(L<=0)
find(F<=0)
find(M<=0)
%寻找avg_discount平均折扣率<0或>1的异常情况
find(C>1 | C<0)
结果如下:
说明存在avg_discount平均折扣率<0或>1的异常情况,去除这些数据;并进行数据标准化
%去掉avg_discount平均折扣率<0或>1的异常情况
index=find(C>1 | C<0);
L(index)=[];
R(index)=[];
F(index)=[];
M(index)=[];
C(index)=[];
%处理后的数据,利用zscore函数进行标准差标准化后
data=[L,R,F,M,C];
data=zscore(data);
- 聚类:将客户分成五个级别:
%%选择5作为聚类数,进行聚类
% 参数初始化
k = 5; % 聚类的类别
iteration =500 ; % 聚类最大循环次数
distance = 'sqEuclidean'; % 距离函数
% 调用kmeans算法
opts = statset('MaxIter',iteration);
[IDX,C,sumd,D] = kmeans(data,k,'distance',distance,'Options',opts);
统计各类中的客户数分布:
histogram(IDX)
以及各类的LRFMC指标对应的概率密度:
(五种颜色的曲线对应五种类,legend见右上)
L:会员入会时间距观测窗口结束的月数,
hold on;
%做L指标的概率分布图
for t=1:5
cdfplot(L(find(IDX==t)));
end
legend('Cluster 1','Cluster 2','Cluster 3','Cluster 4','Cluster 5')
R,F,M,C 频率分布图:
hold on;
%依次做RFMC指标的概率分布图
for t=1:5
cdfplot(R(find(IDX==t)));//F,M,C的代码同,不再赘述
end
legend('Cluster 1','Cluster 2','Cluster 3','Cluster 4','Cluster 5')
R:客户最近一次乘坐公司飞机距观测窗口结束的月数;
F:客户在观测窗口内乘坐公司飞机的次数;
M:客户在观测窗口内乘坐公司飞机的总里程;
C:客户在观测窗口内乘坐舱位所对应的折扣系数的平均值。
并分析类标号(15)与聚类目标(AE)的对应关系:
重要保持客户(A)、重要发展客户(B)、重要挽留客户(C)、一般客户(D)、低价值客户(E)
L:会员入会时间距观测窗口结束的月数;
R:客户最近一次乘坐公司飞机距观测窗口结束的月数;
F:客户在观测窗口内乘坐公司飞机的次数;
M:客户在观测窗口内乘坐公司飞机的总里程;
C:客户在观测窗口内乘坐舱位所对应的折扣系数的平均值。
L越长,R越小(该指标受观测窗口时间印象,仅具有一定参考价值),F越大,M越大,C越小,用户价值越高
根据各主要指标:(>表示更具价值)
人数比例:1:2:3:4:5 = 3:2:1:4:2
L:1>3>5>2>4 反应客户新老度,忠诚度
R:3>4>1>2>5 一定程度上能反应近期客户乘机频率(只具有一定参考价值)
F:4>>2≈5>3>1 反应客户乘机次数
M:3>>4≈1>2>5 反应客户乘机里程
C:2>>1≈3≈4≈5 反应客户乘机舱位层次高低,折扣系数越小,舱位越高级,可攫取利润越高
由此,可得以下关系:,
重要保持客户(A) cluster2:舱位层次高,乘机相对频繁
重要发展客户(B)cluster4:乘机次数和近期乘机次数高,且用户较新,具备发展潜力
重要挽留客户(C)cluster3:乘机里程和近期乘机次数较高,且用户较老,总量最大,需重点挽留
一般客户(D)cluster1:总量相对较大,乘机里程一般,乘机舱位普通,老用户,乘机次数较少
低价值客户(E)cluster5,注册相对较久,但乘机次数较少,乘机里程最少,舱位普通
- 【非计算机专业学生选做】评估聚类质量(本人非计算机专业)
3.根据你所选择的K-means聚类方法,选择F统计量作为评价指标,对聚类效果进行分析。
指标选用来自PPT:
m=mean(data);
a=sum(dist(C,m'));
b=(sumd).^0.5;
F=abs(a./b-1)
结果:
该聚类方案 LRFMC五大指标的F统计量 都接近于1,聚类效果较好.但毫无疑问的是,LRFMC五大指标各有侧重点,反应用户了用户忠诚度(新老用户),乘机频率,乘机舱位高低等不同价值,在重要度上也理应占有不同权值,更具有着不同的评估意义.所以执着于聚类数据上的效果而忽略了实际效果,是没有意义的.
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)