Keturunan gradien stokastik berdasarkan pada operasi vektor?

10

mari kita asumsikan bahwa saya ingin melatih algoritma regresi penurunan gradien stokastik menggunakan dataset yang memiliki sampel N. Karena ukuran dataset sudah diperbaiki, saya akan menggunakan kembali data T kali. Pada setiap iterasi atau "zaman", saya menggunakan masing-masing sampel pelatihan tepat satu kali setelah secara acak memesan kembali seluruh rangkaian pelatihan.

Implementasi saya didasarkan pada Python dan Numpy. Oleh karena itu, menggunakan operasi vektor dapat sangat mengurangi waktu komputasi. Datang dengan implementasi vektor keturunan gradien batch cukup mudah. Namun, dalam kasus keturunan gradien stokastik saya tidak bisa mencari cara untuk menghindari loop luar yang berulang melalui semua sampel di setiap zaman.

Adakah yang tahu implementasi vektor dari penurunan gradien stokastik?

EDIT : Saya ditanya mengapa saya ingin menggunakan gradient descent online jika ukuran dataset saya diperbaiki.

Dari [1], orang dapat melihat bahwa penurunan gradien online menyatu lebih lambat dari penurunan gradien batch ke minimum biaya empiris. Namun, konvergen lebih cepat ke minimum biaya yang diharapkan, yang mengukur kinerja generalisasi. Saya ingin menguji dampak dari hasil teoritis ini dalam masalah khusus saya, dengan cara validasi silang. Tanpa implementasi vectorized, kode online gradient descent saya jauh lebih lambat daripada batch gradient descent. Itu sangat meningkatkan waktu yang diperlukan untuk proses validasi silang untuk diselesaikan.

EDIT : Saya menyertakan di sini pseudocode implementasi gradient descent on-line saya, seperti yang diminta oleh teman. Saya memecahkan masalah regresi.

Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)

Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
    Randomly shuffle training samples
    for each training sample i:
        Compute error for training sample i
        Update coefficients based on the error above
    prev_error = error
    Calculate outputs F
    error = sum((F-Y)^2)/n
    it = it + 1

[1] "Pembelajaran Online Skala Besar", L. Bottou, Y. Le Cunn, NIPS 2003.

Pablo Suau
sumber
2
Pisahkan dataset menjadi mini-batch dan sesuaikan model ke setiap mini-batch secara berurutan.
Berteman
Terima kasih @ teman. Namun, itu tidak akan menjadi implementasi on-line murni.
Pablo Suau
1
Apa alasan untuk menggunakan implementasi "murni online" jika dataset Anda diperbaiki? SGD hanya mengatakan bahwa Anda tidak perlu mengulangi seluruh dataset sekaligus, tetapi dapat membaginya menjadi beberapa bagian yang acak (mini-batch) dan memprosesnya satu per satu. Mini-batch ukuran 1 hanya masuk akal ketika Anda memiliki sumber data yang berkelanjutan dan mungkin tidak ada habisnya (seperti umpan twitter, misalnya) dan ingin memperbarui model setelah setiap pengamatan baru. Tapi itu kasus yang sangat langka dan jelas bukan untuk dataset tetap.
Berteman
Maaf atas tanggapan saya yang terlambat. Harap periksa teks yang saya tambahkan ke pertanyaan awal.
Pablo Suau
1
Bisakah Anda menunjukkan implementasi Anda? Saya melihat kesalahpahaman, tetapi tanpa sampel kode akan sulit untuk menjelaskannya.
Berteman

Jawaban:

10

Pertama-tama, kata "sampel" biasanya digunakan untuk menggambarkan subset populasi , jadi saya akan merujuk hal yang sama dengan "contoh".

Implementasi SGD Anda lambat karena baris ini:

for each training example i:

Di sini Anda secara eksplisit menggunakan tepat satu contoh untuk setiap pembaruan parameter model. Menurut definisi, vektorisasi adalah teknik untuk mengubah operasi pada satu elemen menjadi operasi pada vektor elemen tersebut. Jadi, tidak, Anda tidak dapat memproses contoh satu per satu dan masih menggunakan vektorisasi.

Namun, Anda dapat memperkirakan SGD sebenarnya dengan menggunakan mini-batch . Mini-batch adalah sebagian kecil dari dataset asli (misalnya, 100 contoh). Anda menghitung kesalahan dan pembaruan parameter berdasarkan mini-batch, tetapi Anda masih menggunakannya berulang kali tanpa optimasi global, membuat proses menjadi stokastik. Jadi, untuk membuat implementasi Anda lebih cepat, cukup mengubah baris sebelumnya menjadi:

batches = split dataset into mini-batches
for batch in batches: 

dan menghitung kesalahan dari batch, bukan dari satu contoh.

Meskipun cukup jelas, saya juga harus menyebutkan vektorisasi pada tingkat per-contoh. Artinya, bukannya sesuatu seperti ini:

theta = np.array([...])  # parameter vector
x = np.array([...])      # example
y = 0                    # predicted response
for i in range(len(example)):
    y += x[i] * theta[i]
error = (true_y - y) ** 2  # true_y - true value of response

Anda pasti harus melakukan sesuatu seperti ini:

error = (true_y - sum(np.dot(x, theta))) ** 2

yang, sekali lagi, mudah digeneralisasi untuk mini-batch:

true_y = np.array([...])     # vector of response values
X = np.array([[...], [...]]) # mini-batch
errors = true_y - sum(np.dot(X, theta), 1)
error = sum(e ** 2 for e in errors)
teman
sumber
1
Saya pikir ini adalah cara untuk pergi. Mini-batch dengan ukuran yang dipilih benar-benar dapat konvergen lebih cepat daripada versi batch atau online (sebelumnya hanya memperbarui bobot sekali per set keseluruhan, dan yang terakhir tidak dapat di-vektorisasi, plus memiliki langkah-langkah pembaruan berat tambahan lebih sering)
Neil Slater
Terima kasih semuanya. Permintaan maaf untuk keras kepala menolak batch mini sebelumnya, tapi saya tidak yakin implikasi dari metode ini pada tingkat konvergensi. Neil, apakah penegasan Anda berasal dari pengalaman Anda sendiri, atau adakah hasil teoretis / empiris yang dipublikasikan?
Pablo Suau
1
@PabloSuau Anda dapat memeriksa kelas Machine Learning Andrew Ng di Coursera, 10 minggu, ia menjelaskan mengapa konvergensi bisa lebih cepat daripada SGD dan batch GD. Untuk lebih tepatnya: itu harus selalu secepat SGD, tetapi kadang-kadang harus lebih cepat dalam praktek.
Gaborous
1

Lihatlah metode partial_fit dari classifier SGD scikit . Anda memiliki kendali atas apa yang Anda panggil dengannya: Anda dapat melakukannya dengan belajar online "benar" dengan melewatkan sebuah instance pada satu waktu, atau Anda dapat mengelompokkan instance menjadi mini-batch jika semua data Anda tersedia dalam array. Jika ya, Anda dapat mengiris array untuk menyediakan minibatch.

Ben Allison
sumber