Dari Memecahkan Persamaan hingga Pembelajaran Mendalam: Tutorial Python TensorFlow

Diterbitkan: 2022-03-11

Ada beberapa perkembangan luar biasa akhir-akhir ini di dunia kecerdasan buatan, dari banyak kemajuan yang dipublikasikan dengan mobil self-driving hingga mesin yang sekarang membuat tiruan Chopin atau hanya menjadi sangat ahli dalam video game.

Inti dari kemajuan ini adalah sejumlah alat untuk membantu memperoleh pembelajaran mendalam dan model pembelajaran mesin lainnya, dengan Torch, Caffe, dan Theano di antara yang terdepan. Namun, sejak Google Brain menjadi open source pada November 2015 dengan kerangka kerja mereka sendiri, TensorFlow, kami telah melihat popularitas pustaka perangkat lunak ini meroket menjadi kerangka kerja pembelajaran mendalam yang paling populer.

TensorFlow

Mengapa ini terjadi? Alasannya termasuk banyaknya dukungan dan dokumentasi yang tersedia, kesiapan produksinya, kemudahan mendistribusikan perhitungan di berbagai perangkat, dan alat visualisasi yang sangat baik: TensorBoard.

Pada akhirnya, TensorFlow berhasil menggabungkan serangkaian fitur teknis yang komprehensif dan fleksibel dengan sangat mudah digunakan.

Dalam artikel ini, Anda akan memperoleh pemahaman tentang mekanisme alat ini dengan menggunakannya untuk memecahkan masalah numerik umum, cukup di luar apa yang biasanya melibatkan pembelajaran mesin, sebelum memperkenalkan penggunaannya dalam pembelajaran mendalam dengan implementasi jaringan saraf sederhana.

Sebelum kamu memulai

Pengetahuan dasar tentang metode pembelajaran mesin diasumsikan. Jika Anda perlu mengejar ketinggalan, lihat posting yang sangat berguna ini.

Karena kami akan mendemonstrasikan API Python, pemahaman tentang Numpy juga bermanfaat.

Untuk menyiapkan TensorFlow, ikuti petunjuk yang ada di sini.

Jika Anda menggunakan Windows, perlu diperhatikan bahwa, pada saat penulisan, Anda harus menggunakan Python 3.4+, bukan 2.7.

Kemudian ketika Anda siap, Anda harus dapat mengimpor perpustakaan dengan:

 import tensorflow as tf

Langkah 1 dari 2 ke Solusi TensorFlow: Buat Grafik

Konstruksi program TensorFlow umumnya terdiri dari dua langkah utama, yang pertama adalah membuat grafik komputasi, yang akan menjelaskan komputasi yang ingin Anda lakukan, tetapi tidak benar-benar menjalankannya atau menyimpan nilai apa pun.

Seperti halnya grafik apa pun, kami memiliki simpul dan tepi. Tepi mewakili tensor, tensor mewakili array n-dimensi. Misalnya, tensor dengan dimensi (atau peringkat dalam bahasa TensorFlow) 0 adalah skalar, peringkat 1 vektor, peringkat 2 matriks dan seterusnya.

Node mewakili operasi yang menghasilkan tensor keluaran, mengambil tensor sebagai masukan jika diperlukan. Operasi tersebut meliputi penambahan ( tf.add ), perkalian matriks ( tf.matmul ), dan juga pembuatan konstanta ( tf.constant ).

Jadi, mari gabungkan beberapa di antaranya untuk grafik pertama kita.

 a = tf.constant([2.5, 2]) b = tf.constant([3, 6], dtype=tf.float32) total = tf.add(a, b)

Di sini kita telah membuat tiga operasi, dua di antaranya untuk membuat array 1-d yang konstan.

Tipe data disimpulkan dari argumen nilai yang diteruskan, atau Anda dapat menunjukkannya dengan argumen dtype . Jika saya tidak melakukan ini untuk b , maka int32 akan disimpulkan dan kesalahan dilemparkan karena tf.add akan mencoba mendefinisikan tambahan pada dua jenis yang berbeda.

Langkah 2 dari 2 ke Solusi TensorFlow: Jalankan Operasi

Grafik sudah ditentukan, tetapi untuk benar-benar melakukan perhitungan apa pun di atasnya (atau bagian mana pun darinya), kita harus menyiapkan Sesi TensorFlow.

 sess = tf.Session()

Atau, jika kita menjalankan sesi di shell interaktif, seperti IPython, maka kita menggunakan:

 sess = tf.InteractiveSession()

Metode run pada objek session adalah salah satu cara untuk mengevaluasi Tensor.

Oleh karena itu, untuk mengevaluasi perhitungan penambahan yang didefinisikan di atas, kami meneruskan 'total', Tensor untuk diambil, yang mewakili output dari tf.add op.

 print(sess.run(total)) # [ 5.5 8. ]

Pada titik ini, kami memperkenalkan kelas Variabel TensorFlow. Sedangkan konstanta adalah bagian tetap dari definisi grafik, variabel dapat diperbarui. Konstruktor kelas memerlukan nilai awal, tetapi meskipun demikian, variabel memerlukan operasi untuk menginisialisasinya secara eksplisit sebelum operasi lain pada variabel tersebut dilakukan.

Variabel memegang status grafik dalam sesi tertentu sehingga kita harus mengamati apa yang terjadi dengan beberapa sesi menggunakan grafik yang sama untuk lebih memahami variabel.

 # Create a variable with an initial value of 1 some_var = tf.Variable(1) # Create op to run variable initializers init_op = tf.global_variables_initializer() # Create an op to replace the value held by some_var to 3 assign_op = some_var.assign(3) # Set up two instances of a session sess1 = tf.Session() sess2 = tf.Session() # Initialize variables in both sessions sess1.run(init_op) sess2.run(init_op) print(sess1.run(some_var)) # Outputs 1 # Change some_var in session1 sess1.run(assign_op) print(sess1.run(some_var)) # Outputs 3 print(sess2.run(some_var)) # Outputs 1 # Close sessions sess1.close() sess2.close()

Kami telah menyiapkan grafik dan dua sesi.

Setelah menjalankan inisialisasi pada kedua sesi (jika kami tidak menjalankan ini dan kemudian mengevaluasi variabel, kami menemukan kesalahan), kami hanya menjalankan operasi penugasan pada satu sesi. Seperti yang bisa dilihat, nilai variabel tetap ada, tetapi tidak di seluruh sesi.

Memberi Makan Grafik untuk Mengatasi Masalah Numerik

Konsep penting lainnya dari TensorFlow adalah placeholder. Sementara variabel menahan status, placeholder digunakan untuk menentukan input apa yang dapat diharapkan grafik dan tipe datanya (dan opsional bentuknya). Kemudian kami dapat memasukkan data ke dalam grafik melalui placeholder ini saat kami menjalankan komputasi.

Grafik TensorFlow mulai menyerupai jaringan saraf yang pada akhirnya ingin kita latih, tetapi sebelum itu, mari gunakan konsep untuk memecahkan masalah numerik umum dari dunia keuangan.

Misalkan kita ingin mencari y dalam persamaan seperti ini:

v = Ce -0,5y + Ce -y +Ce -1,5y +(C+P)e -2y

untuk v tertentu (dengan konstanta C dan P ).

Ini adalah formula untuk menghitung imbal hasil hingga jatuh tempo ( y ) pada obligasi dengan nilai pasar v , pokok P , dan kupon C yang dibayarkan setiap setengah tahun tetapi dengan arus kas yang didiskontokan dengan peracikan berkelanjutan.

Kami pada dasarnya harus menyelesaikan persamaan seperti ini dengan coba-coba, dan kami akan memilih metode bagi dua untuk membidik nilai akhir kami untuk y .

Pertama, kita akan memodelkan masalah ini sebagai grafik TensorFlow.

C dan P adalah konstanta tetap dan merupakan bagian dari definisi grafik kita. Kami ingin memiliki proses yang memperhalus batas bawah dan atas y . Oleh karena itu, batas-batas ini (dilambangkan a dan b ) adalah kandidat yang baik untuk variabel yang perlu diubah setelah setiap tebakan y (dianggap sebagai titik tengah a dan b ).

 # Specify the values our constant ops will output C = tf.constant(5.0) P = tf.constant(100.0) # We specify the initial values that our lower and upper bounds will be when initialised. # Obviously the ultimate success of this algorithm depends on decent start points a = tf.Variable(-10.0) b = tf.Variable(10.0) # We expect a floating number to be inserted into the graph v_target = tf.placeholder("float") # Remember the following operations are definitions, # none are carried out until an operation is evaluated in a session! y = (a+b)/2 v_guess = C*tf.exp(-0.5*y) + C*tf.exp(-y) + C*tf.exp(-1.5*y) + (C + P)*tf.exp(-2*y) # Operations to set temporary values (a_ and b_) intended to be the next values of a and b. # eg if the guess results in av greater than the target v, # we will set a_ to be the current value of y a_ = tf.where(v_guess > v_target, y, a) b_ = tf.where(v_guess < v_target, y, b) # The last stage of our graph is to assign the two temporary vals to our variables step = tf.group( a.assign(a_), b.assign(b_) )

Jadi kami sekarang memiliki daftar operasi dan variabel, yang mana saja dapat dievaluasi terhadap sesi tertentu. Beberapa operasi ini bergantung pada operasi lain untuk dijalankan, jadi menjalankan, katakanlah, v_guess akan memicu reaksi berantai agar tensor lain, seperti C dan P , dievaluasi terlebih dahulu.

Beberapa dari operasi ini bergantung pada placeholder yang nilainya perlu ditentukan, jadi bagaimana sebenarnya kita memasukkan nilai itu?

Ini dilakukan melalui argumen feed_dict di fungsi run itu sendiri.

Jika kami ingin mengevaluasi a_ , kami memasukkan nilai untuk placeholder kami v_target , seperti:

 sess.run(a_, feed_dict={v_target: 100})

memberi kita 0,0.

Pasang v_target 130 dan kita mendapatkan -10.0.

Ini adalah operasi "langkah" kami yang sebenarnya membutuhkan semua operasi lain untuk dilakukan sebagai prasyarat dan pada dasarnya mengeksekusi seluruh grafik. Ini juga merupakan operasi yang benar-benar mengubah status aktual di seluruh sesi kami. Oleh karena itu, semakin banyak kita menjalankan langkah, semakin kita secara bertahap mendorong variabel a dan b ke nilai sebenarnya dari y .

Jadi, misalkan nilai kita untuk v dalam persamaan kita sama dengan 95. Mari kita buat sesi dan jalankan grafik kita di atasnya 100 kali.

 # Set up a session and initialize variables sess = tf.Session() tf.global_variables_initializer().run() # Run the step operation (and therefore whole graph) 100 times for i in range (100): sess.run(step, feed_dict={v_target:95})

Jika kita mengevaluasi tensor y sekarang, kita mendapatkan sesuatu yang menyerupai jawaban yang diinginkan

 print(sess.run(y)) # 0.125163

Jaringan Saraf

Sekarang setelah kita memahami mekanisme TensorFlow, kita dapat menggabungkannya dengan beberapa operasi pembelajaran mesin tambahan yang ada di TensorFlow untuk melatih jaringan saraf sederhana.

Di sini, kami ingin mengklasifikasikan titik data pada sistem koordinat 2d tergantung pada apakah mereka termasuk dalam wilayah tertentu—lingkaran dengan radius 0,5 yang berpusat di titik asal.

Tentu saja, ini dapat diverifikasi secara konkret hanya dengan memeriksa titik tertentu (a,b) jika a^2 + b^2 < 0.5 , tetapi untuk tujuan eksperimen pembelajaran mesin ini, kami ingin memasukkan a set pelatihan: Serangkaian poin acak dan apakah mereka termasuk dalam wilayah yang kami tuju. Inilah salah satu cara untuk membuatnya:

 import numpy as np NO_OF_RANDOM_POINTS = 100 CIRCLE_RADIUS = 0.5 random_spots = np.random.rand(NO_OF_RANDOM_POINTS, 2) * 2 - 1 is_inside_circle = (np.power(random_spots[:,0],2) + np.power(random_spots[:,1],2) < CIRCLE_RADIUS).astype(int)

Kami akan membuat jaringan saraf dengan karakteristik sebagai berikut:

  1. Ini terdiri dari lapisan input dengan dua node, di mana kami memberi makan seri vektor dua dimensi kami yang terkandung dalam "random_spots". Ini akan diwakili oleh placeholder yang menunggu data pelatihan.
  2. Lapisan keluaran juga akan memiliki dua simpul, jadi kita perlu memasukkan rangkaian label pelatihan (“is_inside_circle”) ke dalam placeholder untuk skalar, dan kemudian mengubah nilai-nilai itu menjadi vektor dua dimensi satu-panas.
  3. Kami akan memiliki satu lapisan tersembunyi yang terdiri dari tiga node, jadi kami perlu menggunakan variabel untuk matriks bobot dan vektor bias kami, karena ini adalah nilai yang perlu disempurnakan saat melakukan pelatihan.
 INPUT_LAYER_SIZE = 2 HIDDEN_LAYER_SIZE = 3 OUTPUT_LAYER_SIZE = 2 # Starting values for weights and biases are drawn randomly and uniformly from [-1, 1] # For example W1 is a matrix of shape 2x3 W1 = tf.Variable(tf.random_uniform([INPUT_LAYER_SIZE, HIDDEN_LAYER_SIZE], -1, 1)) b1 = tf.Variable(tf.random_uniform([HIDDEN_LAYER_SIZE], -1, 1)) W2 = tf.Variable(tf.random_uniform([HIDDEN_LAYER_SIZE, OUTPUT_LAYER_SIZE], -1, 1)) b2 = tf.Variable(tf.random_uniform([OUTPUT_LAYER_SIZE], -1, 1)) # Specifying that the placeholder X can expect a matrix of 2 columns (but any number of rows) # representing random spots X = tf.placeholder(tf.float32, [None, INPUT_LAYER_SIZE]) # Placeholder Y can expect integers representing whether corresponding point is in the circle # or not (no shape specified) Y = tf.placeholder(tf.uint8) # An op to convert to a one hot vector onehot_output = tf.one_hot(Y, OUTPUT_LAYER_SIZE)

Untuk melengkapi definisi grafik kita, kita mendefinisikan beberapa operasi yang akan membantu kita melatih variabel untuk mencapai pengklasifikasi yang lebih baik. Ini termasuk perhitungan matriks, fungsi aktivasi, dan pengoptimal.

 LEARNING_RATE = 0.01 # Op to perform matrix calculation X*W1 + b1 hidden_layer = tf.add(tf.matmul(X, W1), b1) # Use sigmoid activation function on the outcome activated_hidden_layer = tf.sigmoid(hidden_layer) # Apply next weights and bias (W2, b2) to hidden layer and then apply softmax function # to get our output layer (each vector adding up to 1) output_layer = tf.nn.softmax(tf.add(tf.matmul(activated_hidden_layer, W2), b2)) # Calculate cross entropy for our loss function loss = -tf.reduce_sum(onehot_output * tf.log(output_layer)) # Use gradient descent optimizer at specified learning rate to minimize value given by loss tensor train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(loss)

Setelah mengatur grafik kita, saatnya untuk menyiapkan sesi dan menjalankan "train_step" (yang juga menjalankan operasi prasyarat apa pun). Beberapa dari operasi ini menggunakan placeholder, jadi nilai untuk itu perlu diberikan. Langkah pelatihan ini mewakili satu epoch dalam algoritme pembelajaran kami dan, dengan demikian, diulangi di atas jumlah epoch yang ingin kami jalankan. Kita dapat menjalankan bagian lain dari grafik, seperti tensor "kerugian" untuk tujuan informasi.

 EPOCH_COUNT = 1000 sess = tf.Session() tf.global_variables_initializer().run() for i in range(EPOCH_COUNT): if i%100 == 0: print('Loss after %d runs: %f' % (i, sess.run(loss, feed_dict={X: random_spots, Y: is_inside_circle}))) sess.run(train_step, feed_dict={X: random_spots, Y: is_inside_circle}) print('Final loss after %d runs: %f' % (i, sess.run(loss, feed_dict={X: random_spots, Y: is_inside_circle})))

Setelah kami melatih algoritme, kami dapat memasukkan satu titik dan mendapatkan output dari jaringan saraf seperti:

 sess.run(output_layer, feed_dict={X: [[1, 1]]}) # Hopefully something close to [1, 0] sess.run(output_layer, feed_dict={X: [[0, 0]]}) # Hopefully something close to [0, 1]

Kita dapat mengklasifikasikan titik sebagai keluar dari lingkaran jika anggota pertama dari vektor keluaran lebih besar dari 0,5, di dalam sebaliknya.

Dengan menjalankan tensor output_layer untuk banyak titik, kita dapat memperoleh gambaran tentang bagaimana pelajar membayangkan wilayah yang berisi titik-titik yang diklasifikasikan secara positif. Ada baiknya bermain-main dengan ukuran set pelatihan, tingkat pembelajaran, dan parameter lain untuk melihat seberapa dekat kita bisa sampai ke lingkaran yang kita inginkan.

Hampir segitiga
Set pelatihan: 100 poin
Tingkat pembelajaran: 0,01
Zaman: 1000

segitiga kecil
Set pelatihan: 1000 poin
Tingkat pembelajaran: 0,01
Zaman: 1000

segitiga besar
Set pelatihan: 1000 poin
Tingkat pembelajaran: 0,01
Zaman: 10000

Hampir lingkaran
Set pelatihan: 1000 poin
Tingkat pembelajaran: 0,001
Zaman: 10000

Bungkus

Ini adalah pelajaran yang baik bahwa peningkatan set pelatihan atau jumlah epoch tidak menjamin pembelajar yang baik—tingkat pembelajaran harus disesuaikan dengan tepat.

Semoga demonstrasi ini memberi Anda pemahaman yang baik tentang prinsip-prinsip inti TensorFlow, dan memberikan dasar yang kuat untuk menerapkan teknik yang lebih kompleks.

Kami belum membahas konsep seperti Tensorboard atau melatih model kami di seluruh GPU, tetapi ini tercakup dengan baik dalam dokumentasi TensorFlow. Sejumlah resep dapat ditemukan dalam dokumentasi yang dapat membantu Anda mempercepat dalam menangani tugas-tugas pembelajaran mendalam yang menarik menggunakan kerangka kerja yang kuat ini!

Terkait: Banyaknya Aplikasi Gradient Descent di TensorFlow