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
Last revision Both sides next 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:19]
pszwed [3. LogisticRegressionScores - ocena wyników]
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.** Wytrenuje 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.txt · Last modified: 2024/04/24 23:20 by pszwed
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0