Saya memiliki dua array numpy dengan bentuk yang berbeda, tetapi dengan panjang yang sama (dimensi terdepan). Saya ingin mengocok masing-masing, sehingga elemen yang sesuai terus berkorespondensi - yaitu mengocoknya bersamaan sehubungan dengan indeks utama mereka.
Kode ini berfungsi, dan menggambarkan tujuan saya:
def shuffle_in_unison(a, b):
assert len(a) == len(b)
shuffled_a = numpy.empty(a.shape, dtype=a.dtype)
shuffled_b = numpy.empty(b.shape, dtype=b.dtype)
permutation = numpy.random.permutation(len(a))
for old_index, new_index in enumerate(permutation):
shuffled_a[new_index] = a[old_index]
shuffled_b[new_index] = b[old_index]
return shuffled_a, shuffled_b
Sebagai contoh:
>>> a = numpy.asarray([[1, 1], [2, 2], [3, 3]])
>>> b = numpy.asarray([1, 2, 3])
>>> shuffle_in_unison(a, b)
(array([[2, 2],
[1, 1],
[3, 3]]), array([2, 1, 3]))
Namun, ini terasa kikuk, tidak efisien, dan lambat, dan perlu membuat salinan array - saya lebih suka mengocoknya di tempat, karena mereka akan cukup besar.
Apakah ada cara yang lebih baik untuk melakukan ini? Eksekusi lebih cepat dan penggunaan memori yang lebih rendah adalah tujuan utama saya, tetapi kode yang elegan juga bagus.
Satu pemikiran lain yang saya miliki adalah ini:
def shuffle_in_unison_scary(a, b):
rng_state = numpy.random.get_state()
numpy.random.shuffle(a)
numpy.random.set_state(rng_state)
numpy.random.shuffle(b)
Ini berfungsi ... tapi ini sedikit menakutkan, karena saya melihat sedikit jaminan itu akan terus bekerja - itu tidak terlihat seperti hal yang dijamin untuk bertahan hidup di seluruh versi numpy, misalnya.
Jawaban:
Solusi "menakutkan" Anda tidak tampak menakutkan bagi saya. Memanggil
shuffle()
dua urutan dengan panjang yang sama menghasilkan jumlah panggilan yang sama ke generator angka acak, dan ini adalah satu-satunya elemen "acak" dalam algoritma shuffle. Dengan mengatur ulang keadaan, Anda memastikan bahwa panggilan ke generator nomor acak akan memberikan hasil yang sama pada panggilan keduashuffle()
, sehingga seluruh algoritme akan menghasilkan permutasi yang sama.Jika Anda tidak suka ini, solusi yang berbeda adalah menyimpan data Anda dalam satu array bukan dua sejak awal, dan membuat dua tampilan ke dalam array tunggal ini mensimulasikan dua array yang Anda miliki sekarang. Anda dapat menggunakan array tunggal untuk pengocokan dan tampilan untuk semua tujuan lain.
Contoh: Mari kita asumsikan array
a
danb
terlihat seperti ini:Kami sekarang dapat membuat satu array yang berisi semua data:
Sekarang kami membuat tampilan yang mensimulasikan yang asli
a
danb
:Data
a2
danb2
dibagikan denganc
. Untuk mengocok kedua array secara bersamaan, gunakannumpy.random.shuffle(c)
.Dalam kode produksi, Anda tentu saja akan mencoba untuk menghindari membuat yang asli
a
danb
sama sekali dan segera membuatc
,a2
danb2
.Solusi ini dapat disesuaikan dengan kasus itu
a
danb
memiliki dtypes yang berbeda.sumber
numpy.random.shuffle()
beroperasi pada urutan yang bisa berubah-ubah, seperti daftar Python atau array NumPy. Bentuk array tidak masalah, hanya panjang urutannya. Ini sangat tidak mungkin berubah menurut pendapat saya.Anda dapat menggunakan pengindeksan array NumPy :
Ini akan menghasilkan penciptaan array yang dikocok secara terpisah.
sumber
>>> t = timeit.Timer(stmt = "<function>(a,b)", setup = "import numpy as np; a,b = np.arange(4), np.arange(4*20).reshape((4,20))")>>> t.timeit()
dan mendapatkan 38 detik untuk versi OP, dan 27,5 detik untuk saya, masing-masing untuk 1 juta panggilan.a.shape
adalah(31925, 405)
danb.shape
sekarang(31925,)
.Untuk mempelajari lebih lanjut, lihat http://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html
sumber
Solusi yang sangat sederhana:
kedua array x, y sekarang keduanya diacak secara acak dengan cara yang sama
sumber
James menulis pada tahun 2015 solusi sklearn yang sangat membantu. Namun dia menambahkan variabel keadaan acak, yang tidak diperlukan. Dalam kode di bawah ini, keadaan acak dari numpy diasumsikan secara otomatis.
sumber
sumber
Kocok sejumlah array secara bersamaan, di tempat, hanya menggunakan NumPy.
Dan bisa digunakan seperti ini
Beberapa hal yang perlu diperhatikan:
Setelah acak, data dapat dipisah menggunakan
np.split
atau direferensikan menggunakan irisan - tergantung pada aplikasi.sumber
RandomState
dapat digunakan di luar loop. Lihat jawabanfor
loop adalah apakah akan menetapkan kembali atau memulai kembali keadaan acak. Dengan jumlah array yang diteruskan ke fungsi pengocokan diharapkan kecil, saya tidak akan mengharapkan perbedaan kinerja antara keduanya. Tapi ya, rstate dapat ditugaskan di luar loop dan di-reseed di dalam loop pada setiap iterasi.Anda dapat membuat array seperti:
lalu kocok:
sekarang gunakan ini sebagai argumen dari array Anda. argumen dikocok yang sama mengembalikan vektor dikocok yang sama.
sumber
Salah satu cara di mana pengocokan di tempat dapat dilakukan untuk daftar terhubung adalah menggunakan seed (itu bisa acak) dan menggunakan numpy.random.shuffle untuk melakukan pengocokan.
Itu dia. Ini akan mengocok a dan b dengan cara yang sama persis. Ini juga dilakukan di tempat yang selalu merupakan nilai tambah.
Sunting, jangan gunakan np.random.seed () gunakan np.random.RandomState sebagai gantinya
Saat memanggilnya, berikan saja biji apa saja untuk memberi makan kondisi acak:
Keluaran:
Sunting: Memperbaiki kode untuk menabur kembali keadaan acak
sumber
RandomState
perubahan status pada panggilan pertama dana
danb
tidak dikocok bersamaan.Ada fungsi terkenal yang bisa menangani ini:
Hanya dengan menetapkan test_size ke 0 akan menghindari pemisahan dan memberikan Anda data acak. Meskipun biasanya digunakan untuk membagi data kereta dan menguji, itu mengocoknya juga.
Dari dokumentasi
sumber
Katakanlah kita memiliki dua array: a dan b.
Pertama-tama kita dapat memperoleh indeks baris dengan mengijinkan permutasi dimensi pertama
Kemudian gunakan pengindeksan lanjutan. Di sini kita menggunakan indeks yang sama untuk mengocok kedua array secara bersamaan.
Ini setara dengan
sumber
Jika Anda ingin menghindari menyalin array, maka saya akan menyarankan bahwa alih-alih menghasilkan daftar permutasi, Anda pergi melalui setiap elemen dalam array, dan menukar secara acak ke posisi lain dalam array
Ini mengimplementasikan algoritma shuffle Knuth-Fisher-Yates.
sumber
len(a)
denganreversed(range(1, len(a)))
. Tapi toh itu tidak akan sangat efisien.Ini sepertinya solusi yang sangat sederhana:
sumber
Dengan sebuah contoh, inilah yang saya lakukan:
sumber
combo = zip(images, labels); shuffle(combo); im, lab = zip(*combo)
, hanya lebih lambat. Karena Anda tetap menggunakan Numpy, solusi yang jauh lebih cepat adalahcombo = np.c_[images, labels]
meng -zip array menggunakan Numpy , shuffle, dan unzip lagiimages, labels = combo.T
. Dengan asumsi bahwalabels
danimages
merupakan array Numpy satu dimensi dengan panjang yang sama untuk memulai, ini akan dengan mudah solusi tercepat. Jika mereka multidimensi, lihat jawaban saya di atas.Saya menambah python secara acak.shuffle () untuk mengambil argumen kedua:
Dengan begitu saya bisa yakin bahwa pengocokan terjadi di tempat, dan fungsinya tidak terlalu panjang atau rumit.
sumber
Cukup gunakan
numpy
...Pertama menggabungkan dua array input array 1D adalah label (y) dan array 2D adalah data (x) dan mengocoknya dengan
shuffle
metode NumPy . Akhirnya pisahkan mereka dan kembali.sumber