JavaRush /Java Blog /Random-ID /Pembelajaran Mesin untuk Pengembang Java, Bagian 2

Pembelajaran Mesin untuk Pengembang Java, Bagian 2

Dipublikasikan di grup Random-ID
Pembelajaran Mesin untuk Pengembang Java, Bagian 1
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 1

Estimasi Fungsi Tujuan

Ingatlah bahwa fungsi target , disebut juga fungsi prediksi, adalah hasil dari proses persiapan atau pelatihan. Secara matematis, tantangannya adalah menemukan fungsi yang mengambil variabel sebagai masukan хdan mengembalikan nilai prediksi у.
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 2
Dalam pembelajaran mesin, fungsi biaya (J(θ))digunakan untuk menghitung nilai kesalahan atau "biaya" dari fungsi tujuan tertentu.
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 3
Fungsi biaya menunjukkan seberapa cocok model dengan data pelatihan. Untuk menentukan biaya fungsi tujuan di atas, perlu dihitung kesalahan kuadrat setiap contoh rumah (i). Error adalah jarak antara nilai yang dihitung уdan nilai sebenarnya yrumah dari contoh i.
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 4
Misalnya harga riil rumah dengan luas 1.330 = 6.500.000 € . Dan selisih antara prediksi harga rumah dengan fungsi tujuan yang dilatih adalah €7,032,478 : selisih (atau kesalahan) adalah €532,478 . Anda juga dapat melihat perbedaannya pada grafik di atas. Perbedaan (atau kesalahan) ditampilkan sebagai garis merah putus-putus vertikal untuk setiap pasangan pelatihan area harga. Setelah menghitung biaya fungsi tujuan yang dilatih, Anda perlu menjumlahkan kesalahan kuadrat untuk setiap rumah dalam contoh dan menghitung nilai utamanya. Semakin kecil nilai harga (J(θ)), semakin akurat prediksi fungsi tujuan kita. Listing 3 menunjukkan implementasi Java sederhana dari fungsi biaya yang mengambil input fungsi tujuan, daftar data pelatihan, dan label yang terkait dengannya. Nilai prediksi akan dihitung secara loop dan error akan dihitung dengan mengurangkan nilai harga sebenarnya (diambil dari label). Nantinya, kuadrat kesalahannya akan dijumlahkan dan dihitung nilai kesalahannya. Biaya akan dikembalikan sebagai nilai tipe double:

Daftar-3

public static double cost(Function<ltDouble[], Double> targetFunction,
 List<ltDouble[]> dataset,
 List<ltDouble> labels) {
 int m = dataset.size();
 double sumSquaredErrors = 0;

 // рассчет квадрата ошибки («разницы») для каждого тренировочного примера и //добавление его к сумме
 for (int i = 0; i < m; i++) {
 // получаем вектор признаков из текущего примера
 Double[] featureVector = dataset.get(i);
 // предсказываем meaning и вычисляем ошибку базируясь на реальном
 //значении (метка)
 double predicted = targetFunction.apply(featureVector);
 double label = labels.get(i);
 double gap = predicted - label;
 sumSquaredErrors += Math.pow(gap, 2);
 }

 // Вычисляем и возращаем meaning ошибки (чем меньше тем лучше)
 return (1.0 / (2 * m)) * sumSquaredErrors;
}
Tertarik membaca tentang Java? Bergabunglah dengan grup Pengembang Java !

Mempelajari fungsi target

Meskipun fungsi biaya membantu mengevaluasi kualitas fungsi tujuan dan parameter theta, Anda tetap perlu menemukan parameter theta yang paling sesuai. Anda dapat menggunakan algoritma penurunan gradien untuk ini.

Penurunan Gradien

Penurunan gradien meminimalkan fungsi biaya. Artinya digunakan untuk mencari parameter theta yang memiliki biaya minimum (J(θ))berdasarkan data pelatihan. Berikut algoritma yang disederhanakan untuk menghitung nilai theta baru yang lebih sesuai:
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 5
Jadi, parameter vektor theta akan meningkat dengan setiap iterasi algoritma. Koefisien pembelajaran α menentukan jumlah perhitungan pada setiap iterasi. Perhitungan ini dapat dilakukan sampai ditemukan nilai theta yang “baik”. Misalnya, fungsi regresi linier di bawah ini memiliki tiga parameter theta:
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 6
Pada setiap iterasi, nilai baru akan dihitung untuk setiap parameter theta: , , dan . Setelah setiap iterasi, implementasi baru yang lebih tepat dapat dibuat menggunakan vektor theta baru 0 , θ 1 , θ 2 } . Listing -4 menunjukkan kode Java untuk algoritma peluruhan gradien. Theta untuk fungsi regresi akan dilatih menggunakan data pelatihan, data penanda, kecepatan pembelajaran . Hasilnya adalah fungsi tujuan yang ditingkatkan menggunakan parameter theta. Metode ini akan dipanggil berulang kali, meneruskan fungsi tujuan baru dan parameter theta baru dari perhitungan sebelumnya. Dan panggilan ini akan diulang hingga fungsi tujuan yang dikonfigurasi mencapai titik minimum: θ0θ1θ2LinearRegressionFunction(α)train()

Daftar-4

public static LinearRegressionFunction train(LinearRegressionFunction targetFunction,
 List<ltDouble[]> dataset,
 List<ltDouble> labels,
 double alpha) {
 int m = dataset.size();
 double[] thetaVector = targetFunction.getThetas();
 double[] newThetaVector = new double[thetaVector.length];

 // вычисление нового значения тета для каждого element тета массива
 for (int j = 0; j < thetaVector.length; j++) {
 // сумируем разницу ошибки * признак
 double sumErrors = 0;
 for (int i = 0; i < m; i++) {
 Double[] featureVector = dataset.get(i);
 double error = targetFunction.apply(featureVector) - labels.get(i);
 sumErrors += error * featureVector[j];
 }

 //вычисляем новые значения тета
 double gradient = (1.0 / m) * sumErrors;
 newThetaVector[j] = thetaVector[j] - alpha * gradient;
 }

 return new LinearRegressionFunction(newThetaVector);
}
Untuk memastikan bahwa biaya terus menurun, Anda dapat menjalankan fungsi biaya J(θ)setelah setiap langkah pelatihan. Setelah setiap iterasi, biayanya akan berkurang. Jika hal ini tidak terjadi, berarti nilai koefisien pembelajaran terlalu besar dan algoritma melewatkan nilai minimum. Dalam kasus seperti itu, algoritma peluruhan gradien gagal. Plot di bawah ini menunjukkan fungsi tujuan menggunakan parameter theta baru yang dihitung, dimulai dengan vektor theta awal {1.0, 1.0}. Kolom kiri menunjukkan plot fungsi prediksi setelah 50 iterasi; kolom tengah setelah 200 repetisi; dan kolom kanan setelah 1000 pengulangan. Dari sini kita dapat melihat bahwa harga menurun setelah setiap iterasi, dan fungsi tujuan yang baru semakin cocok. Setelah 500-600 pengulangan, parameter theta tidak lagi berubah secara signifikan, dan harga mencapai titik stabil. Setelah ini, keakuratan fungsi target tidak dapat ditingkatkan dengan cara ini.
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 7
Dalam hal ini, meskipun biaya tidak lagi berkurang secara signifikan setelah 500-600 iterasi, namun fungsi tujuan masih belum optimal. Hal ini menunjukkan adanya kesenjangan . Dalam pembelajaran mesin, istilah "inkonsistensi" digunakan untuk menunjukkan bahwa algoritme pembelajaran tidak menemukan tren mendasar dalam data. Berdasarkan pengalaman nyata, kemungkinan besar terdapat penurunan harga per meter persegi untuk properti yang lebih besar. Dari sini kita dapat menyimpulkan bahwa model yang digunakan untuk proses pembelajaran fungsi target kurang sesuai dengan data. Perbedaan ini sering kali disebabkan oleh penyederhanaan model yang berlebihan. Ini terjadi dalam kasus kami, fungsi tujuan terlalu sederhana, dan untuk analisisnya menggunakan satu parameter - luas rumah. Namun informasi ini tidak cukup untuk memprediksi harga sebuah rumah secara akurat.

Menambahkan fitur dan menskalakannya

Jika ternyata fungsi tujuan Anda tidak sesuai dengan masalah yang ingin Anda selesaikan, maka perlu disesuaikan. Cara umum untuk memperbaiki ketidakkonsistenan adalah dengan menambahkan fitur tambahan ke vektor fitur. Pada contoh harga rumah, Anda dapat menambahkan ciri-ciri seperti jumlah kamar atau umur rumah. Artinya, daripada menggunakan vektor dengan satu nilai fitur {size}untuk mendeskripsikan sebuah rumah, Anda dapat menggunakan vektor dengan beberapa nilai, misalnya, {size, number-of-rooms, age}. Dalam beberapa kasus, jumlah fitur dalam data pelatihan yang tersedia tidak mencukupi. Maka ada baiknya mencoba menggunakan fitur polinomial yang dihitung menggunakan fitur yang sudah ada. Misalnya, Anda mempunyai kesempatan untuk memperluas fungsi tujuan penentuan harga rumah sehingga mencakup fitur penghitungan meter persegi (x2):
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 8
Penggunaan beberapa fitur memerlukan penskalaan fitur , yang digunakan untuk menstandardisasi rentang fitur yang berbeda. Dengan demikian, rentang nilai untuk atribut size 2 secara signifikan lebih besar daripada rentang nilai untuk atribut size. Tanpa penskalaan fitur, ukuran 2 akan terlalu mempengaruhi fungsi biaya. Kesalahan yang disebabkan oleh atribut ukuran 2 akan jauh lebih besar daripada kesalahan yang disebabkan oleh atribut ukuran. Algoritme penskalaan fitur sederhana diberikan di bawah ini:
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 9
Algoritma ini diimplementasikan di kelas FeaturesScalingpada contoh kode di bawah ini. Kelas ini FeaturesScalingmenyajikan metode komersial untuk membuat fungsi penskalaan yang disesuaikan dengan data pelatihan. Secara internal, contoh data pelatihan digunakan untuk menghitung nilai rata-rata, minimum dan maksimum. Fungsi yang dihasilkan mengambil vektor fitur dan menghasilkan yang baru dengan fitur berskala. Penskalaan fitur diperlukan untuk proses pembelajaran dan proses prediksi, seperti yang ditunjukkan di bawah ini:
// создание массива данных
List<ltDouble[]> dataset = new ArrayList<>();
dataset.add(new Double[] { 1.0, 90.0, 8100.0 }); // feature vector of house#1
dataset.add(new Double[] { 1.0, 101.0, 10201.0 }); // feature vector of house#2
dataset.add(new Double[] { 1.0, 103.0, 10609.0 }); // ...
//...

// создание меток
List<ltDouble> labels = new ArrayList<>();
labels.add(249.0); // price label of house#1
labels.add(338.0); // price label of house#2
labels.add(304.0); // ...
//...

// создание расширенного списка признаков
Function<ltDouble[], Double[]> scalingFunc = FeaturesScaling.createFunction(dataset);
List<ltDouble[]> scaledDataset = dataset.stream().map(scalingFunc).collect(Collectors.toList());

// создаем функцию которая инициализирует теты и осуществляет обучение //используя коэффициент обучения 0.1

LinearRegressionFunction targetFunction = new LinearRegressionFunction(new double[] { 1.0, 1.0, 1.0 });
for (int i = 0; i < 10000; i++) {
 targetFunction = Learner.train(targetFunction, scaledDataset, labels, 0.1);
}

// делаем предсказание стоимости дома с площадью 600 m2
Double[] scaledFeatureVector = scalingFunc.apply(new Double[] { 1.0, 600.0, 360000.0 });
double predictedPrice = targetFunction.apply(scaledFeatureVector);
Semakin banyak fitur yang ditambahkan, kesesuaian dengan fungsi tujuan meningkat, namun hati-hati. Jika Anda melangkah terlalu jauh dan menambahkan terlalu banyak fitur, Anda mungkin akan mempelajari fungsi tujuan yang berlebihan.

Pencocokan berlebihan dan validasi silang

Overfitting terjadi ketika fungsi tujuan atau model terlalu cocok dengan data pelatihan, sehingga menangkap noise atau variasi acak dalam data pelatihan. Contoh overfitting ditunjukkan pada grafik paling kanan di bawah ini:
Pembelajaran Mesin untuk Pengembang Java, Bagian 2 - 10
Namun, model overfitting berperforma sangat baik pada data pelatihan, namun akan berperforma buruk pada data nyata yang tidak diketahui. Ada beberapa cara untuk menghindari overfitting.
  • Gunakan kumpulan data yang lebih besar untuk pelatihan.
  • Gunakan lebih sedikit fitur seperti yang ditunjukkan pada grafik di atas.
  • Gunakan algoritme pembelajaran mesin yang ditingkatkan yang mempertimbangkan regularisasi.
Jika algoritme prediksi melebihi data pelatihan, fitur-fitur yang tidak menguntungkan keakuratannya perlu dihilangkan. Kesulitannya adalah menemukan fitur yang memiliki pengaruh lebih signifikan terhadap keakuratan prediksi dibandingkan fitur lainnya. Seperti yang ditunjukkan pada grafik, overfit dapat ditentukan secara visual menggunakan grafik. Ini berfungsi baik untuk grafik dengan 2 atau 3 koordinat, akan sulit untuk memplot dan mengevaluasi grafik jika Anda menggunakan lebih dari 2 fitur. Dalam validasi silang, Anda menguji ulang model setelah pelatihan menggunakan data yang tidak diketahui algoritme setelah proses pelatihan selesai. Data berlabel yang tersedia harus dibagi menjadi 3 set:
  • data pelatihan;
  • data verifikasi;
  • data uji.
Dalam hal ini, 60 persen dari catatan berlabel yang mengkarakterisasi rumah harus digunakan dalam proses pelatihan varian algoritma target. Setelah proses pelatihan, setengah dari data yang tersisa (yang sebelumnya tidak digunakan) harus digunakan untuk memverifikasi bahwa algoritma target yang dilatih bekerja dengan baik pada data yang tidak diketahui. Biasanya, algoritma yang berkinerja lebih baik daripada yang lain dipilih untuk digunakan. Data yang tersisa digunakan untuk menghitung nilai kesalahan untuk model akhir yang dipilih. Ada teknik validasi silang lainnya, seperti k-fold . Namun, saya tidak akan menjelaskannya di artikel ini.

Alat pembelajaran mesin dan kerangka kerja Weka

Sebagian besar kerangka kerja dan perpustakaan menyediakan banyak koleksi algoritma pembelajaran mesin. Selain itu, mereka menyediakan antarmuka tingkat tinggi yang nyaman untuk melatih, menguji, dan memproses model data. Weka adalah salah satu framework paling populer untuk JVM. Weka adalah perpustakaan Java praktis yang berisi tes grafis untuk memvalidasi model. Contoh di bawah ini menggunakan perpustakaan Weka untuk membuat dataset pelatihan yang berisi fitur dan label. Metode setClassIndex()- untuk menandai. Di Weka, label didefinisikan sebagai kelas:
// определяем атрибуты для признаков и меток
ArrayList<ltAttribute> attributes = new ArrayList<>();
Attribute sizeAttribute = new Attribute("sizeFeature");
attributes.add(sizeAttribute);
Attribute squaredSizeAttribute = new Attribute("squaredSizeFeature");
attributes.add(squaredSizeAttribute);
Attribute priceAttribute = new Attribute("priceLabel");
attributes.add(priceAttribute);


// создаем и заполняем список признаков 5000 примеров
Instances trainingDataset = new Instances("trainData", attributes, 5000);
trainingDataset.setClassIndex(trainingSet.numAttributes() - 1);
Instance instance = new DenseInstance(3);

instance.setValue(sizeAttribute, 90.0);
instance.setValue(squaredSizeAttribute, Math.pow(90.0, 2));
instance.setValue(priceAttribute, 249.0);
trainingDataset.add(instance);
Instance instance = new DenseInstance(3);
instance.setValue(sizeAttribute, 101.0);
...
Kumpulan Data dan Objek Sampel dapat disimpan dan dimuat dari file. Weka menggunakan ARFF (Attribute Relation File Format) yang didukung oleh benchmark grafis Weka. Kumpulan data ini digunakan untuk melatih fungsi tujuan yang dikenal sebagai pengklasifikasi di Weka. Pertama-tama, Anda harus mendefinisikan fungsi tujuan. Kode di bawah ini LinearRegressionakan membuat sebuah instance dari classifier. Pengklasifikasi ini akan dilatih menggunakan buildClassifier(). Metode ini buildClassifier()memilih parameter theta berdasarkan data pelatihan untuk mencari model target terbaik. Dengan Weka, Anda tidak perlu khawatir tentang pengaturan kecepatan pembelajaran atau jumlah iterasi. Weka juga melakukan penskalaan fitur secara mandiri.
Classifier targetFunction = new LinearRegression();
targetFunction.buildClassifier(trainingDataset);
Setelah pengaturan ini dibuat, fungsi tujuan dapat digunakan untuk memprediksi harga rumah, seperti yang ditunjukkan di bawah ini:
Instances unlabeledInstances = new Instances("predictionset", attributes, 1);
unlabeledInstances.setClassIndex(trainingSet.numAttributes() - 1);
Instance unlabeled = new DenseInstance(3);
unlabeled.setValue(sizeAttribute, 1330.0);
unlabeled.setValue(squaredSizeAttribute, Math.pow(1330.0, 2));
unlabeledInstances.add(unlabeled);

double prediction = targetFunction.classifyInstance(unlabeledInstances.get(0));
Weka menyediakan kelas Evaluationuntuk menguji pengklasifikasi atau model terlatih. Dalam kode di bawah ini, serangkaian data validasi yang dipilih digunakan untuk menghindari hasil yang salah. Hasil pengukuran (biaya kesalahan) akan ditampilkan di konsol. Biasanya, hasil evaluasi digunakan untuk membandingkan model yang dilatih menggunakan algoritme pembelajaran mesin yang berbeda, atau variasinya:
Evaluation evaluation = new Evaluation(trainingDataset);
evaluation.evaluateModel(targetFunction, validationDataset);
System.out.println(evaluation.toSummaryString("Results", false));
Contoh di atas menggunakan regresi linier, yang memprediksi nilai numerik, seperti harga rumah, berdasarkan nilai masukan. Regresi linier mendukung prediksi nilai numerik berkelanjutan. Untuk memprediksi nilai biner (“Ya” dan “Tidak”), Anda perlu menggunakan algoritme pembelajaran mesin lainnya. Misalnya, pohon keputusan, jaringan saraf, atau regresi logistik.
// использование логистической регрессии
Classifier targetFunction = new Logistic();
targetFunction.buildClassifier(trainingSet);
Anda dapat menggunakan salah satu algoritma ini, misalnya, untuk memprediksi apakah sebuah pesan email adalah spam, atau memprediksi cuaca, atau memprediksi apakah sebuah rumah akan terjual dengan baik. Jika Anda ingin mengajarkan algoritme Anda untuk memprediksi cuaca atau seberapa cepat sebuah rumah akan terjual, Anda memerlukan kumpulan data yang berbeda, misalnya.topseller:
// использование атрибута маркера topseller instead of атрибута маркера цена
ArrayList<string> classVal = new ArrayList<>();
classVal.add("true");
classVal.add("false");

Attribute topsellerAttribute = new Attribute("topsellerLabel", classVal);
attributes.add(topsellerAttribute);
Kumpulan data ini akan digunakan untuk melatih pengklasifikasi baru topseller. Setelah dilatih, panggilan prediksi harus mengembalikan indeks kelas token yang dapat digunakan untuk mendapatkan nilai prediksi.
int idx = (int) targetFunction.classifyInstance(unlabeledInstances.get(0));
String prediction = classVal.get(idx);

Kesimpulan

Meskipun pembelajaran mesin terkait erat dengan statistik dan menggunakan banyak konsep matematika, perangkat pembelajaran mesin memungkinkan Anda untuk mulai mengintegrasikan pembelajaran mesin ke dalam program Anda tanpa pengetahuan matematika yang mendalam. Namun, semakin baik Anda memahami algoritma pembelajaran mesin yang mendasarinya, seperti algoritma regresi linier yang kita bahas dalam artikel ini, semakin Anda dapat memilih algoritma yang tepat dan menyesuaikannya untuk kinerja yang optimal. Terjemahan dari bahasa Inggris. Penulis: Gregor Roth, Arsitek Perangkat Lunak, JavaWorld.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION