Python通过Matlab的Tensor_Toolbox实现张量分解(笔记)

1 通过Python与Matlab交互

参考网站:

将 Python 与 MATLAB 结合使用-MATLAB & Simulink- MathWorks 中国

MATLAB 产品(按版本)兼容的 Python 版本

从 Python 中调用 MATLAB

1.1 Matlab 安装tensor_toolbox工具箱

Tensor Toolbox 的官方网址

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 变量

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的数据交换和映射

以下可用于使用时的查询:

1)从 Python 将数据传递到 MATLAB

2)处理从 MATLAB 返回到 Python 的数据

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 数据进行绘图

从 Python 对 Matlab 数据进行分类并绘图

2 Tensor Toolbox 的使用

2.1 Kruskal 张量

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=1Rmrnrtr
其中下标表示列索引,圆圈表示外积,换句话说,张量 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=1Rγmrnrtr
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 并测试。

L-BFGS-B-C 的 GitHub 网址

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));

4 迭代过程的自定义

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不睡觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值