JavaRush /Blog Java /Random-MS /Pembelajaran Mesin untuk Pembangun Java, Bahagian 2

Pembelajaran Mesin untuk Pembangun Java, Bahagian 2

Diterbitkan dalam kumpulan
Pembelajaran Mesin untuk Pembangun Java, Bahagian 1
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 1

Anggaran Fungsi Objektif

Mari kita ingat bahawa fungsi sasaran , juga dikenali sebagai fungsi ramalan, adalah hasil daripada proses penyediaan atau latihan. Secara matematik, cabarannya adalah untuk mencari fungsi yang mengambil pembolehubah sebagai input хdan mengembalikan nilai yang diramalkan у.
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 2
Dalam pembelajaran mesin, fungsi kos (J(θ))digunakan untuk mengira nilai ralat atau "kos" bagi fungsi objektif tertentu.
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 3
Fungsi kos menunjukkan sejauh mana model sesuai dengan data latihan. Untuk menentukan kos fungsi objektif yang ditunjukkan di atas, adalah perlu untuk mengira ralat kuasa dua bagi setiap rumah contoh (i). Ralat ialah jarak antara nilai yang dikira уdan nilai sebenar yrumah daripada contoh i.
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 4
Sebagai contoh, harga sebenar rumah dengan keluasan 1330 = 6,500,000 € . Dan perbezaan antara harga rumah yang diramalkan oleh fungsi objektif terlatih ialah €7,032,478 : perbezaan (atau ralat) ialah €532,478 . Anda juga boleh melihat perbezaan ini dalam graf di atas. Perbezaan (atau ralat) ditunjukkan sebagai garis merah putus-putus menegak untuk setiap pasangan latihan kawasan harga. Setelah mengira kos fungsi objektif terlatih, anda perlu menjumlahkan ralat kuasa dua untuk setiap rumah dalam contoh dan mengira nilai utama. Lebih kecil nilai harga (J(θ)), lebih tepat ramalan fungsi objektif kami. Penyenaraian 3 menunjukkan pelaksanaan Java mudah bagi fungsi kos yang mengambil sebagai input fungsi objektif, senarai data latihan dan label yang dikaitkan dengannya. Nilai ramalan akan dikira dalam gelung dan ralat akan dikira dengan menolak nilai harga sebenar (diambil daripada label). Kemudian, kuasa dua ralat akan dijumlahkan dan nilai ralat akan dikira. Kos akan dikembalikan sebagai nilai jenis double:

Penyenaraian-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;
}
Berminat membaca tentang Java? Sertai kumpulan Pembangun Java !

Mempelajari fungsi sasaran

Walaupun fungsi kos membantu menilai kualiti fungsi objektif dan parameter theta, anda masih perlu mencari parameter theta yang paling sesuai. Anda boleh menggunakan algoritma penurunan kecerunan untuk ini.

Keturunan Kecerunan

Penurunan kecerunan meminimumkan fungsi kos. Ini bermakna ia digunakan untuk mencari parameter theta yang mempunyai kos minimum (J(θ))berdasarkan data latihan. Berikut ialah algoritma yang dipermudahkan untuk mengira nilai theta baharu yang lebih sesuai:
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 5
Jadi, parameter vektor theta akan bertambah baik dengan setiap lelaran algoritma. Pekali pembelajaran α menentukan bilangan pengiraan pada setiap lelaran. Pengiraan ini boleh dijalankan sehingga nilai theta "baik" ditemui. Sebagai contoh, fungsi regresi linear di bawah mempunyai tiga parameter theta:
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 6
Pada setiap lelaran, nilai baharu akan dikira untuk setiap parameter theta: , , dan . Selepas setiap lelaran, pelaksanaan baharu yang lebih sesuai boleh dibuat menggunakan vektor theta baharu 0 , θ 1 , θ 2 } . Penyenaraian -4 menunjukkan kod Java untuk algoritma pereputan kecerunan. Theta untuk fungsi regresi akan dilatih menggunakan data latihan, data penanda, kadar pembelajaran . Hasilnya akan menjadi fungsi objektif yang lebih baik menggunakan parameter theta. Kaedah ini akan dipanggil berulang kali, melepasi fungsi objektif baharu dan parameter theta baharu daripada pengiraan sebelumnya. Dan panggilan ini akan diulang sehingga fungsi objektif yang dikonfigurasikan mencapai dataran minimum: θ0θ1θ2LinearRegressionFunction(α)train()

Penyenaraian-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 kos terus berkurangan, anda boleh menjalankan fungsi kos J(θ)selepas setiap langkah latihan. Selepas setiap lelaran, kos harus berkurangan. Jika ini tidak berlaku, ini bermakna nilai pekali pembelajaran adalah terlalu besar dan algoritma telah terlepas nilai minimum. Dalam kes sedemikian, algoritma pereputan kecerunan gagal. Plot di bawah menunjukkan fungsi objektif menggunakan parameter theta baharu yang dikira, bermula dengan vektor theta permulaan {1.0, 1.0}. Lajur kiri menunjukkan plot fungsi ramalan selepas 50 lelaran; lajur tengah selepas 200 ulangan; dan lajur kanan selepas 1000 ulangan. Daripada ini, kita dapat melihat bahawa harga menurun selepas setiap lelaran, dan fungsi objektif baharu lebih sesuai dan lebih baik. Selepas 500-600 ulangan, parameter theta tidak lagi berubah dengan ketara, dan harga mencapai dataran tinggi yang stabil. Selepas ini, ketepatan fungsi sasaran tidak boleh dipertingkatkan dengan cara ini.
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 7
Dalam kes ini, walaupun kos tidak lagi berkurangan dengan ketara selepas 500-600 lelaran, fungsi objektif masih tidak optimum. Ini menunjukkan percanggahan . Dalam pembelajaran mesin, istilah "ketidakkonsistenan" digunakan untuk menunjukkan bahawa algoritma pembelajaran tidak menemui aliran asas dalam data. Berdasarkan pengalaman sebenar, ia berkemungkinan menjangkakan pengurangan harga bagi setiap meter persegi untuk hartanah yang lebih besar. Daripada ini dapat kita simpulkan bahawa model yang digunakan untuk proses pembelajaran fungsi sasaran tidak cukup sesuai dengan data. Percanggahan selalunya disebabkan oleh terlalu memudahkan model. Ini berlaku dalam kes kami, fungsi objektif terlalu mudah, dan untuk analisis ia menggunakan satu parameter - kawasan rumah. Tetapi maklumat ini tidak mencukupi untuk meramalkan harga rumah dengan tepat.

Menambah ciri dan menskalakannya

Jika anda mendapati bahawa fungsi objektif anda tidak sepadan dengan masalah yang anda cuba selesaikan, ia perlu diselaraskan. Cara biasa untuk membetulkan ketidakkonsistenan adalah dengan menambahkan ciri tambahan pada vektor ciri. Dalam contoh harga rumah, anda boleh menambah ciri-ciri seperti bilangan bilik atau umur rumah. Iaitu, daripada menggunakan vektor dengan satu nilai ciri {size}untuk menggambarkan rumah, anda boleh menggunakan vektor dengan beberapa nilai, sebagai contoh, {size, number-of-rooms, age}. Dalam beberapa kes, bilangan ciri dalam data latihan yang tersedia tidak mencukupi. Maka patut dicuba menggunakan ciri polinomial yang dikira menggunakan ciri sedia ada. Sebagai contoh, anda mempunyai peluang untuk melanjutkan fungsi objektif untuk menentukan harga rumah supaya ia termasuk ciri pengiraan meter persegi (x2):
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 8
Menggunakan berbilang ciri memerlukan penskalaan ciri , yang digunakan untuk menyeragamkan julat merentas ciri yang berbeza. Oleh itu, julat nilai untuk atribut saiz 2 adalah jauh lebih besar daripada julat nilai untuk atribut saiz. Tanpa penskalaan ciri, saiz 2 akan mempengaruhi fungsi kos. Ralat yang diperkenalkan oleh atribut saiz 2 akan jauh lebih besar daripada ralat yang diperkenalkan oleh atribut saiz. Algoritma penskalaan ciri mudah diberikan di bawah:
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 9
Algoritma ini dilaksanakan dalam kelas FeaturesScalingdalam contoh kod di bawah. Kelas FeaturesScalingmembentangkan kaedah komersil untuk mencipta fungsi penskalaan yang ditala kepada data latihan. Secara dalaman, contoh data latihan digunakan untuk mengira nilai purata, minimum dan maksimum. Fungsi yang terhasil mengambil vektor ciri dan menghasilkan yang baharu dengan ciri berskala. Penskalaan ciri diperlukan untuk kedua-dua proses pembelajaran dan proses ramalan, seperti ditunjukkan di bawah:
// создание массива данных
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);
Apabila semakin banyak ciri ditambah, kesesuaian dengan fungsi objektif meningkat, tetapi berhati-hati. Jika anda pergi terlalu jauh dan menambah terlalu banyak ciri, anda mungkin akhirnya mempelajari fungsi objektif yang terlalu sesuai.

Terlalu padanan dan pengesahan silang

Pemasangan lampau berlaku apabila fungsi atau model objektif sesuai dengan data latihan terlalu baik, sehingga ia menangkap bunyi atau variasi rawak dalam data latihan. Contoh overfitting ditunjukkan dalam graf paling kanan di bawah:
Pembelajaran Mesin untuk Pembangun Java, Bahagian 2 - 10
Walau bagaimanapun, model overfitting berprestasi sangat baik pada data latihan, tetapi akan berprestasi buruk pada data sebenar yang tidak diketahui. Terdapat beberapa cara untuk mengelakkan overfitting.
  • Gunakan set data yang lebih besar untuk latihan.
  • Gunakan lebih sedikit ciri seperti yang ditunjukkan dalam graf di atas.
  • Gunakan algoritma pembelajaran mesin yang dipertingkatkan yang mengambil kira penyelarasan.
Jika algoritma ramalan mengatasi data latihan, adalah perlu untuk menghapuskan ciri yang tidak memberi manfaat kepada ketepatannya. Kesukarannya adalah untuk mencari ciri yang mempunyai kesan yang lebih ketara terhadap ketepatan ramalan berbanding yang lain. Seperti yang ditunjukkan dalam graf, overfit boleh ditentukan secara visual menggunakan graf. Ini berfungsi dengan baik untuk graf dengan 2 atau 3 koordinat, menjadi sukar untuk memplot dan menilai graf jika anda menggunakan lebih daripada 2 ciri. Dalam pengesahan silang, anda menguji semula model selepas latihan menggunakan data yang tidak diketahui oleh algoritma selepas proses latihan selesai. Data berlabel yang tersedia hendaklah dibahagikan kepada 3 set:
  • data latihan;
  • data pengesahan;
  • data ujian.
Dalam kes ini, 60 peratus daripada rekod berlabel yang mencirikan rumah harus digunakan dalam proses variasi latihan algoritma sasaran. Selepas proses latihan, separuh daripada baki data (tidak digunakan sebelum ini) harus digunakan untuk mengesahkan bahawa algoritma sasaran terlatih berprestasi baik pada data yang tidak diketahui. Biasanya, algoritma yang berprestasi lebih baik daripada yang lain dipilih untuk digunakan. Data selebihnya digunakan untuk mengira nilai ralat untuk model yang dipilih akhir. Terdapat teknik pengesahan silang lain, seperti lipatan k . Walau bagaimanapun, saya tidak akan menerangkannya dalam artikel ini.

Alat pembelajaran mesin dan rangka kerja Weka

Kebanyakan rangka kerja dan perpustakaan menyediakan koleksi algoritma pembelajaran mesin yang banyak. Di samping itu, mereka menyediakan antara muka peringkat tinggi yang mudah untuk melatih, menguji dan memproses model data. Weka ialah salah satu rangka kerja yang paling popular untuk JVM. Weka ialah perpustakaan Java praktikal yang mengandungi ujian grafik untuk mengesahkan model. Contoh di bawah menggunakan pustaka Weka untuk membuat set data latihan yang mengandungi ciri dan label. Kaedah setClassIndex()- untuk menandakan. Dalam Weka, label ditakrifkan 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);
...
Set Data dan Objek Sampel boleh disimpan dan dimuatkan daripada fail. Weka menggunakan ARFF (Attribute Relation File Format) yang disokong oleh penanda aras grafik Weka. Set data ini digunakan untuk melatih fungsi objektif yang dikenali sebagai pengelas dalam Weka. Pertama sekali, anda mesti menentukan fungsi objektif. Kod di bawah LinearRegressionakan mencipta contoh pengelas. Pengelas ini akan dilatih menggunakan buildClassifier(). Kaedah buildClassifier()memilih parameter theta berdasarkan data latihan untuk mencari model sasaran terbaik. Dengan Weka, anda tidak perlu risau tentang menetapkan kadar pembelajaran atau bilangan lelaran. Weka juga melakukan penskalaan ciri secara bebas.
Classifier targetFunction = new LinearRegression();
targetFunction.buildClassifier(trainingDataset);
Setelah tetapan ini dibuat, fungsi objektif boleh digunakan untuk meramalkan harga rumah, seperti yang ditunjukkan di bawah:
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 pengelas atau model terlatih. Dalam kod di bawah, tatasusunan data pengesahan yang dipilih digunakan untuk mengelakkan keputusan palsu. Hasil pengukuran (kos ralat) akan dipaparkan pada konsol. Biasanya, hasil penilaian digunakan untuk membandingkan model yang dilatih menggunakan algoritma pembelajaran mesin yang berbeza, atau variasi ini:
Evaluation evaluation = new Evaluation(trainingDataset);
evaluation.evaluateModel(targetFunction, validationDataset);
System.out.println(evaluation.toSummaryString("Results", false));
Contoh di atas menggunakan regresi linear, yang meramalkan nilai berangka, seperti harga rumah, berdasarkan nilai input. Regresi linear menyokong ramalan nilai berangka berterusan. Untuk meramalkan nilai binari ("Ya" dan "Tidak"), anda perlu menggunakan algoritma pembelajaran mesin yang lain. Contohnya, pepohon keputusan, rangkaian saraf atau regresi logistik.
// использование логистической регрессии
Classifier targetFunction = new Logistic();
targetFunction.buildClassifier(trainingSet);
Anda boleh menggunakan salah satu daripada algoritma ini, sebagai contoh, untuk meramalkan sama ada mesej e-mel adalah spam, atau meramalkan cuaca, atau meramalkan sama ada rumah akan terjual dengan baik. Jika anda ingin mengajar algoritma anda untuk meramalkan cuaca atau berapa cepat rumah akan dijual, anda memerlukan set data yang berbeza, mis.topseller:
// использование атрибута маркера topseller instead of атрибута маркера цена
ArrayList<string> classVal = new ArrayList<>();
classVal.add("true");
classVal.add("false");

Attribute topsellerAttribute = new Attribute("topsellerLabel", classVal);
attributes.add(topsellerAttribute);
Set data ini akan digunakan untuk melatih pengelas baharu topseller. Sebaik sahaja ia telah dilatih, panggilan ramalan harus mengembalikan indeks kelas token yang boleh digunakan untuk mendapatkan nilai ramalan.
int idx = (int) targetFunction.classifyInstance(unlabeledInstances.get(0));
String prediction = classVal.get(idx);

Kesimpulan

Walaupun pembelajaran mesin berkait rapat dengan statistik dan menggunakan banyak konsep matematik, kit alat pembelajaran mesin membolehkan anda mula menyepadukan pembelajaran mesin ke dalam program anda tanpa pengetahuan mendalam tentang matematik. Walau bagaimanapun, lebih baik anda memahami algoritma pembelajaran mesin yang mendasari, seperti algoritma regresi linear yang kami terokai dalam artikel ini, lebih banyak anda akan dapat memilih algoritma yang betul dan menalanya untuk prestasi optimum. Terjemahan daripada bahasa Inggeris. Pengarang: Gregor Roth, Arkitek Perisian, JavaWorld.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION