Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
ed:lab_08 [2024/04/09 04:55]
pszwed [2.1 Budowa modelu i interpretacja współczynników]
ed:lab_08 [2024/04/24 23:20] (current)
pszwed [4. LogisticRegressionGrid - tworzenie tabeli ocen]
Line 1: Line 1:
-====== Regresja logistyczna ======+====== Laboratorium 8 - regresja logistyczna ======
  
 Celem jest budowa modelu regresji logistycznej pozwalającej przewidywać, czy dany student zdał egzamin z języka C++ w pierwszym terminie. Celem jest budowa modelu regresji logistycznej pozwalającej przewidywać, czy dany student zdał egzamin z języka C++ w pierwszym terminie.
Line 14: Line 14:
  
 === Zbiory danych === === Zbiory danych ===
-  * {{ :ed:egzamin-cpp.csv |egzamin-cpp.csv}} - zanonimizowane wyniki zaliczeń/egzaminu z C i C++ w 2016 roku +  * {{ :ed:egzamin-cpp.csv |egzamin-cpp.csv}} - poddane anonimizacji wyniki zaliczeń/egzaminu z C i C++ w 2016 roku 
   * {{ :ed:grid.csv |grid.csv}} - kombinacje ocen    * {{ :ed:grid.csv |grid.csv}} - kombinacje ocen 
  
Line 88: Line 88:
 </code> </code>
  
-**2.** Regresja logistyczna wymaga, aby atrybutów wejściowe były typu numerycznego. Jets też metodą klasyfikacji binarnej (etykiety powinny mieć wartości 0 i 1)+**2.** Regresja logistyczna wymaga, aby atrybutów wejściowe były typu numerycznego. Jest też metodą klasyfikacji binarnej (etykiety powinny mieć wartości 0 i 1)
   * przekonwertuj datę  za pomocą funkcji ''unix_timestamp'' - nadaj nowej kolumnie nazwę ''timestamp''   * przekonwertuj datę  za pomocą funkcji ''unix_timestamp'' - nadaj nowej kolumnie nazwę ''timestamp''
   * Dodaj kolumnę ''Wynik'' będącą wynikiem testu, czy ''Egzamin>=3.0'' - użyj funkcji SQL IF()   * Dodaj kolumnę ''Wynik'' będącą wynikiem testu, czy ''Egzamin>=3.0'' - użyj funkcji SQL IF()
Line 110: Line 110:
 </code> </code>
  
-===== 2. Analiza działania algorytmu  =====+===== 2. LogisticRegressionAnalysis - analiza działania algorytmu  =====
  
 ==== 2.1 Budowa modelu i interpretacja współczynników ==== ==== 2.1 Budowa modelu i interpretacja współczynników ====
Line 139: Line 139:
 **3.** Zinterpretuj współczynniki równania regresji (napisz kod lub zamieść wykonane obliczenia). Pamiętaj, że timestamp jest wyrażony w sekundach. **3.** Zinterpretuj współczynniki równania regresji (napisz kod lub zamieść wykonane obliczenia). Pamiętaj, że timestamp jest wyrażony w sekundach.
  
-Poniższe wyniki były wygenerowane za pomocą kodu. W praktyce wynik nie zależy od daty...+Poniższe wyniki były wygenerowane programowo. W praktyce wynik nie zależy od daty...
 <code> <code>
 Wzrost OcenaC o 1 zwiększa logit o 0.719097, a szanse zdania razy 2.052578 czyli o 105.257821% Wzrost OcenaC o 1 zwiększa logit o 0.719097, a szanse zdania razy 2.052578 czyli o 105.257821%
Line 169: Line 169:
  
 Wewnątrz: Wewnątrz:
-  * oblicz wartośc ''logit'' jako iloczyn skalarny współczynników i cech powięksozny o ''lrModel.intercept()''+  * oblicz wartośc ''logit'' jako iloczyn skalarny współczynników i cech powiększony o ''lrModel.intercept()''
   * Oblicz prawdopodobieństwo P(0) i P(1) z odpowiedniego wzoru - wykorzystując wartośc logit   * Oblicz prawdopodobieństwo P(0) i P(1) z odpowiedniego wzoru - wykorzystując wartośc logit
   * Wyświetl i porównaj wartości ''rawPrediction'' i ''prawdopodobieństwa''   * Wyświetl i porównaj wartości ''rawPrediction'' i ''prawdopodobieństwa''
-  * Wyświetl parwdopodobieństwo wybranej przez klasyfikator etykiety - czyli większe z prawdopodobieństw+  * Wyświetl prawdopodobieństwo wybranej przez klasyfikator etykiety - czyli większe z prawdopodobieństw
   * Funkcja ''row.getAs(String)'' zwraca element w danej kolumnie. Użyj też funkcji ''Vector.argmax()''    * Funkcja ''row.getAs(String)'' zwraca element w danej kolumnie. Użyj też funkcji ''Vector.argmax()'' 
    
Line 240: Line 240:
 Instrukcja ''df_predictions = df_predictions.repartition(1);'' jest opcjonalna. Jaka będzie postać wyjścia, kiedy zmienimy argument ''repartition'' - np. ustawimy 5. Instrukcja ''df_predictions = df_predictions.repartition(1);'' jest opcjonalna. Jaka będzie postać wyjścia, kiedy zmienimy argument ''repartition'' - np. ustawimy 5.
  
 +===== 3. LogisticRegressionScores - ocena wyników =====
 +
 +Napisz funkcję trainAndTest, która:
 +
 +  * dokona podziału na zbiór treningowy i testowy
 +  * skonfiguruje algorytm
 +  * i przeprowadzi uczenie na zbiorze treningowym 
 +
 +<code java>
 +    static LogisticRegressionModel trainAndTest(Dataset<Row> df){
 +        int splitSeed = 123;
 +        Dataset<Row>[] splits = df.randomSplit(new double[]{0.7, 0.3},splitSeed);
 +        Dataset<Row> df_train = splits[0];
 +        Dataset<Row> df_test = splits[1];
 +
 +        LogisticRegression lr = new LogisticRegression()
 +                .setMaxIter(20)
 +                .setRegParam(0.1)
 +                .setFeaturesCol("features")
 +                .setLabelCol("Wynik");
 +
 +
 +        LogisticRegressionModel lrModel = lr.fit(df_train);
 +        ...
 +        return lrModel;
 +    }
 +</code>
 +
 +==== 3.1 Analiza informacji zebranych w training summary ====
 +
 +<code java>
 +BinaryLogisticRegressionTrainingSummary trainingSummary = lrModel.binarySummary();
 +</code>
 +
 +**1.** Pobierz historię objective history i wyświetl jej wykres. Napisz odpowiednią funkcję do wyświetlania wykresu ''plotObjectiveHistory()''
 +
 +
 +<code java>
 +double[] objectiveHistory = trainingSummary.objectiveHistory();
 +plotObjectiveHistory(objectiveHistory);
 +</code>
 +
 +Oczekiwany wynik:
 +
 +{{ :ed:logreg-objective-history.png?direct&400 |}}
 +
 +
 +**2.** Pobierz informacje o krzywej ROC. Możesz o niej przeczytać tu: [[https://home.agh.edu.pl/~pszwed/wiki/lib/exe/fetch.php?media=med:med-w04.pdf|Wykład 4, slajdy 24-27]]
 +
 +<code java>
 +Dataset<Row> roc = trainingSummary.roc();
 +roc.show();
 +</code>
 +
 +<code>
 ++--------------------+-------------------+
 +|                 FPR|                TPR|
 ++--------------------+-------------------+
 +|                 0.0|                0.0|
 +|                 0.0|0.07692307692307693|
 +|                 0.0|0.09615384615384616|
 +|                 0.0|0.15384615384615385|
 +|                 0.0|0.21153846153846154|
 +|                 0.0|0.23076923076923078|
 +|                 0.0| 0.3076923076923077|
 +|                 0.0|0.34615384615384615|
 +|                 0.0|0.38461538461538464|
 +|                 0.0| 0.4230769230769231|
 +|                 0.0| 0.4807692307692308|
 +|                 0.0|                0.5|
 +|                 0.0| 0.5192307692307693|
 +|                 0.0| 0.5576923076923077|
 +|                 0.0| 0.5961538461538461|
 +|0.047619047619047616| 0.5961538461538461|
 +|0.047619047619047616| 0.6153846153846154|
 +|0.047619047619047616| 0.6730769230769231|
 +| 0.09523809523809523| 0.6730769230769231|
 +| 0.14285714285714285| 0.6923076923076923|
 ++--------------------+-------------------+
 +</code>
 +
 +**3.** Wyświetl wykres ROC. Napisz odpowiednią funkcję
 +
 +<code java>
 +static void plotROC(Dataset<Row> roc)
 +</code>
 +
 +Oczekiwany wynik:
 +
 +{{ :ed:logrec-roc-curve.png?direct&400 |}}
 +<code java>
 +</code>
 +
 +**3.** Wyświetl miary:
 +  * Accuracy
 +  * FPR
 +  * TPR
 +  * Precision
 +  * Recall
 +  * F-measure
 +
 +==== 3.2 Dobór progu prawdopodobieństwa ====
 +
 +Krzywą ROC można wykorzystać do doboru progu prawdopodobieństwa. Patrz [[https://home.agh.edu.pl/~pszwed/wiki/lib/exe/fetch.php?media=med:med-w04.pdf|Wykład 4 slajd 27]]
 +
 +**1.** Dobierzemy próg według miary //F-measure//. To będzie gdzieś tu:
 +<code java>
 +Dataset<Row> df_fmeasures = trainingSummary.fMeasureByThreshold();
 +df_fmeasures.offset(35).show();
 +</code>
 +
 +<code>
 ++-------------------+------------------+
 +|          threshold|         F-Measure|
 ++-------------------+------------------+
 +| 0.4627032508959811|0.8869565217391304|
 +| 0.4382847817892507|0.8793103448275861|
 +| 0.4034706528697256| 0.888888888888889|
 +| 0.3858997834933381|0.8813559322033898|
 +| 0.3461380134069699| 0.859504132231405|
 +| 0.3143853597224281|0.8524590163934427|
 +|0.19135299955580787|0.8455284552845529|
 +| 0.1472470120383692|0.8387096774193548|
 +|0.13010893832947723|             0.832|
 ++-------------------+------------------+
 +</code>
 +
 +**2.** Wyznacz programowo najlepszy próg. 
 +  * Wpierw wyznacz maksymalną wartość F-measure (przykład kodu poniżej)
 +  * A następnie odpowiadającą jej wartość progu (używając ''where ... equalTo ... select...'')
 +  * W powyższej tabelce możesz sprawdzić, czy znalezione zostały właściwe wartości (oczywiście one zależą od sposobu podziału na zbiór treningowy i testowy, a więc ziarna ''seed''  
 +
 +<code java>
 +double maxFMeasure = df_fmeasures.select(functions.max("F-Measure")).head().getDouble(0);
 +</code>
 +
 +**3.** Ustaw próg klasyfikatora
 +
 +<code java>
 +lrModel.setThreshold(bestThreshold);
 +</code>
 +
 +==== 3.3 Ewaluacja na zbiorze testowym ====
 +
 +**1.** Wywołaj funkcję predykcji i skonfiguruj ewaluator
 +
 +<code java>
 +        Dataset<Row> predictions = lrModel.transform(df_test);
 +
 +        MulticlassClassificationEvaluator eval = new MulticlassClassificationEvaluator()
 +                .setLabelCol("Wynik")
 +                .setPredictionCol("prediction");
 +</code>
 +
 +**2.** Wyznacz:
 +  * accuracy
 +  * weightedPrecision
 +  * weightedRecall
 +  * f1   
 +
 +Oczekiwane są wartości rzędu 0.82-0.83
 +
 +Nazwy dostępnych metryk:
 +<code>
 +(f1|accuracy|weightedPrecision|weightedRecall|weightedTruePositiveRate| weightedFalsePositiveRate|weightedFMeasure|truePositiveRateByLabel| falsePositiveRateByLabel|precisionByLabel|recallByLabel|fMeasureByLabel| logLoss|hammingLoss)'
 +</code>
 +
 +
 +===== 4. LogisticRegressionGrid - tworzenie tabeli ocen =====
 +
 +Celem jest utworzenie tabeli ocen postaci, jak poniżej
 +
 +<code>
 ++--------------+------+----------+--------+--------+
 +|  ImieNazwisko|OcenaC|     DataC|OcenaCpp|   Wynik|
 ++--------------+------+----------+--------+--------+
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     2.0|Nie zdał|
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     3.0|Nie zdał|
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     3.5|    Zdał|
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     4.0|    Zdał|
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     4.5|    Zdał|
 +|'Xxxxx Yyyyyy'  3.0|2016-01-17|     5.0|    Zdał|
 +|'Xxxxx Yyyyyy'  3.5|2016-01-17|     2.0|Nie zdał|
 +|'Xxxxx Yyyyyy'  3.5|2016-01-17|     3.0|Nie zdał|
 +|'Xxxxx Yyyyyy'  3.5|2016-01-17|     3.5|    Zdał|
 +|'Xxxxx Yyyyyy'  3.5|2016-01-17|     4.0|    Zdał|
 +
 +...
 +</code>
 +
 +**Uwaga:** wynik może się nieco różnić w zależności od konfiguracji, np. progu prawdopodobieństwa 
 +
 +**1.** Wytrenuj klasyfikator na zbiorze ''egzamin-cpp.csv''. Wykorzystuj kod z poprzedniej części, ustaw próg prawdopodobieństwa.
 +
 +**2.** Napisz funkcje
 +
 +<code java>
 +void addClassificationToGrid(SparkSession spark, LogisticRegressionModel lrModel)
 +</code>
 +
 +która:
 +  * Wczyta zbiór danych ''grid.csv''
 +  * Przetworzy daty, tak aby stały się wartościami numerycznymi
 +  * Skonfiguruje VectorAssembler
 +  * Wywoła funkcję predykcji zmiennej ''lrMpdel''
 +  * Usunie nadmiarowe kolumny
 +  * Za pomocą funkcji ''IF()'' SQL lub zarejestrowanej funkcji użytkownika UDF dokona konwersji etykiet //0->Nie zdał// oraz //1->Zdał//
 +  * Wyświetli wynik
 +  * Zapisze w pliku ''grid-with-classification.csv'' 
ed/lab_08.1712631334.txt.gz · Last modified: 2024/04/09 04:55 by pszwed
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0