Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@nyantacos

argsortの逆関数

More than 1 year has passed since last update.

概要

numpy.argsort関数の「逆関数」みたいな操作をしたいと思うことがあり、ネットを調べてみても、すぐには出てこなさそうだったので、自分で考えてみました。
いろいろ試した結論としては、numpy.argsort( numpy.argsort( ARRAY_INPUT ) ) とするとよさそうです。

・・・という記事です。

本当?

と思われる方は、以下本文を参照ください・・・

なぜそんなことを考えたのか?

機械学習の仕事をしていて、学習モデルが出力する予測値を変換してからスコア算出する、ということをしたいことがありました。
例えば、学習モデルが以下のような予測値の配列を出力したとします。

INDEX 0 1 2 3 4 5 6 7 8 9
VALUE 0.15 0.04 0.20 0.08 0.05 0.30 0.12 0.01 0.03 0.02

これは0-9の各クラスのいずれかに属するかを示す確信度(1に近いほど高確率)を表しているものとします。このままでもいいのかもしれないですが、トップ3だけに、順に10点、5点、1点のスコアを与え、あとは0点にしてスコア計算したいという要求がありました。
(そういうスコアの与え方でGridSearchしたかったのです。)

つまり、上記の例でいうと、以下のような配列に変換してから、スコア計算したかったわけです。

INDEX 0 1 2 3 4 5 6 7 8 9
VALUE 1 0 5 0 0 10 0 0 0 0

この配列をどうやったら作れるんだろう?
numpy.argsort関数の逆関数、例えばinv_argsortという名前の関数があって、以下のようなことができたらうれしいわけです。

In [1]: prediction
Out[1]: [0.15, 0.04, 0.2, 0.08, 0.05, 0.3, 0.12, 0.01, 0.03, 0.02]

In [2]: score = [0, 0, 0, 0, 0, 0, 0, 1, 5, 10]

In [3]: prediction_scored = numpy.take(score, inv_argsort(prediction))

In [4]: prediction_scored
Out[4]: array([ 1,  0,  5,  0,  0, 10,  0,  0,  0,  0])

inv_argsortの実装

概要にも書きましたが、以下の通り、実装自体は簡単です。

def inv_argsort(array_input):
    return numpy.argsort(numpy.argsort(array_input))

でも本当にそれでいいの?という気もしますので、以下で簡単な証明をしておこうと思います。

証明

1回目のargsort

${ n }$個の要素を持つ配列 ${ v }$ が学習モデルの直接の出力とします。

INDEX 0 1 2 ${\dots}$ ${n-1}$
${ v }$の値 ${ v_0 }$ ${ v_1 }$ ${ v_2 }$ ${ \dots }$ ${ v_{n-1} }$

これを numpy.argsort にかけた結果を ${ u }$ とします。

INDEX 0 1 2 ${\dots}$ ${n-1}$
${ u }$の値 ${ u_0 }$ ${ u_1 }$ ${ u_2 }$ ${ \dots }$ ${ u_{n-1} }$
${ v }$の値 ${ v_{u_0} }$ ${ v_{u_1} }$ ${ v_{u_2} }$ ${ \dots }$ ${ v_{u_{n-1}} }$

ここで、argsortの定義により、

$$ v_{u_0} \leq v_{u_1} \leq v_{u_2} \leq \dots \leq v_{u_{n-1}} $$

であるとわかります。
つまり、INDEXの $0, 1, 2,\dots, n-1$ と大小関係が一致するわけです。
ここでこの表の最下行に、付与したいスコアもくっつけてみます。

INDEX 0 1 2 ${\dots}$ ${n-1}$
${ u }$の値 ${ u_0 }$ ${ u_1 }$ ${ u_2 }$ ${ \dots }$ ${ u_{n-1} }$
${ v }$の値 ${ v_{u_0} }$ ${ v_{u_1} }$ ${ v_{u_2} }$ ${ \dots }$ ${ v_{u_{n-1}} }$
SCORE ${ s_0 }$ ${ s_1 }$ ${ s_2 }$ ${ \dots }$ ${ s_{n-1} }$

概要の例でいえば、${ s_9 = 10, s_8 = 5, s_7 = 1 }$ で残りは 0 ということになります。
$v$ の昇順に並んでいるので、「トップ3に順に 10点、5点、1点を割り当てる」という対応関係が成立しています。

2回目のargsort

$u$ を numpy.argsort にかけた結果を ${ w }$ とします。

INDEX 0 1 2 ${\dots}$ ${n-1}$
${ w }$の値 ${ w_0 }$ ${ w_1 }$ ${ w_2 }$ ${ \dots }$ ${ w_{n-1} }$
${ u }$の値 ${ u_{w_0} }$ ${ u_{w_1} }$ ${ u_{w_2} }$ ${ \dots }$ ${ u_{w_{n-1}} }$
${ v }$の値 ${ v_{u_{w_0}} }$ ${ v_{u_{w_1}} }$ ${ v_{u_{w_2}} }$ ${ \dots }$ ${ v_{u_{w_{n-1}}} }$
SCORE ${ s_{w_0} }$ ${ s_{w_1} }$ ${ s_{w_2} }$ ${ \dots }$ ${ s_{w_{n-1}}} $

ここで、あることに気が付きます。
$$ u_{w_i} \in [0, 1, 2, \dots, n-1], \hspace{12pt} u_{w_0} \lt u_{w_1} \lt u_{w_2} \lt \dots \lt u_{w_{n-1}}$$
という事実から、
$$ u_{w_0}=0, u_{w_1}=1, u_{w_2}=2, \dots , u_{w_{n-1}}=n-1 $$
であるとわかります。
これをもとに表を書き換えておきましょう。

INDEX 0 1 2 ${\dots}$ ${n-1}$
${ w }$の値 ${ w_0 }$ ${ w_1 }$ ${ w_2 }$ ${ \dots }$ ${ w_{n-1} }$
${ u }$の値 ${ 0 }$ ${ 1 }$ ${ 2 }$ ${ \dots }$ ${ n-1 }$
${ v }$の値 ${ v_0 }$ ${ v_1 }$ ${ v_2 }$ ${ \dots }$ ${ v_{n-1} }$
SCORE ${ s_{w_0} }$ ${ s_{w_1} }$ ${ s_{w_2} }$ ${ \dots }$ ${ s_{w_{n-1}}} $

・・・おや、$v$ の並び順がもともとの並び順に戻っていますね。
これはつまり、学習モデルが出力したままの順序に戻ったわけです。
それに対応するスコア配列の並びは、 $w$ に記録されています。

つまり、求めるスコア配列(prediction_scored)は、以下で求めることができるということです。

v = prediction
u = numpy.argsort( v )
w = numpy.argsort( u )
score = [0, 0, 0, 0, 0, 0, 0, 1, 5, 10]
prediction_scored = numpy.take(score, w)

[証明終了]

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?