cvxpyライブラリの表記が古くて困ったこと
絶賛cvxpy
を用いて最適化問題を解く練習をしている中で、参考書のcvxpy
に関する記述が古くて困った話
何が困った
変なエラーが出る。実行したコードとエラーの内容は以下。
import numpy as np import numpy.linalg as lin import cvxpy as cvx Mu=np.array([1.0,3.0,1.5,6.0,4.5])#期待値 Std=np.array([5.0,10.0,7.5,15.0,11.0]) #分散 CorrMatrix = np.array([[1.00, 0.25, 0.18, 0.10, 0.25], [0.25, 1.00, 0.36, 0.20, 0.20], [0.18, 0.36, 1.00, 0.25, 0.36], [0.10, 0.20, 0.25, 1.00, 0.45], [0.25, 0.20, 0.36, 0.45, 1.00]]) Sigma=np.diag(Std).dot(CorrMatrix).dot(np.diag(Std))#分散共分散行列 iota=np.ones(Mu.shape) inv_Sigma=lin.inv(Sigma) #空売り制約下での分散最小化問題の設定 Weight=cvx.Variable(Mu.shape[0]) Target_Return=cvx.Parameter(sign='positive') Risk_Variance=cvx.quad_form(Weight,Sigma) constraints=[Weight.T*Mu == Target_Return, cvx.sum_entries(Weight)==1.0, Weight>=0.0] Opt_Portfolio=cvx.Problem(cvx.Minimize(Risk_Variance),constraints) V_Target=np.linspace(Mu.min(),Mu.max(),num=250) V_Risk=np.zeros(V_Target) V_Weight=np.zeros((V_Target.shape[0],Mu.shape[0])) for idx,Target_Return.value in enumerate(V_Target): Opt_Portfolio.solve() V_Weight[idx,:] V_Risk[idx]=np.sqrt(Risk_Variance.value)
File "pyfin_bond_yield_curve.py", line 19, in <module> Target_Return = cvx.Parameter(sign='positive') File "/Users/ikamihiroaki/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/cvxpy/expressions/constants/parameter.py", line 41, in __init__ super(Parameter, self).__init__(shape, value, **kwargs) TypeError: __init__() got an unexpected keyword argument 'sign'
対応1
TypeErrorの内容を見るに、恐らく引数に入れてるsign
ってやつが古いバージョンの引数で現在は使われてないのではないかと考えた。
とりあえず、19行目を以下のように変更。
before
Target_Return=cvx.Parameter(sign='positive')
after
Target_Return=cvx.Parameter
結果
エラーが返ってきた。内容は以下。
Traceback (most recent call last): File "pyfin_mvf_example2.py", line 24, in <module> constraints=[Weight.T*Mu == Target_Return, File "/Users/ikamihiroaki/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/cvxpy/expressions/expression.py", line 45, in cast_op other = self.cast_to_const(other) File "/Users/ikamihiroaki/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/cvxpy/expressions/expression.py", line 446, in cast_to_const return expr if isinstance(expr, Expression) else cvxtypes.constant()(expr) File "/Users/ikamihiroaki/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/cvxpy/expressions/constants/constant.py", line 44, in __init__ self._value = intf.DEFAULT_INTF.const_to_matrix(value) File "/Users/ikamihiroaki/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/cvxpy/interface/numpy_interface/ndarray_interface.py", line 50, in const_to_matrix return result.astype(numpy.float64) TypeError: float() argument must be a string or a number, not 'ABCMeta'
対応2
エラーの内容を見るに、データの型がおかしいみたい。
なので、24行目の変数Weight
,Mu
,Target_Return
のデータの型を調べてみた。
- 実行コード
print (type(Weight)) print (type(Mu)) print (type(Target_Return))
- 結果
<class 'cvxpy.expressions.variable.Variable'> <class 'numpy.ndarray'> <class 'abc.ABCMeta'>
あやしい、、、結果の3行目があやしい、、、エラーに出てるワードじゃん、、
というか3行目ってさっきのパラメータ入れるところじゃん
ということで、ググった。
その結果、最近のcvxpy
では
Target_Return=cvx.Parameter(sign='positive')
ではなく
Target_Return=cvx.Parameter(nonneg=True)
と表記するらしい
これで実行すると、24行目のエラーは解消!次に進む!
でもその次の25行目ですぐエラー出た
File "pyfin_mvf_example2.py", line 25, in <module> cvx.sum_entries(Weight)==1.0, AttributeError: module 'cvxpy' has no attribute 'sum_entries'
対応3
sum_entries
なんて関数?はないみたい。時代はsum
before
cvx.sum_entries(Weight)==1.0,
after
cvx.sum(Weight)==1.0,
これで解決!
まとめ
結局何が困ったかというと
cvxpy
の関数Parameter
の引数にsign
は使われてなかったsign='positive'
ではなくnonneg=True
cvxpy
の関数sum_entries
は使われてなかったcvxpy.sum_entries
ではなくcvxpy.sum