Cara menerapkan gradien softmax di backprop

8

Saya baru-baru melakukan pekerjaan rumah di mana saya harus belajar model untuk klasifikasi 10 digit MNIST. HW memiliki beberapa kode perancah dan saya seharusnya bekerja dalam konteks kode ini.

Pekerjaan rumah saya bekerja / lulus tes tetapi sekarang saya mencoba untuk melakukan semuanya dari awal (kerangka kerja saya sendiri, tidak ada kode perancah hw) dan saya terjebak menerapkan grandient dari softmax pada langkah backprop, dan bahkan berpikir apa hw kode scaffolding mungkin tidak benar.

Hw meminta saya menggunakan apa yang mereka sebut 'kerugian softmax' sebagai simpul terakhir di nn. Yang berarti, untuk beberapa alasan mereka memutuskan untuk bergabung dengan aktivasi softmax dengan cross entropy loss secara keseluruhan, alih-alih memperlakukan softmax sebagai fungsi aktivasi dan cross entropy sebagai fungsi loss terpisah.

Fungsi hw loss kemudian terlihat seperti ini (minimal diedit oleh saya):

class SoftmaxLoss:
    """
    A batched softmax loss, used for classification problems.
    input[0] (the prediction) = np.array of dims batch_size x 10
    input[1] (the truth) = np.array of dims batch_size x 10
    """
    @staticmethod
    def softmax(input):
        exp = np.exp(input - np.max(input, axis=1, keepdims=True))
        return exp / np.sum(exp, axis=1, keepdims=True)

    @staticmethod
    def forward(inputs):
        softmax = SoftmaxLoss.softmax(inputs[0])
        labels = inputs[1]
        return np.mean(-np.sum(labels * np.log(softmax), axis=1))

    @staticmethod
    def backward(inputs, gradient):
        softmax = SoftmaxLoss.softmax(inputs[0])
        return [
            gradient * (softmax - inputs[1]) / inputs[0].shape[0],
            gradient * (-np.log(softmax)) / inputs[0].shape[0]
        ]

Seperti yang Anda lihat, pada maju tidak softmax (x) dan kemudian lintas kehilangan entropi.

Tetapi pada backprop, tampaknya hanya melakukan turunan dari cross entropy dan bukan dari softmax. Softmax dibiarkan seperti itu.

Bukankah seharusnya juga mengambil turunan dari softmax sehubungan dengan input ke softmax?

Dengan asumsi bahwa itu harus mengambil turunan dari softmax, saya tidak yakin bagaimana hw ini benar-benar lulus tes ...

Sekarang, dalam implementasi saya sendiri dari awal, saya membuat softmax dan cross entropy node yang terpisah, seperti itu (p dan t berarti prediksi dan kebenaran):

class SoftMax(NetNode):
    def __init__(self, x):
        ex = np.exp(x.data - np.max(x.data, axis=1, keepdims=True))
        super().__init__(ex / np.sum(ex, axis=1, keepdims=True), x)

    def _back(self, x):
        g = self.data * (np.eye(self.data.shape[0]) - self.data)
        x.g += self.g * g
        super()._back()

class LCE(NetNode):
    def __init__(self, p, t):
        super().__init__(
            np.mean(-np.sum(t.data * np.log(p.data), axis=1)),
            p, t
        )

    def _back(self, p, t):
        p.g += self.g * (p.data - t.data) / t.data.shape[0]
        t.g += self.g * -np.log(p.data) / t.data.shape[0]
        super()._back()

Seperti yang Anda lihat, cross entropy loss (LCE) saya memiliki turunan yang sama dengan yang ada di hw, karena itu adalah turunan dari kerugian itu sendiri, tanpa masuk ke softmax.

Tapi kemudian, saya masih harus melakukan turunan softmax untuk rantai itu dengan turunan dari kerugian. Di sinilah saya terjebak.

Untuk softmax didefinisikan sebagai:

Sebuah

Derivatif biasanya didefinisikan sebagai:

b

Tapi saya butuh turunan yang menghasilkan tensor dengan ukuran yang sama dengan input ke softmax, dalam hal ini, batch_size x 10. Jadi saya tidak yakin bagaimana yang di atas harus diterapkan pada hanya 10 komponen, karena ini menyiratkan bahwa saya akan membedakan semua input sehubungan dengan semua output (semua kombinasi) atau cdalam bentuk matriks.

SaldaVonSchwartz
sumber
Saya pikir Anda harus memposting ini dalam codereview atau stackoverflow
DuttaA
Mengapa? itu adalah neural net, pertanyaan backprop. Itu termasuk dalam pertukaran tumpukan AI.
siapa pun yang menolak saya mungkin tidak terlalu berpengalaman dalam AI ... mari kita lihat, pertanyaannya adalah tentang menerapkan turunan parsial dalam konteks propagasi kembali, dalam konteks jaringan saraf, dalam konteks pembelajaran mesin, dalam konteks pembelajaran yang diawasi, dalam konteks 'AI'. Apa bagian dari ini: 1- menunjukkan kurangnya penelitian 2-tidak terkait dengan 'AI', 3- adalah jenis pertanyaan 'kirim saya kodez', 4- adalah pertanyaan opini 5- terlalu luas pertanyaan ?
Dari ai.se faq "dan ini bukan tentang ... implementasi pembelajaran mesin"
mico
@ mico ok saya mengerti, ya, sejauh faq Anda benar. Tetapi saya merasa itu tidak terduga. Maksud saya, mendiskusikan matematika dan implementasi AI algos adalah praktik umum di lapangan (termasuk di tingkat akademik).
SaldaVonSchwartz

Jawaban:

5

Setelah lebih lanjut mengerjakan ini, saya menemukan bahwa:

  1. Implementasi pekerjaan rumah menggabungkan softmax dengan cross entropy loss sebagai pilihan, sementara pilihan saya untuk menjaga softmax terpisah sebagai fungsi aktivasi juga valid.

  2. Implementasi pekerjaan rumah memang kehilangan turunan softmax untuk pass backprop.

  3. Gradien dari softmax sehubungan dengan inputnya adalah benar-benar bagian dari setiap output sehubungan dengan setiap input:

gradient1

Jadi untuk bentuk vektor (gradien): gradient2

Yang dalam kode numpy vektorized saya hanya:

self.data * (1. - self.data)

Di mana self.datasoftmax input, yang sebelumnya dihitung dari umpan maju.

SaldaVonSchwartz
sumber
3
Saya pikir ini tidak benar. Anda juga harus menghitung smax (x_i) / x_j, di mana j ≠ i dan menjumlahkan semua gradien individual. Ini karena ketika menghitung softmax untuk x_i, semua parameter lain juga digunakan untuk menentukan nilai softmax.
harveyslash