入力がゼロの場合、次のような配列を作成します。
[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行で実装できる方法はありますか?
通常、機械学習の分類用のワンホットエンコーディングを取得する場合、インデックスの配列があります。
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)
何かのようなもの :
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行で実行できないことです。
リスト内包表記を使用できます:
[0 if i !=5 else 1 for i in range(10)]
になります
[0,0,0,0,0,1,0,0,0,0]
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
np.put
は、配列argin-placeを変更します。 Pythonでは、インプレースミューテーションを実行してNone
を返す関数/メソッドの従来型です。 np.put
はその規則に従います。したがって、a
が1D配列であり、
a = np.put(a, 5, 1)
a
はNone
に置き換えられます。
コードはそれに似ていますが、名前のない配列を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]
ここでの問題は、配列をどこにも保存しないことです。 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つのライナーとして行う正しい方法です。これは読みやすいかもしれませんし、読みやすいコードは良いコードです。
マニュアル をざっと見てみると、np.put
が値を返さないことがわかります。テクニックは問題ありませんが、結果配列の代わりにNone
にアクセスしています。
1次元配列の場合、特にこのような単純なケースでは、直接インデックスを使用することをお勧めします。
最小限の変更でコードを書き換える方法は次のとおりです。
arr = np.zeros(10)
np.put(arr, 5, 1)
put
の代わりにインデックスを使用して2行目を行う方法は次のとおりです。
arr[5] = 1
パフォーマンスはわかりませんが、次のコードは機能し、きれいです。
x = np.array([0, 5])
x_onehot = np.identity(6)[x]
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 ---