JavaRush /Java Blog /Random-TL /Machine Learning para sa Java Developers, Part 2

Machine Learning para sa Java Developers, Part 2

Nai-publish sa grupo
Machine Learning para sa Mga Developer ng Java, Bahagi 1
Machine Learning para sa Java Developers, Part 2 - 1

Pagtatantya ng Layunin ng Function

Alalahanin natin na ang target na function , na kilala rin bilang prediction function, ay ang resulta ng paghahanda o proseso ng pagsasanay. Sa matematika, ang hamon ay maghanap ng function na kumukuha ng variable bilang input хat ibinabalik ang hinulaang halaga у.
Machine Learning para sa Java Developers, Part 2 - 2
Sa machine learning, ang isang cost function (J(θ))ay ginagamit upang kalkulahin ang error value o "cost" ng isang partikular na layunin function.
Machine Learning para sa Java Developers, Part 2 - 3
Ipinapakita ng function ng gastos kung gaano kahusay ang pagkakatugma ng modelo sa data ng pagsasanay. Upang matukoy ang halaga ng layunin ng function na ipinapakita sa itaas, kinakailangan upang kalkulahin ang squared error ng bawat halimbawang bahay (i). Ang error ay ang distansya sa pagitan ng kinakalkula na halaga уat ang tunay na halaga yng bahay mula sa halimbawa i.
Machine Learning para sa Java Developers, Part 2 - 4
Halimbawa, ang tunay na presyo ng isang bahay na may lawak na 1330 = 6,500,000 € . At ang pagkakaiba sa pagitan ng hinulaang presyo ng bahay sa pamamagitan ng sinanay na layunin ng function ay €7,032,478 : ang pagkakaiba (o error) ay €532,478 . Makikita mo rin ang pagkakaibang ito sa graph sa itaas. Ang pagkakaiba (o error) ay ipinapakita bilang patayong putol-putol na pulang linya para sa bawat pares ng pagsasanay sa lugar ng presyo. Ang pagkakaroon ng pagkalkula ng gastos ng sinanay na layunin ng pag-andar, kailangan mong isama ang squared error para sa bawat bahay sa halimbawa at kalkulahin ang pangunahing halaga. Kung mas maliit ang halaga ng presyo (J(θ)), magiging mas tumpak ang mga hula ng aming layunin na function. Ang listahan 3 ay nagpapakita ng isang simpleng pagpapatupad ng Java ng isang function ng gastos na kumukuha bilang input ng isang layunin na function, isang listahan ng data ng pagsasanay, at mga label na nauugnay sa kanila. Ang mga halaga ng hula ay kakalkulahin sa isang loop at ang error ay kakalkulahin sa pamamagitan ng pagbabawas ng tunay na halaga ng presyo (kinuha mula sa label). Mamaya, ang parisukat ng mga error ay susumahin at ang halaga ng error ay kakalkulahin. Ang gastos ay ibabalik bilang isang halaga ng uri double:

Listahan-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;
}
Interesado sa pagbabasa tungkol sa Java? Sumali sa Java Developer group !

Pag-aaral ng target na function

Bagama't nakakatulong ang function ng gastos na suriin ang kalidad ng layunin ng function at mga parameter ng theta, kailangan mo pa ring mahanap ang pinakaangkop na mga parameter ng theta. Maaari mong gamitin ang gradient descent algorithm para dito.

Gradient Descent

Pinaliit ng gradient descent ang function ng gastos. Nangangahulugan ito na ginagamit ito upang mahanap ang mga parameter ng theta na may pinakamababang gastos (J(θ))batay sa data ng pagsasanay. Narito ang isang pinasimpleng algorithm para sa pagkalkula ng bago, mas naaangkop na mga halaga ng theta:
Machine Learning para sa Java Developers, Part 2 - 5
Kaya, ang mga parameter ng theta vector ay mapapabuti sa bawat pag-ulit ng algorithm. Tinutukoy ng learning coefficient α ang bilang ng mga kalkulasyon sa bawat pag-ulit. Ang mga kalkulasyong ito ay maaaring isagawa hanggang sa matagpuan ang "magandang" mga halaga ng theta. Halimbawa, ang linear regression function sa ibaba ay may tatlong mga parameter ng theta:
Machine Learning para sa Java Developers, Part 2 - 6
Sa bawat pag-ulit, kakalkulahin ang isang bagong halaga para sa bawat isa sa mga parameter ng theta: , , at . Pagkatapos ng bawat pag-ulit, isang bago, mas naaangkop na pagpapatupad ay maaaring gawin gamit ang bagong theta vector 0 , θ 1 , θ 2 } . Ipinapakita ng listahan -4 ang Java code para sa gradient decay algorithm. Ang Theta para sa regression function ay sasanayin gamit ang data ng pagsasanay, data ng marker, rate ng pagkatuto . Ang resulta ay isang pinahusay na layunin ng function gamit ang mga parameter ng theta. Ang pamamaraan ay tatawagan nang paulit-ulit, na ipinapasa ang bagong layunin ng pag-andar at ang bagong mga parameter ng theta mula sa mga nakaraang kalkulasyon. At uulitin ang mga tawag na ito hanggang sa maabot ng naka-configure na layunin ang isang minimum na talampas: θ0θ1θ2LinearRegressionFunction(α)train()

Listahan-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);
}
Upang matiyak na patuloy na bumababa ang gastos, maaari mong patakbuhin ang function ng gastos J(θ)pagkatapos ng bawat hakbang sa pagsasanay. Pagkatapos ng bawat pag-ulit, ang gastos ay dapat bumaba. Kung hindi ito mangyayari, nangangahulugan ito na ang halaga ng koepisyent ng pag-aaral ay masyadong malaki at ang algorithm ay napalampas lamang ang pinakamababang halaga. Sa ganoong kaso, nabigo ang gradient decay algorithm. Ang mga plot sa ibaba ay nagpapakita ng layunin ng function gamit ang bago, kinakalkula na mga parameter ng theta, simula sa simula ng theta vector {1.0, 1.0}. Ang kaliwang column ay nagpapakita ng plot ng prediction function pagkatapos ng 50 iteration; gitnang haligi pagkatapos ng 200 na pag-uulit; at ang kanang column pagkatapos ng 1000 repetitions. Mula sa mga ito makikita natin na ang presyo ay bumababa pagkatapos ng bawat pag-ulit, at ang bagong layunin ng function ay mas mahusay at mas mahusay. Pagkatapos ng 500-600 na pag-uulit, ang mga parameter ng theta ay hindi na nagbabago nang malaki, at ang presyo ay umabot sa isang matatag na talampas. Pagkatapos nito, ang katumpakan ng target na function ay hindi maaaring mapabuti sa ganitong paraan.
Machine Learning para sa Java Developers, Part 2 - 7
Sa kasong ito, kahit na ang gastos ay hindi na bumababa nang malaki pagkatapos ng 500-600 na pag-ulit, ang layunin na pag-andar ay hindi pa rin optimal. Ito ay nagpapahiwatig ng isang pagkakaiba . Sa machine learning, ang terminong "inconsistency" ay ginagamit para isaad na ang learning algorithm ay hindi nakakahanap ng mga pinagbabatayan na trend sa data. Batay sa totoong buhay na karanasan, malamang na asahan ang pagbaba sa presyo sa bawat metro kuwadrado para sa mas malalaking property. Mula dito maaari nating tapusin na ang modelo na ginamit para sa proseso ng pag-aaral ng target na function ay hindi sapat na angkop sa data. Ang pagkakaiba ay kadalasang dahil sa sobrang pagpapasimple ng modelo. Nangyari ito sa aming kaso, ang layunin ng pag-andar ay masyadong simple, at para sa pagsusuri ay gumagamit ito ng isang solong parameter - ang lugar ng bahay. Ngunit ang impormasyong ito ay hindi sapat upang tumpak na mahulaan ang presyo ng isang bahay.

Pagdaragdag ng mga feature at pag-scale sa mga ito

Kung nakita mo na ang iyong layunin na pag-andar ay hindi tumutugma sa problemang sinusubukan mong lutasin, kailangan itong ayusin. Ang isang karaniwang paraan upang itama ang hindi pagkakapare-pareho ay ang pagdaragdag ng mga karagdagang feature sa feature vector. Sa halimbawa ng presyo ng isang bahay, maaari kang magdagdag ng mga katangian tulad ng bilang ng mga silid o edad ng bahay. Ibig sabihin, sa halip na gumamit ng vector na may isang feature value {size}para ilarawan ang isang bahay, maaari kang gumamit ng vector na may ilang value, halimbawa, {size, number-of-rooms, age}. Sa ilang mga kaso, hindi sapat ang bilang ng mga feature sa available na data ng pagsasanay. Pagkatapos ay sulit na subukang gumamit ng mga polynomial na tampok na kinakalkula gamit ang mga umiiral na. Halimbawa, mayroon kang pagkakataon na palawigin ang layunin ng pag-andar para sa pagtukoy ng presyo ng isang bahay upang kasama nito ang isang kinakalkula na tampok ng square meters (x2):
Machine Learning para sa Java Developers, Part 2 - 8
Ang paggamit ng maraming feature ay nangangailangan ng feature scaling , na ginagamit para i-standardize ang range sa iba't ibang feature. Kaya, ang hanay ng mga halaga para sa laki ng 2 na katangian ay makabuluhang mas malaki kaysa sa hanay ng mga halaga para sa laki ng katangian. Kung walang feature scaling, ang laki 2 ay labis na makakaimpluwensya sa paggana ng gastos. Ang error na ipinakilala ng size 2 attribute ay mas malaki kaysa sa error na ipinakilala ng size attribute. Ang isang simpleng feature scaling algorithm ay ibinigay sa ibaba:
Machine Learning para sa Java Developers, Part 2 - 9
Ang algorithm na ito ay ipinatupad sa klase FeaturesScalingsa halimbawang code sa ibaba. Ang klase FeaturesScalingay nagpapakita ng isang komersyal na paraan para sa paglikha ng isang scaling function na nakatutok sa data ng pagsasanay. Sa panloob, ang mga instance ng data ng pagsasanay ay ginagamit upang kalkulahin ang average, minimum at maximum na mga halaga. Kinukuha ng resultang function ang feature vector at gumagawa ng bago na may mga naka-scale na feature. Kinakailangan ang pag-scale ng feature para sa proseso ng pag-aaral at proseso ng paghula, tulad ng ipinapakita sa ibaba:
// создание массива данных
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);
Habang dumarami ang mga feature, tumataas ang akma sa layunin, ngunit mag-ingat. Kung lalayo ka at magdagdag ng napakaraming feature, maaaring matutunan mo ang layuning function na overfit.

Over-matching at cross-validation

Ang overfitting ay nangyayari kapag ang layunin na function o modelo ay umaangkop nang husto sa data ng pagsasanay, kaya't nakakakuha ito ng ingay o mga random na variation sa data ng pagsasanay. Ang isang halimbawa ng overfitting ay ipinapakita sa pinakakanang graph sa ibaba:
Machine Learning para sa Java Developers, Part 2 - 10
Gayunpaman, ang isang overfitting na modelo ay gumaganap nang napakahusay sa data ng pagsasanay, ngunit hindi maganda ang pagganap sa tunay na hindi kilalang data. Mayroong ilang mga paraan upang maiwasan ang overfitting.
  • Gumamit ng mas malaking set ng data para sa pagsasanay.
  • Gumamit ng mas kaunting mga tampok tulad ng ipinapakita sa mga graph sa itaas.
  • Gumamit ng pinahusay na machine learning algorithm na isinasaalang-alang ang regularization.
Kung ang isang algorithm ng paghula ay lumampas sa data ng pagsasanay, kinakailangan upang alisin ang mga tampok na hindi nakikinabang sa katumpakan nito. Ang kahirapan ay maghanap ng mga feature na may mas makabuluhang epekto sa katumpakan ng hula kaysa sa iba. Gaya ng ipinapakita sa mga graph, maaaring matukoy ang overfit gamit ang mga graph. Ito ay mahusay na gumagana para sa mga graph na may 2 o 3 coordinate, nagiging mahirap na i-plot at suriin ang graph kung gumagamit ka ng higit sa 2 mga tampok. Sa cross-validation, susuriin mo muli ang mga modelo pagkatapos ng pagsasanay gamit ang data na hindi alam ng algorithm pagkatapos makumpleto ang proseso ng pagsasanay. Ang available na may label na data ay dapat nahahati sa 3 set:
  • data ng pagsasanay;
  • data ng pagpapatunay;
  • data ng pagsubok.
Sa kasong ito, 60 porsiyento ng mga may label na talaan na nagpapakilala sa mga bahay ay dapat gamitin sa proseso ng mga variant ng pagsasanay ng target na algorithm. Pagkatapos ng proseso ng pagsasanay, kalahati ng natitirang data (hindi pa ginamit dati) ay dapat gamitin upang i-verify na mahusay na gumaganap ang sinanay na target na algorithm sa hindi kilalang data. Karaniwan, ang algorithm na gumaganap nang mas mahusay kaysa sa iba ay pinipili para sa paggamit. Ang natitirang data ay ginagamit upang kalkulahin ang halaga ng error para sa huling napiling modelo. Mayroong iba pang mga diskarte sa cross-validation, tulad ng k-fold . Gayunpaman, hindi ko ilalarawan ang mga ito sa artikulong ito.

Machine learning tool at Weka framework

Karamihan sa mga framework at library ay nagbibigay ng malawak na koleksyon ng mga machine learning algorithm. Bilang karagdagan, nagbibigay sila ng isang maginhawang mataas na antas na interface sa pagsasanay, pagsubok at pagproseso ng mga modelo ng data. Ang Weka ay isa sa mga pinakasikat na framework para sa JVM. Ang Weka ay isang praktikal na library ng Java na naglalaman ng mga graphical na pagsubok para sa pagpapatunay ng mga modelo. Ginagamit ng halimbawa sa ibaba ang Weka library para gumawa ng dataset ng pagsasanay na naglalaman ng mga feature at label. Paraan setClassIndex()- para sa pagmamarka. Sa Weka, ang isang label ay tinukoy bilang isang klase:
// определяем атрибуты для признаков и меток
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);
...
Maaaring i-save at i-load ang Data Set at Sample Object mula sa isang file. Gumagamit ang Weka ng ARFF (Attribute Relation File Format) na sinusuportahan ng mga benchmark ng graphics ng Weka. Ginagamit ang dataset na ito upang sanayin ang isang layunin na function na kilala bilang isang classifier sa Weka. Una sa lahat, dapat mong tukuyin ang layunin ng function. Ang code sa ibaba LinearRegressionay lilikha ng isang instance ng classifier. Ang classifier na ito ay sasanayin gamit ang buildClassifier(). Pinipili ng pamamaraan buildClassifier()ang mga parameter ng theta batay sa data ng pagsasanay sa paghahanap ng pinakamahusay na target na modelo. Sa Weka, hindi mo kailangang mag-alala tungkol sa pagtatakda ng rate ng pagkatuto o bilang ng mga pag-ulit. Nagsasagawa rin si Weka ng feature scaling nang nakapag-iisa.
Classifier targetFunction = new LinearRegression();
targetFunction.buildClassifier(trainingDataset);
Kapag nagawa na ang mga setting na ito, magagamit ang layuning function upang mahulaan ang presyo ng isang bahay, tulad ng ipinapakita sa ibaba:
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));
Nagbibigay ang Weka ng klase Evaluationupang subukan ang isang sinanay na classifier o modelo. Sa code sa ibaba, isang napiling hanay ng data ng pagpapatunay ang ginagamit upang maiwasan ang mga maling resulta. Ang mga resulta ng pagsukat (gastos ng error) ay ipapakita sa console. Karaniwan, ginagamit ang mga resulta ng pagsusuri upang ihambing ang mga modelong sinanay gamit ang iba't ibang algorithm ng machine learning, o mga variation ng mga ito:
Evaluation evaluation = new Evaluation(trainingDataset);
evaluation.evaluateModel(targetFunction, validationDataset);
System.out.println(evaluation.toSummaryString("Results", false));
Ang halimbawa sa itaas ay gumagamit ng linear regression, na hinuhulaan ang mga numerical na halaga, gaya ng presyo ng isang bahay, batay sa mga halaga ng input. Sinusuportahan ng linear regression ang hula ng tuloy-tuloy na mga numerical value. Upang mahulaan ang mga binary na halaga ("Oo" at "Hindi"), kailangan mong gumamit ng iba pang mga algorithm ng machine learning. Halimbawa, decision tree, neural network o logistic regression.
// использование логистической регрессии
Classifier targetFunction = new Logistic();
targetFunction.buildClassifier(trainingSet);
Maaari mong gamitin ang isa sa mga algorithm na ito, halimbawa, upang hulaan kung ang isang email na mensahe ay spam, o hulaan ang lagay ng panahon, o hulaan kung ang isang bahay ay magbebenta nang maayos. Kung gusto mong turuan ang iyong algorithm na hulaan ang lagay ng panahon o kung gaano kabilis magbebenta ang isang bahay, kailangan mo ng ibang set ng data, hal.topseller:
// использование атрибута маркера topseller instead of атрибута маркера цена
ArrayList<string> classVal = new ArrayList<>();
classVal.add("true");
classVal.add("false");

Attribute topsellerAttribute = new Attribute("topsellerLabel", classVal);
attributes.add(topsellerAttribute);
Gagamitin ang dataset na ito para sanayin ang isang bagong classifier topseller. Kapag nasanay na ito, dapat magbalik ang prediction call ng token class index na magagamit para makuha ang hinulaang halaga.
int idx = (int) targetFunction.classifyInstance(unlabeledInstances.get(0));
String prediction = classVal.get(idx);

Konklusyon

Bagama't malapit na nauugnay ang machine learning sa mga istatistika at gumagamit ng maraming mathematical na konsepto, binibigyang-daan ka ng machine learning toolkit na simulan ang pagsasama ng machine learning sa iyong mga programa nang walang malalim na kaalaman sa matematika. Gayunpaman, kapag mas nauunawaan mo ang pinagbabatayan na mga algorithm ng machine learning, gaya ng linear regression algorithm na aming na-explore sa artikulong ito, mas mapipili mo ang tamang algorithm at ibagay ito para sa pinakamainam na performance. Pagsasalin mula sa Ingles. May-akda: Gregor Roth, Arkitekto ng Software, JavaWorld.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION