2D配列に対してargmaxを実行し、最大の行と列のインデックスを返す便利な関数があれば、本当に便利です。
次のコードを再利用していることがよくあります
def argmax2d(X):
n, m = X.shape
x_ = np.ravel(X)
k = np.argmax(x_)
i, j = k // m, k % m
return i, j
シンプルですが、この関数を一貫して調べなければならないほど不透明です。
これがすでにnumpyで利用可能であるといいでしょう。
この機能をすぐに利用できるようにするために、numpyでPRを開くことに異議はありますか?
np.unravel_index
使ってみませんか?
例えば
np.unravel_index(X.argmax(), X.shape)
ボーナスとして、 X
に3つ以上の次元がある場合にも機能します。
argmax2d
ファンではありませんが、 i, j = a.argmax(axis=(0, 1))
説得される可能性があります
@ eric-wieserそれはどのように振る舞うべきだと思いますか? 現在、 a.argmax()
はスカラーを返し、 a.argmax(axis=0)
は残りの次元の形状の配列を返します。 3D配列のa.argmax(axis=(0,1))
は、形状a.shape[2]
配列を返すと思います。
この問題はさておき、一般的なケースでa.argmax(axis=range(n))
を使用して、デフォルトの整数線形インデックスの代わりにn
長さのインデックスタプルを取得するのは少し奇妙です。 おそらく、新しいキーワードで出力表現を切り替えることができますか?
繰り返しになりますが、この形状認識結果オプションは、既存のaxis
キーワードとどのように連携して、非スカラーの戻り値になりますか?
2D配列の行の1つに最大値がない場合(それは単に定数配列です)、argmaxはそれをどのように報告できますか?
例えば:
# setup the problem
import numpy as np
x=np.arange(10).reshape([2,5])
x[1,3]=2
# x is this:
# [[0, 1, 2, 3, 4],
# [5, 6, 7, 2, 9]]
# this will behave normally
np.argmax(x==2, axis=1)
# Out: [2,3]
# but this one returns 0 instead of NaN
np.argmax(x==3, axis=1)
# Out: [3,0]
# Expected: [3, nan]
たとえば、最大値が使用できない場合にユーザーが何をするかを制御できるようにするための追加の引数があると便利です: np.argmax(x,axis,no_ind=0)
(下位互換性を維持するために0がデフォルトです)。
@ thoth291は、 argmax
動作に関するより一般的な質問ではありませんか? 同じことが、1次元配列にaxis
キーワード引数がない場合にも発生します。
>>> np.argmax([2,2,2])
0
そして、これは同点の場合の通常の動作です。同点の値の中から最初のものを選択します。 同様に、その配列のmax
がnan
はない場合:2です。最大値がある場合は、対応するインデックスが必要です。 それとも私はあなたのポイントを逃しましたか?
@adeak 、今あなたはそれを言った-私はこれが確かにもっと一般的な質問だと思い始めている。
max([2,2,2])
が2
等しいことに同意できます。
しかし、argmax([2,2,2])について考えてみてください-numpyドキュメントの定義によれば、 the indices corresponding to the first occurrence
返します。 これは実装の観点からは問題ないようですが、実際にはアルゴリズムの古語法であり、実際に何が起こるかとは関係ありません。 事実上、すべてのインデックスを返すことができ、正しいものとして扱う必要があります。 または、定数値の配列の場合、argmaxはあいまいであると言えます。
そうは言っても、私はそもそもそのような決定を避け、 inf
を返して、そのようなケースの処理方法を決定するのはユーザー次第であることを知らせたいと思います。
実際に起こることとは何の関係もありません。
「argmaxの抽象的な定義とは何の関係もない」という意味ですか? _ "アルゴリズム" _と_ "実際に起こること" _が同じものであるだけでなく、ドキュメントと一致していることを願っています。
@adeak :返信しないでごめんなさい
繰り返しになりますが、この形状認識結果オプションは、既存のaxisキーワードとどのように連携して、非スカラーの戻り値になりますか?
これに対処するための明白な方法が1つあると思います。 例として:
>>> ret = argmax(np.empty((A, B, C, D, E)), axes=(0, 2))
>>> type(ret)
tuple
>>> len(ret) # == len(axes)
2
>>> ret[0].shape
(B, D, E)
>>> ret[1].shape
(B, D, e)
それとkeepdimsを使用すると、任意の次元でarr[argmax(arr, axes, keepdims=True)] == max(arr, keepdims=True)
を取得できます。これは、私にとって非常に望ましいと思われます。
擬似コードでは、私は期待します:
def argmax(arr, axes, keepdims)
was_tuple = isinstance(axes, tuple):
if not was_tuple:
axes = (axes,)
shape = np.array(arr.shape)
axis_mask = np.array([i in axes for i in range(arr.ndim)])
shape[axis_mask] = 1
ret = tuple(np.empty(shape) for _ in axes)
# do the actual work
if not keepdims:
ret = tuple(r.reshape(shape[~axis_mask]) for r in ret)
if not was_tuple:
return ret[0]
@ eric-wieser-ナイスキャッチ-正しく翻訳できるよりも速く入力しました。 後で気をつけます。 コメントを「発生する」ではなく「発生するはず」に更新しました。 それが役に立てば幸いです、そうでなければ-改革のための提案を開いてください。
重要なのは、argmax([2,2,2])== 0はargmax([2,2,2])== 1などと同じくらい優れており、ライブラリではなくユーザーが選択する必要があるということです。 それ以外の場合、フォールバックメカニズムは、(たとえば)追加のキーワードdefault=
またはinitial=
の形式で提供する必要があります。これにより、この場合に何を返すかが指示されます。
@ thoth291 :あなたが話しているのは_2D_ argmaxに固有のものではないので、新しい問題を作成することをお勧めします
@ eric-wieser心配ありません、私に戻ってきてくれてありがとう。 私はあなたの提案を理解していると思います、そしてそれは明白で実用的であるように見えます。 axis
引数の型によって、戻り値が配列であるか配列のタプルであるかが決まるという事実は、私には少し驚きです(特に、 axes=0
とaxes=[0]
)。しかし、同じ動作の既存の例はたくさんあると確信しています(また、実用性は純粋さを上回ります)。
〜念のために言っておきますが、あなたの例では、 axes=(0,2)
場合、返される形状は(B,D,E)
であるはずですよね?
念のために
両方とも修正され、良いキャッチ
axis引数の型によって、戻り値が配列であるか配列のタプルであるかが決まるという事実は、私には少し驚きです。
実際の配列は同じであることに注意してください。 これは実用性と純粋さの両方に影響すると思います-ルールはaxis=(a,)
→ res = (arr,)
とaxis=a
→ res = arr
です。 サイズ1の特殊なケースのタプルは、その特殊なケーシングがコールスタック全体に伝染する必要があるため、悪い考えだと思います。
特別な場合の長さ1のタプルを考えたことはありませんでしたが、それは間違っているように聞こえます。 スカラーとタプルの場合について疑問に思っていました。 スカラーと長さ1のタプルのケースは、あなたが述べたように互いに対応していることに漠然と思い浮かびましたが、それを詳しく説明したので、スカラー-> 1-タプル->一般的なタプルのケースが単純な一般化であることは明らかです。 おかげで、私はあなたの提案を完全に支持します。
最も参考になるコメント
np.unravel_index
使ってみませんか?例えば
ボーナスとして、
X
に3つ以上の次元がある場合にも機能します。