web-dev-qa-db-ja.com

numpyを使用した1つのホットエンコーディング

入力がゼロの場合、次のような配列を作成します。

[1,0,0,0,0,0,0,0,0,0]

入力が5の場合:

[0,0,0,0,0,1,0,0,0,0]

上記について私は書きました:

np.put(np.zeros(10),5,1)

しかし、うまくいきませんでした。

これを1行で実装できる方法はありますか?

28

通常、機械学習の分類用のワンホットエンコーディングを取得する場合、インデックスの配列があります。

import numpy as np
nb_classes = 6
targets = np.array([[2, 3, 4, 0]]).reshape(-1)
one_hot_targets = np.eye(nb_classes)[targets]

one_hot_targetsは現在

array([[[ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 1.,  0.,  0.,  0.,  0.,  0.]]])

.reshape(-1)は、正しいラベル形式を持っていることを確認するためにあります([[2], [3], [4], [0]]もあるかもしれません)。 -1は特別な値で、「このディメンションに残っているものをすべて置く」ことを意味します。 1つしかないため、配列を平坦化します。

コピーペーストソリューション

def get_one_hot(targets, nb_classes):
    res = np.eye(nb_classes)[np.array(targets).reshape(-1)]
    return res.reshape(list(targets.shape)+[nb_classes])

パッケージ

mpu.ml.indices2one_hot を使用できます。テスト済みで使いやすい:

import mpu.ml
one_hot = mpu.ml.indices2one_hot([1, 3, 0], nb_classes=5)
59
Martin Thoma

何かのようなもの :

np.array([int(i == 5) for i in range(10)])

トリックを行う必要があります。しかし、numpyを使用する他のソリューションがあると思います。

編集:数式が機能しない理由:np.putは何も返さず、最初のパラメーターで指定された要素を変更するだけです。 np.put()を使用する際の適切な答えは次のとおりです。

a = np.zeros(10)
np.put(a,5,1)

問題は、配列をnp.put()に渡す前に定義する必要があるため、1行で実行できないことです。

9
HolyDanna

リスト内包表記を使用できます:

[0 if i !=5 else 1 for i in range(10)]

になります

[0,0,0,0,0,1,0,0,0,0]
3
Rikku Porta

np.identityまたはnp.eyeを使用します。入力iと配列サイズsで次のようなものを試すことができます。

np.identity(s)[i:i+1]

たとえば、print(np.identity(5)[0:1])は次のようになります。

[[ 1.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

TensorFlowを使用している場合、tf.one_hotを使用できます。 https://www.tensorflow.org/api_docs/python/array_ops/slicing_and_joining#one_hot

2
Sung Kim

np.putは、配列argin-placeを変更します。 Pythonでは、インプレースミューテーションを実行してNoneを返す関数/メソッドの従来型です。 np.putはその規則に従います。したがって、aが1D配列であり、

a = np.put(a, 5, 1)

aNoneに置き換えられます。

コードはそれに似ていますが、名前のない配列をnp.putに渡します。

あなたが望むことをするコンパクトで効率的な方法は、単純な関数を使うことです。例えば:

import numpy as np

def one_hot(i):
    a = np.zeros(10, 'uint8')
    a[i] = 1
    return a

a = one_hot(5) 
print(a)

出力

[0 0 0 0 0 1 0 0 0 0]
2
PM 2Ring

ここでの問題は、配列をどこにも保存しないことです。 put関数は配列の所定の位置で機能し、何も返しません。アレイに名前を付けないため、後でアドレスすることはできません。したがって、この

one_pos = 5
x = np.zeros(10)
np.put(x, one_pos, 1)

動作しますが、その後、単にインデックスを使用することができます:

one_pos = 5
x = np.zeros(10)
x[one_pos] = 1

私の意見では、特別な理由が存在しない場合、これを1つのライナーとして行う正しい方法です。これは読みやすいかもしれませんし、読みやすいコードは良いコードです。

2
m00am

マニュアル をざっと見てみると、np.putが値を返さないことがわかります。テクニックは問題ありませんが、結果配列の代わりにNoneにアクセスしています。

1次元配列の場合、特にこのような単純なケースでは、直接インデックスを使用することをお勧めします。

最小限の変更でコードを書き換える方法は次のとおりです。

arr = np.zeros(10)
np.put(arr, 5, 1)

putの代わりにインデックスを使用して2行目を行う方法は次のとおりです。

arr[5] = 1
2
Mad Physicist

パフォーマンスはわかりませんが、次のコードは機能し、きれいです。

x = np.array([0, 5])
x_onehot = np.identity(6)[x]
0
Ken Chan
import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
    a= np.repeat(0,10)
    np.put(a,l,1)
    z.append(a)
print("--- %s seconds ---" % (time.time() - start_time))

#--- 0.00174784660339 seconds ---

import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
    z.append(np.array([int(i == l) for i in range(10)]))
print("--- %s seconds ---" % (time.time() - start_time))

#--- 0.000400066375732 seconds ---
0