最後に、 :
- まず、scipy documentationに基づいて、LiL(リンクリスト)形式がこの種の操作に理想的なようです。 (ただし、実際の比較は一度も行っていませんでした)
- 私はhereの機能を使って行と列を入れ替えました。
に続いて、私は200×200の 'ウィンドウ'をマトリックスの左上隅に定義し、ウィンドウ内の非ゼロ要素の数と単純に等しい「ウィンドウスコア」を実装しました。
- スワップする列を特定するために、ウィンドウ内の非ゼロ要素が最も少ない列と、ウィンドウ外の最も非ゼロの要素を含む列を調べました。タイの場合、列全体の非ゼロ要素の数はタイブレーカー(これが結ばれていれば、ランダムに選択した)です。
- 行を交換する方法は同じでした。
import numpy as np
import scipy.sparse
import operator
def swap_rows(mat, a, b):
''' See link in description'''
def swap_cols(mat, a, b) :
''' See link in description'''
def windowScore(lilmatrix,window):
''' Return no. of non-zero elements inside window. '''
a=lilmatrix.nonzero()
return sum([1 for i,j in list(zip(a[0],a[1])) if i<window and j<window])
def colsToSwap(lilmatrix,window):
''' Determine columns to be swapped.
In: lil_matrix, window (to what col_no is it considered "left")
Out: (minColumnLeft,maxColumnRight) columns inside/outside of window w/ least/most NZ elements'''
# Locate non-zero elements
a=lilmatrix.nonzero()
totalCols=lilmatrix.get_shape()[1]
# Store no. of NZ elements for each column {in the window,in the whole table}, initialize with zeros
colScoreWindow=np.zeros(totalCols)
colScoreWhole=np.zeros(totalCols)
### Set colScoreWindow scores
# Unique row indices
rows_uniq={k for k in a[0] if k<window}
for k in rows_uniq:
# List of tuples w/ location of each NZ element in current row
gen=((row,col) for row,col in list(zip(a[0],a[1])) if row==k)
for row,col in gen:
# Increment no. of NZ elements in current column in colScoreWindow
colScoreWindow[col]+=1
### Set colScoreWhole scores
# Unique row indices
rows_uniq={k for k in a[0]}
for k in rows_uniq:
# List of tuples w/ location of each NZ element in current row
gen=((row,col) for row,col in list(zip(a[0],a[1])) if row==k)
for row,col in gen:
# Increment no. of NZ elements in current column in colScoreWhole
colScoreWhole[col]+=1
# Column inside of window w/ least NZ elements
minColumnLeft=sorted(list(zip(np.arange(totalCols),colScoreWindow,colScoreWhole,np.random.rand(totalCols)))[:window], key=operator.itemgetter(1,2,3))[0][0]
# Column outside of window w/ most NZ elements
maxColumnRight=sorted(list(zip(np.arange(totalCols),colScoreWindow,colScoreWhole,np.random.rand(totalCols)))[window:], key=operator.itemgetter(1,2,3))[-1][0]
return (minColumnLeft,maxColumnRight)
def rowsToSwap(lilmatrix,window):
''' Same as colsToSwap, adjusted for rows.'''
colsToSwap
とrowsToSwap
の反復と実際のスワッピング機能の適切な数を実行した後、ウィンドウ内の非ゼロ要素の数が最大値に収束します。この方法はまったく最適化されておらず、改善の余地があることに注意してください。たとえば、疎な行列型変換の回数を減らすことや、a=lilmatrix.nonzero()
呼び出しを減らすことで、速度が大幅に向上すると思われます。
MATLABには線形代数解を改善するための疎行列の再配列方法があります。私は 'scipy'コードでは何も認識していません。しかし、疎な文書をスキャンして確認してください。また、適用された数学の論文を探します。 MATLABは 'csc'を使用しますが、おそらくコンパイルされたコードで再配置します。 – hpaulj
'csr'と' csc'マトリックスの行と列の合計とインデックスは行列乗算で行われます。したがって、この並べ替えはおそらく同じ方法で実行できます。私はこれについて最近SOに答えました。 – hpaulj
scikit learnにはコンパイルされた疎なユーティリティコードがあります。そのドキュメントを勉強してください。 – hpaulj