numpy.array berperilaku aneh dengan / = operator?

Sep 11 2020

Saya mencoba menormalkan larik angka ke kisaran (0, 1] sehingga saya dapat menggunakannya sebagai bobot untuk random.choice () berbobot, jadi saya memasukkan baris ini:

# weights is a nonzero numpy.array
weights /= weights.max()

Namun, Pycharm mengatakan ada parameter yang tidak terisi ke max()fungsi ( Parameter 'initial' unfilled). Saya mencoba ini di REPL dengan operator / = dan dengan divisi "reguler" ( a = a / b) dan mendapatkan hasil yang berbeda untuk keduanya dan kesalahan yang berbeda dari yang diperkirakan Pycharm:

>>> a = numpy.array([1,2,3])
>>> a.max()
3
>>> a /= a.max()
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    a /= a.max()
TypeError: No loop matching the specified signature and casting was found for ufunc true_divide
>>> a = a/a.max()
>>> a
array([0.33333333, 0.66666667, 1.        ])

Saya juga menyadari bahwa untuk acak berbobot, bobot harus dijumlahkan menjadi satu daripada dinormalisasi. Tetapi membaginya dengan jumlah menghasilkan hal yang sama persis TypeErrormenggunakan operasi / = (tetapi Pycharm berpikir ini baik-baik saja):

>>> a = numpy.array([1,2,3])
>>> sum(a)
6
>>> a
array([1, 2, 3])
>>> a /= sum(a)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a /= sum(a)
TypeError: No loop matching the specified signature and casting was found for ufunc true_divide
>>> a = a / sum(a)
>>> a
array([0.16666667, 0.33333333, 0.5       ])

Apa yang saya temukan di sini? Apakah ini bug aneh di Numpy atau apakah operator / = memiliki kegunaan yang berbeda atau sesuatu? Saya tahu mereka menggunakan __truediv__dan __itruediv__tetapi saya tidak dapat melihat mengapa yang satu memiliki masalah dan yang lainnya tidak. Saya telah mengonfirmasi perilaku ini dengan versi terbaru Numpy dari pip (1.19.2 di Windows x64).

Jawaban

1 Fahim Sep 11 2020 at 23:24

Itu karena numpy peduli pada tipenya. Saat Anda menerapkan pembagian, Anda berubah intmenjadi float. Tapi numpy tidak akan membiarkan Anda melakukan itu! Itulah mengapa nilai-nilai Anda harus sudah ada float. Coba ini:

>>> a = np.array([1.0,2.0,3.0])
>>> a /= sum(a)
>>> a
array([0.16666667, 0.33333333, 0.5       ])

Tetapi mengapa yang lainnya berhasil? Itu karena itu bukan operasi "di tempat". Karenanya lokasi memori baru sedang dibuat. Variabel baru, tipe baru, maka numpy tidak peduli disini.