Saya memiliki array 2D numpy dengan nilai yang berkisar dari 0 hingga 59.

Bagi mereka yang akrab dengan DL dan khususnya Segmentasi Gambar - Saya membuat array (sebut saja L) dari gambar .png dan nilai setiap piksel L[x,y] berarti kelas tempat piksel ini berada (di luar 60 kelas).

Saya ingin membuat tensor 1-hot - Lhot, di mana (Lhot[x,y,z] == 1) hanya jika (L[x,y] == z), dan 0 sebaliknya.

Saya ingin membuatnya dengan semacam penyiaran/pengindeksan (1,2 baris) - tanpa loop.

Itu harus secara fungsional sama dengan potongan kode ini (Dtype sesuai dengan L):

Lhot = np.zeros((L.shape[0], L.shape[1], 60), dtype=Dtype)
for i in range(L.shape[0]):
    for j in range(L.shape[1]):
        Lhot[i,j,L[i,j]] = 1

Ada yang punya ide? Terima kasih!

3
Itai Mesery 8 Agustus 2017, 01:49

2 jawaban

Jawaban Terbaik

Cara yang jauh lebih cepat dan lebih bersih menggunakan numpy murni

Lhot = np.transpose(np.eye(60)[L], (1,2,0))

Masalah yang akan Anda hadapi dengan one-hots multidimensi adalah mereka menjadi sangat besar dan sangat jarang dan tidak ada cara yang baik untuk menangani array jarang dengan lebih dari 2D di numpy/scipy (atau sklearn atau banyak paket ML lainnya menurut saya). Apakah Anda benar-benar membutuhkan n-d one-hot?

4
Daniel F 8 Agustus 2017, 07:37

Karena penyandian satu-panas khas didefinisikan untuk vektor 1D, yang harus Anda lakukan adalah meratakan matriks Anda, menggunakan satu pembuat enkode panas dari scikit-learn (atau perpustakaan lain dengan penyandian satu-panas) dan membentuk kembali.

from sklearn.preprocessing import OneHotEncoder
n, m = L.shape
k = 60
Lhot = np.array(OneHotEncoder(n_values=k).fit_transform(L.reshape(-1,1)).todense()).reshape(n, m, k)

Tentu saja Anda dapat melakukannya dengan tangan juga

n, m = L.shape
k = 60
Lhot = np.zeros((n*m, k)) # empty, flat array
Lhot[np.arange(n*m), L.flatten()] = 1 # one-hot encoding for 1D
Lhot = Lhot.reshape(n, m, k) # reshaping back to 3D tensor
3
lejlot 7 Agustus 2017, 23:11