1 通过Python与Matlab交互
参考网站:
将 Python 与 MATLAB 结合使用-MATLAB & Simulink- MathWorks 中国
1.1 Matlab 安装tensor_toolbox工具箱
1)下载安装并解压,将解压后文件夹复制到自己电脑matlab的安装文件夹下(例如):
E:\Matlab\tensor_toolbox-v3.6
2)在matlab命令行窗口添加路径并保存,如下代码:
addpath E:\Matlab\tensor_toolbox-v3.6 % matlab命令行输入添加路径
savepath % 保存路径
which cp_als.m % 验证
1.2 在Python虚拟环境中安装matlab的引擎API
1)已安装的MATLAB都自带setup.py文件。
2)进入命令行窗口(Windows),如若有虚拟环境,建议在虚拟环境中输入命令:
E: % 进入Matlab安装盘
cd ./Matlab/extern/engines/python % 进入setup.py的目录下
python setup.py install % 执行安装
3)验证安装成功
python
import matlab
1.3 Matlab引擎启动方法
1)启动 MATLAB Engine for Python。通过调用 start_matlab 启动新的 MATLAB进程。start_matlab 函数返回 Python 对象 eng,您可以通过该对象传递数据和调用由 MATLAB 执行的函数。
import matlab.engine
eng = matlab.engine.start_matlab() # 启动引擎
... ...
eng.quit() # 停止引擎
2)异步启动引擎。以异步方式启动引擎,在 MATLAB 启动时,您可以在 Python 命令行中输入命令。
import matlab.engine
future = matlab.engine.start_matlab(background=True) # 异步启动引擎
... ...
eng.quit() # 停止引擎
3)运行多个引擎。分别启动每个引擎。每个引擎启动自己的 MATLAB 进程并与之通信。
import matlab.engine
eng1 = matlab.engine.start_matlab()
eng2 = matlab.engine.start_matlab()
... ...
eng.quit() # 停止引擎
1.4 Matlab 数组作为 Python 变量
import matlab.engine
eng = matlab.engine.start_matlab()
a = matlab.double([1,4,9,16,25])
b = eng.sqrt(a)
print(b)
1.5 通过 Python 调用 MATLAB 函数
1)从 MATLAB 函数返回输出参数。
import matlab.engine
eng = matlab.engine.start_matlab()
tf = eng.isprime(37) # 要确定某个数是否为质数,使用该引擎调用 isprime 函数。
print(tf)
2)从 MATLAB 函数返回多个输出参数。
当使用引擎调用函数时,默认情况下该引擎会返回单个输出参数。如果您知道函数可能返回多个参数,请使用 nargout 参数指定输出参数的数量。
import matlab.engine
eng = matlab.engine.start_matlab()
t = eng.gcd(100.0,80.0,nargout=3) # 要确定两个数的最大公分母,请使用 gcd 函数。设置 nargout 以从 gcd 返回三个输出参数。
print(t)
3)不从 MATLAB 函数返回任何输出参数。
有些 MATLAB 函数不会返回任何输出参数。如果函数不返回任何参数,则将 nargout 设为 0。
import matlab.engine
eng = matlab.engine.start_matlab() # 通过 Python 打开 MATLAB 帮助浏览器。
eng.doc(nargout=0)
4)停止执行函数
要停止执行 MATLAB 函数,请按 Ctrl+C。控制权将返回给 Python。
5)用函数名称替代 MATLAB 运算符
您可以通过调用等效函数在 Python 中使用 MATLAB 运算符。有关运算符和关联的函数名称的列表,请参阅 MATLAB 运算符和关联的函数。例如,要添加两个数值,请使用 plus 函数,而不是 + 运算符。
import matlab.engine
eng = matlab.engine.start_matlab()
a = 2
b = 3
eng.plus(a,b)
注意:在Python中,不能直接使用MATLAB的运算符(+ / - *…),需用等效的函数替代。
1.6 Python和Matlab的数据交换和映射
以下可用于使用时的查询:
3)MATLAB 和 Python 中的默认数值类型
默认情况下,MATLAB 以双精度浮点数形式存储所有数值,而 Python 默认情况下将一些数值存储为整数。由于这种差异,您可能会将整数作为输入参数传递给需要双精度数值的 MATLAB 函数。
当调用接受整数作为数值输入参数的 MATLAB 函数时,可以将具有 Python 数据类型 int 的输入参数传递给该函数。
1.7 从 Python 中调用用户脚本和函数(m文件)
1)调用用户脚本
首先,我们在Matlab中写一个名为 cp_test.m 脚本。而后,具体在python中调用如下:
import matlab.engine
eng = matlab.engine.start_matlab()
eng.cp_test(nargout=0)
2)调用m文件函数
首先在 MATLAB 写一个函数 formula1.m 如下:
function [y] = formula1(x)
y = (-2)./((x.^2)-1);
具体在python中调用如下:
import matlab.engine
a = np.array([2.0, 4.0, 3.0])
eng = matlab.engine.start_matlab()
result = eng.formula1(a)
print("type a : {}".format(type(a)))
print(type(result))
print(result)
1.8 从 Python 对 Matlab 数据进行绘图
2 Tensor Toolbox 的使用
2.1 Kruskal 张量
Kruskal 格式是张量 X 的分解,作为矩阵列的外积之和。
X
=
∑
r
=
1
R
m
r
∘
n
r
∘
t
r
\mathcal{X} = \sum_{r=1}^R m_r \circ n_r \circ t_r
X=r=1∑Rmr∘nr∘tr
其中下标表示列索引,圆圈表示外积,换句话说,张量 X 是由矩阵 A、B 和 C 的列构建的。明确指定每个外积权重通常很有帮助。
X
=
∑
r
=
1
R
γ
⋅
m
r
∘
n
r
∘
t
r
\mathcal{X} = \sum_{r=1}^R \gamma \cdot m_r \circ n_r \circ t_r
X=r=1∑Rγ⋅mr∘nr∘tr
ktensor 类存储张量 X 的组件,可以执行许多操作,例如 ttm,而无需显式形成张量 X。
下面是我们在python下,使用ktensor在Matlab引擎环境下做运算:
import matlab # matlab用于数据转换等工作
import matlab.engine # engine启动调用的matlab函数
A = np.random.randn(4, 2) # First column is a_1, second is a_2. <class 'numpy.array'>
B = np.random.randn(3, 2)
C = np.random.randn(2, 2)
A = A.tolist() # <class 'list'>
B = B.tolist()
C = C.tolist()
# matlab引擎启动
eng = matlab.engine.start_matlab()
A = matlab.double(A) # <class 'matlab.double'>
B = matlab.double(B)
C = matlab.double(C)
X = eng.formula1(A, B, C) # 调用matlab函数, <class 'matlab.double'>
X_list = list(X) # <class 'matlab.double'>
print(X)
# 停止引擎
eng.quit()
其中,formula1.m 如下:
function [X_array] = formula1(A, B, C)
rng('default'); % 为这个脚本设置随机种子
X = ktensor({A,B,C}); % 创建 ktensor. class = 'ktensor'
X_tensor = full(X); % 或tensor(X). class = 'tensor'
X_array = X_tensor.data; % class = 'double'
end
综上,关键是数据类型的多次变换:
3 Tensor Toolbox 实现张量分解(调用Matlab的库)
3.1 CP-ALS
// A code block
var foo = 'bar';
3.2 CP-WOPT
1) 安装MinGW
链接1 :下载安装MinGW-w64详细步骤(c/c++的编译器gcc的windows版,win10真实可用)
链接2 :从0安装MinGW32/64 ,Matlab错误使用mex未找到支持的编译器或SDK解决办法
setenv('MW_MINGW64_LOC','D:\EDGE_Download\mingw64') # 在MATLAB命令行内运行命令.
mex -setup # 检查 MATLAB 当前配置的编译器。它会显示当前 MATLAB 使用的编译器及其选项.
2)从Github下载 L-BFGS-B-C 并测试。
run('E:\Matlab\bin\L-BFGS-B-C\Matlab\compile_mex.m') # 在matlab命令行键入运行测试
addpath('E:\Matlab\bin\L-BFGS-B-C\Matlab') # 将此目录添加到我们保存的路径.
当然还是最建议直接在 MATLAB 主页–>环境–>设置路径,如下:
按照如下图框中添加我们 脚本文件夹 MATLAB_file 以及 L-BFGS-B-C 的路径。
现在,我们就可以使用 CP-WOPT 函数了。
% CP_WOPT
clc;
clear;
rng('default'); %<- Setting random seed for reproducibility of this script
R = 5;
% 官网例子
info = create_problem('Size', [15 10 5], 'Num_Factors', R, 'M', 0.25, 'Noise', 0.10);
X = info.Data; % class tensor
P = info.Pattern;
M_true= info.Soln;
M_init = create_guess('Data', X, 'Num_Factors', R, 'Factor_Generator', 'nvecs');
[~,~,output] = cp_wopt(X, P, R, 'init', M_init); % output表示此次迭代的信息
exitmsg = output.ExitMsg;
% 自定义数据;
% 将数据张量缺失条目中的值清零至关重要, 这可以通过调用 cp_wopt(X.*P,P,...)来完成
A = rand(15,R); %<-- First column is a_1, second is a_2.
B = rand(10,R); %<-- Likewise for B.
C = rand(5,R); %<-- Likewise for C.
data_k = ktensor({A,B,C});
data_tensor = tensor(data_k);
data_missing = data_tensor.*P;
M_init_2 = create_guess('Data', data_missing, 'Num_Factors', R, 'Factor_Generator', 'nvecs');
[M,temp,output] = cp_wopt(data_missing, P, R, 'init', M_init_2);
score(M, data_k);
3.3 GCP
% GCP
clc;
clear;
rng('default')
R = 10;
sz = [50 60 70];
info = create_problem('Size',sz,'Num_Factors',R,'M',0.1);
X = info.Data;
P = info.Pattern;
M_true = info.Soln;
A = rand(50,10); %<-- First column is a_1, second is a_2.
B = rand(60,10); %<-- Likewise for B.
C = rand(70,10); %<-- Likewise for C.
data_k = ktensor({A,B,C});
data_tensor = tensor(data_k);
data_missing = data_tensor.*P;
object_f1=@(x,m) 2.*(m-x).^2; % 目标损失函数
grad_f1=@(x,m) 4.*(m-x); % 梯度函数
M = gcp_opt(data_tensor,R,'type','normal','opt','lbfgsb','mask', P, ...
'printitn',10,'func',object_f1,'grad',grad_f1);
% 注意:对于缺失数据,Adam和SGD不可使用,只能使用'lbfgsb'
fprintf('Final fit: %e (for comparison to f in CP-ALS)\n',1 - norm(data_tensor-full(M))/norm(data_tensor));
fprintf('Score: %f\n',score(M,data_k));