TU ゲームの多重線形拡張を使用して Shapley 値を計算する小さなプログラムを MATLAB で作成しました。しかし、MATLAB の Symbolic Math Toolbox で問題が発生しました。このプログラムでは、一連の関数を統合して Shapley 値を取得する必要があります。ただし、MATLAB プログラム内では int() コマンドを使用できません
Error using sym/subsindex (line 663) Ivalid indexing or function definition. When defining a function, ensure that the body of the function is a SYM object. When indexing, the input must be numeric, logical or ':'.
Error in ShapleyValueML (line 65)shv(jj)=int(dfy,0,1)
結果として、代わりに integral() を使用する必要があります。この場合、式のセットを matlabFunction() を使用して MATLAB 関数ハンドルに変換する必要があります。ただし、アクセスできるすべての Linux マシン (MATLAB R2014a) では、このコマンドは機能しません (以下の説明を参照)。回避策として、MATLAB プログラムは一連の関数を現在のワークスペースに返し、そこで int() コマンドを使用して Shapley 値を計算できます。
議論をより具体的にするために、まずこの小さな MATLAB プログラムについて考えてみましょう。
function [shv,F,dfm]=ShapleyValueML(v)
N=length(v);
[~, n]=log2(N);
S=1:N;
int=0:-1:1-n;
mat=(rem(floor(S(:)*pow2(int)),2)==1);
cmat=(rem(floor(S(:)*pow2(int)),2)==0);
x=sym('x',[1 n]);
mx=1-x;
y = sym('y');
vy=ones(1,n)*y;
F=0;
shv=zeros(1,n);
dfm=cell(1,n);
for ss=1:N
pd1=x(mat(ss,:));
pd2=mx(cmat(ss,:));
pd=prod(pd1)*prod(pd2)*v(ss);
F=pd+F;
end
F=expand(F);
for jj=1:n
dF=diff(F,x(jj));
dfy=subs(dF,x,vy);
%% Does not work!! MATLAB bug???
% mf=matlabFunction(dfy);
% shv(jj)=integral(mf,0,1);
%%
%% The best would be to use:
%%
% shv(jj)=int(dfy,0,1)
%% but it cannot be used inside a program.
dfm{jj}=dfy;
end
end
コメントされた部分は、プログラム内で動作しない部分ですが、そのプログラムで Shapley 値を計算するために必要であり、それが目的です。このプログラムを最大 12 人のプレーヤーでテストしたところ、2 段階の手順で Shapley 値を正常に計算できました。したがって、上記のプログラムは、考慮されている問題を正しく指定しています。この 2 段階の手順と上記のプログラムの機能をよりよく理解するために、3 人用ゲームに焦点を当てましょう。連合の値は、次のデータ配列によって与えられます。
>> v = [0,0,90,0,100,120,220];
連合は、一意の整数表現に従って順序付けられていることに注意してください。ゲームが定義されました。これで、上記のプログラムで多重線形拡張と一連の偏導関数を評価できますが、Shapley 値は評価できません。
>> [shv,F,dfm]=ShapleyValueML(v);
偏導関数の集合の積分は、単位立方体の対角線上で実行されますが、変数を [x1,x2,x3] から [y,y,y] に設定でき、積分は 0 から 1 まで実行されます。
>> for k=1:3, shv(k)=int(dfm{k},0,1);end;
積分の解は、以下によって与えられる Shapley 値です。
>> shv
shv =
65 75 80
これが実際に Shapley 値であることを確認するには、
>> sh_v=ShapleyValue(v)
sh_v =
65 75 80
これは、MATLAB Game Theory Toolbox の MatTuGames に同梱されています。
http://www.mathworks.com/matlabcentral/fileexchange/35933-mattugames
int() と統合する代わりに、integral() を使用することもできますが、内容は次のようになります。
>> dfm{1}
ans =
- 90*y^2 + 190*y
関数ハンドルに matlabFunction() で書き直す必要があります。上で述べたように、これは Linux (MATLAB R2013a、R2013b、R2014a) では機能しません。これを確認するために、例を再現してみましょう
>> syms x y
>> r = sqrt(x^2 + y^2);
URL のドキュメントから:
これは与えるべきです
ht =
@(x,y)tanh(sqrt(x.^2+y.^2))
しかし、私は得る
>> ht = matlabFunction(tanh(r))
Cell contents reference from a non-cell array object.
Error in vectorize (line 15)
c = cells{i};
Error in sym/matlabFunction>mup2mat (line 319)
res = vectorize(res(2:end-1)); % remove quotes
Error in sym/matlabFunction>mup2matcell (line 304)
r = mup2mat(c{1});
Error in sym/matlabFunction (line 123)
body = mup2matcell(funs);
ここに私の質問があります:そこから取得するための代替手順が存在します
>> dfm{1}
ans =
- 90*y^2 + 190*y
関数ハンドル
>> df=@(y) (- 90.*y.^2 + 190.*y)
df =
@(y)(-90.*y.^2+190.*y)
それを統合する
>> integral(df,0,1)
ans =
65
または、別の言い方をします。乗算 * を要素ごとの乗算 .* に変更し、ベキ演算 ^ を要素ごとの累乗に変更する代替方法はありますか?
もちろん、上記の MATLAB プログラムを改善するための提案は大歓迎です。