Statystyczna kuchnia: Kaiserschmarrn
- 10 minut czytania - 2037 słów [Statystyka]Dzisiaj opowiem Wam, jak zrobić austriacki Kaiserschmarrn z jajek, mąki, wody i statystyki.
Przepis na dole. (Wiem, też nie znoszę tych blogów, w których najpierw ktoś opowiada swoją historię życia, a na samym końcu umieszcza przepis. Na swoje usprawiedliwienie mam to, że to nie jest blog poświęcony gotowaniu.)
Kaiserschmarrn albo Kaiserschmarren to popularna w krajach niemieckojęzycznych potrawa – w smaku dość zbliżona do amerykańskich pancakes, wywodząca się z Austrii. Jest kilka legend łączących nazwę z kajzerem Franciszkiem Józefem I.
Schmarrn to ogólne określenie chłopskiej potrawy z jajek, masła, mleka i mąki. Jedna z legend głosi, że Franciszkowi Józefowi podano Schmarrn podczas jednego z polowań w Salzkammergut; ale na cześć cesarza dodano doń rodzynek w rumie i posypano cukrem pudrem. Etymolodzy podejrzewają jednak, że część Kaiser w rzeczywistości pochodzi od Kaser (= Senner, pasterz w dialekcie tyrolskim) albo Casa (dom).
Bardzo dobry jest Kaiserschmarrn, nawet bez rodzynek (nigdy go nie robię z rodzynkami, bo niektórzy nie lubią), czy to jako deser, czy jako śniadanie. Można dodać (zgodnie z tradycją) musu z jabłek, albo (totalnie wbrew tradycji) polać syropem klonowym. Często robiłem go w niedzielę jak moi synowie byli jeszcze mali.
Oprócz jedzenia, Kaiserschmarrn świetnie nadaje się do nauki statystyki. Bo widzicie, już dosyć dawno zacząłem stosować quasi-statystyczną metodologię przy gotowaniu. Kiedy zabieram się za jakiś nowy przepis, zwłaszcza jeśli jest to jakaś popularna potrawa, to zamiast skorzystać z jednego konkretnego wariantu czytam kilka czy nawet kilkanaście. Dzięki temu nabieram wyczucia: co jest istotne, a co nie, jaki jest zakres zmienności składników, jakie są różnice w sposobie przygotowania, itd. Na dłuższą metę okazuje się to bardzo skuteczne.
Nie uwierzycie, ale zebrałem 100 różnych przepisów na Kaiserschmarrn, i jeszcze dodałem swój własny oraz trzy wygenerowane przez AI. Teraz je sobie przeanalizujemy1.
Zanim zabierzemy się za analizę, trzeba by te dane jakoś znormalizować. No bo wiadomo: jeśli wezmę dwa jajka, 100 gr mąki i 200 g mleka to dostanę właściwie to samo, co jakbym wziął jedno jajko, 50 g mąki i 100 g mleka, tylko dwa razy więcej. Znormalizujemy więc najpierw dane tak, żeby przeliczyć procentowy udział składników według wagi (liczę przy tym, że standardowe jajko z Sevres ma 55g, oraz przyjmuję gęstość mleka 1g/ml).
Pierwsze, co się rzuca w oczy, to olbrzymia różnorodność receptur. Oczywiście, wszystkie przepisy zawierają jajka, mąkę, mleko i cukier, a znakomita większość z nich również cukier waniliowy.
Ale proporcje jajek, mąki i mleka są bardzo różne. Poza tym, niektóre przepisy każą dodawać proszek do pieczenia, niektóre wodę mineralną. Popatrzmy na procentowy skład masy:
Jeden z przepisów w 20% składa się z cukru!
Waha się nawet gęstość masy, wyrażona przez procentowy udział wody
(kategoria woda całkowita
), między 45% a ponad 70%.
Może powinniśmy po prostu wszystko uśrednić? Wziąć, dajmy na to, 2 jajka, 80 g mąki, 130 ml mleka, 40 ml wody mineralnej i 20 g cukru? Prawdopodobnie zadziałałoby całkiem nieźle, ale to by było za proste. Po co prosto, jeśli można się tymi danymi pobawić?
Pewien bioinformatyk powiedział mi kiedyś, że wszyscy mają jakąś swoją ulubioną metodę analizy, którą stosują w pierwszej kolejności – nieważne, jakie są dane. Moja ulubiona metoda to analiza komponentów głównych (principal component analysis, PCA). Ma oczywiście wiele ograniczeń, ale jak dla mnie olbrzymią zaletę, jaką jest jej prostota i łatwość w interpretacji.
Poniżej wynik PCA:
Powyżej widzimy cztery pierwsze komponenty. Kolorowo oznaczone są przepisy, które zostały wygenerowane przez sztuczną inteligencję, mój przepis i przepis uśredniony. Jak widać, OpenAI jest zachowawczy i przepisami trafia w centrum. Natomiast Google Bard… um, ma najwyraźniej dosyć odjechany przepis. Nic dziwnego: na dwa jajka, bard zaproponował prawie pół litra płynu - to ponad 65% całej masy. Gwarantuję wam, że z tego nie wyjdzie nic ciekawego.
No dobrze, ale co właściwie mówią nam komponenty?
Każda komponenta to jest kombinacja liniowa użytych składników. Innymi słowy, pozycja danego przepisu na osi oznaczonej “PC1” zależy od tego, ile w przepisie jest mąki, ile mleka, ile wody i ile cukru. Ale nie jest to zwykła suma, tylko suma z wagami: niektóre składniki mają większy wpływ na pozycję przepisu na osi, a niektóre mniejszy.
Na przykład, na osi PC1 przepisy ułożone bardziej na prawo mają więcej mąki i mleka, a mniej jajek i cukru. Natomiast na osi PC2 przepisy ułożone wyżej mają więcej mleka i jajek, a mniej mąki i wody mineralnej2.
Pytanie, jakie mnie jednak nurtowało, brzmi inaczej: czy istnieją pewne grupy przepisów? Like, czy można podzielić przepisy na np. bardzo jajeczne i mało jajeczne, albo na ciężkie i lekkie? Liczyłem na to, że dostrzegę te grupy już na wykresie PCA, ale niestety nie udało się i przyjdzie nam wytoczyć cięższe działa.
W mojej dziedzinie bardzo popularną alternatywą do PCA jest umap. Podobnie jak PCA, umap jest metodą redukcji wymiarowości, ale dużo bardziej skomplikowaną. Jeśli Was interesuje jak działa umap, to tu jest opis, a tu znajdziecie świetne demonstracje (polecam zwłaszcza zabawę mamutem).
Zaletą umapa jest jego zdolność do wykrywania grup, nawet wtedy, gdy grupy te nie są wyraźnie rozdzielone. W przeciwieństwie do PCA, Umap nie jest liniowy, co oznacza, że nie można go opisać jako kombinacji liniowej zmiennych wejściowych – i to jest jego wada, bo nie mogę łatwo powiedzieć, skąd się te nowe współrzędne biorą.
To już jest ciekawe! W tej projekcji przepisy są podzielone na przynajmniej trzy, jeśli nie cztery grupy; np. w jednej jest Google Bard, w drugiej chatGPT 3.5, w trzeciej – chatGPT 4.0.
Rzecz ciekawa: proporcje uśrednione grupują się razem z przedziwnym przepisem barda. Dlaczego? Prawdopodobnie dlatego, że proporcje uśrednione zawierają też niewielki dodatek wody. Najwyraźniej umap zgrupował wszystkie przepisy, które dodają wodę mineralną do ciasta. Łatwo to sprawdzić: na obrazku poniżej kolory oznaczają, czy przepis dodaje wodę, czy nie.
Zanim zabierzemy się za sprawdzanie, czym oprócz wody te grupy się różnią, spróbujmy sprawdzić, ile w ogóle tych grup (klastrów) jest.
Poniżej do grupowania skorzystam z algorytmu k-średnich (ang. k-means), bardzo prościutkiego i bardzo popularnego. Metoda wymaga jednak wstępnego podania liczby grup, na które chcemy podzielić dane, a przecież dokładnie to chcielibyśmy wiedzieć. Dlatego zastosujemy prostego tricka, którego ja nazywam “krzywą łokciową” (w ang. stosuje się określenie “elbow method”). Wygląda to tak: używamy algorytmu, żeby podzielić dane na jeden, dwa, trzy, cztery, itd. grupy. Dla każdego podziału liczymy sobie pewną wartość (co to konkretnie jest, opowiem za moment), która nam mówi, jak ciasno przepisy się grupują, i narysujemy sobie wynik zależnie od liczby grup.
Na obrazku powyżej mamy jakby rękę: u góry po lewej jest ramię, u dołu po prawej jest dłoń, a gdzieś pośrodku jest łokieć. Ten łokieć nas interesuje:
OK, ale żeby dokładnie wyjaśnić co właściwie jest ta wartość na osi Y, musimy pogadać o zmienności.
Przepisy na Kaiserschmarrn różnią się od siebie, zatem mają pewną zmienność. Zmienność w statystyce ma pewną ciekawą właściwość: jest addytywna. Jeśli na przykład mamy dwa zestawy danych, i każdy z własną zmiennością, to zmienność całego zestawu danych jest równa sumie zmienności obu zestawów plus zmienności między tymi zestawami.
Ja wiem, ciężko sobie wyobrazić o czym ja właściwie mówię, w każdym razie bez dokładnego zdefiniowania zmienności i podania paru wzorów. Może ten obrazek trochę pomoże:
Całkowitą zmienność naszych przepisów na Kaiserschmarrn możemy podzielić na część między grupami i wewnątrz grup. Innymi słowy, jeśli podzielimy dane na dajmy na to trzy grupy, to całkowita zmienność wszystkich danych jest równa zmienności wewnątrz tych trzech grup plus zmienności między grupami.
Wyobraźcie sobie, że w ogóle nie ma podziału na grupy. W takim razie, nie ma żadnej zmienności między grupami, prawda? Czyli cała zmienność równa jest zmienności w grupach, bo cały zestaw przepisów to jedna wielka grupa.
A teraz drugie ekstremum: dzielimy przepisy na tyle grup, ile jest przepisów. Czyli w każdej grupie znajdzie się dokładnie jeden przepis. W takim wypadku nie ma zmienności wewnątrz grup – bo wewnątrz grup jest zawsze tylko jeden stały punkt. Cała zmienność jest między grupami.
Oczywiście, oba te ekstrema są mało ciekawe. Nas interesuje jakiś złoty środek.
Obrazek z łokciem pokazuje na osi Y jaka jest część zmienności wewnątrz grup. Zauważcie, że im więcej mamy grup, tym mniejsza jest część zmienności wewnątrz grup. Ale nie tylko to: spadek zmienności też maleje. Dla dwóch grup, prawie połowa zmienności jest wewnątrz grup. Dla trzech, mniej niż jedna czwarta (spadek o 25). Ale dla czterech – jedna dziesiąta (spadek o 15). I tak dalej. W pewnym momencie robi się to mało opłacalne: mnożymy grupy bez potrzeby, ale nie zmieniamy dramatycznie sytuacji.
Oczywiście, że z jednej strony chcielibyśmy mieć grupy, które się od siebie różnią – a więc maksymalizować zmienność między grupami. Z drugiej jednak strony, nie chcemy mieć tych grup za dużo.
Prosta metoda “na oko” wygląda tak: wybieramy tę liczbę grup, gdzie znajduje się “łokieć”. Metoda jest co prawda bardzo niedokładna (i zależy od tego, jak zmrużymy oczy), ale w praktyce sprawdza się całkiem nieźle. W naszym przypadku, wygląda mi na to, że najlepszy podział jest na cztery grupy3.
To teraz zajmiemy się tymi czterema grupami.
Najpierw rysunek pokazujący jak właściwie wyglądają te grupy:
To bardzo fajnie, ale nie mówi nam to wiele o tym, co te grupy oznaczają. Ale akurat w naszym przypadku to jest łatwe, bo nie mamy zbyt wielu zmiennych. Po prostu zobaczymy, jaki jest procentowy udział poszczególnych składników w każdej grupie.
Możemy też użyć nieco innej wizualizacji. Poniższe słupki pokazują medianę procentowego udziału poszczególnych składników w każdej grupie. Wąsy błędów (jak po polsku jest “error bar”?) pokazują zaś kwartyle 1 i 3. Przy okazji: jest to jeden z nielicznych uzasadnionych przypadków użycia słupków w wizualizacji danych, bo pokazujemy procenty. Ładne, bo kolorowe, ale widać, że poprzednia wizualizacja lepiej umożliwia między grupami.
No i pięknie:
- grupa 1: mało cukru, sporo mleka
- grupa 2: dużo cukru, gęste ciasto
- grupa 3: dodatek z wody mineralnej (Google Bard), mniej mleka i jajek
- grupa 4: dużo mleka, dużo mąki (tu jest mój przepis)
I jeszcze może jedna informacja. Łatwo policzyć, który przepis ma ile kalorii na 100g.
A teraz wreszcie kolej na mój przepis.
Przepis
Składniki
Ilość na dwoje dorosłych albo jednego nastolatka. Wliczając masło i cukier puder, ca. 200 kcal/100g, czyli jakieś 1000 kcal na całość (w obliczeniach powyżej wychodziło 176 kcal/100g, ale to nie uwzględniało dodatków).
- 2 jajka, rozdzielone na żółtka i białka
- 100 g mąki
- 200 g mleka albo 100 g jogurtu naturalnego + 100 g wody
- 30 g cukru
- szczypta soli
- paczka cukru waniliowego
- pół paczki proszku do pieczenia (niekoniecznie)
- cukier puder do posypania
- masło do smażenia (dobra czubata łyżka na 2 jajka)
Przygotowanie
Robię w trzech naczyniach:
- białka ubijam mikserem na twardą pianę w jednym naczyniu
- potem w drugim mieszam mąkę i mleko
- a na końcu ucieram w trzecim żółtka z solą, połową cukru i cukrem waniliowym (i proszkiem do pieczenia, jeśli dodaję)
Żółtka muszą być z cukrem fest utarte, aż kolor zmieni się z żółtego na kremowy. Kolejność jest dyktowana użyciem miksera: nie chcę myć go po każdym użyciu, a w ten sposób nie muszę.
Jak ktoś lubi rodzynki, to to jest właściwy moment żeby je dodać. Można je też uprzednio namoczyć w rumie (ale kto wieczorem zastanawia się, czy następnego dnia będzie robił Kaiserschmarrn?).
Potem najpierw mieszam żółtka i mąkę (mikserem), a następnie dodaję dużą łychą białka i delikatnie je rozprowadzam.
Patelnię rozgrzewam, ale bardzo delikatnie - na niewielkim ogniu. Roztapiam masło i wylewam masę (masa z dwóch jajek akurat pasuje na patelnię 26cm). Grubość warstwy powinna być 1-2.5 cm. Trzeba teraz masę delikatnie smażyć na małym ogniu aż spód się zrumieni i masa trochę stężeje. Jak jest za duży ogień, to spód przypali się zanim masa stężeje (been there, done that). Za to jeśli masa nie całkiem stężeje, to nie ma tragedii.
Następnie należy masę przewrócić na drugą stronę. Ja to robię dwiema dużymi łopatkami, ale można też użyć talerza. Jeśli się rozwali, nie szkodzi! Kaiserschmarrn i tak podaje się w kawałkach.
Teraz najpierw chwilę rumienię Kaiserschmarrn z drugiej strony, a potem rozrywam na kawałki (tak długości / grubości kciuka mniej więcej) i posypuję resztą cukru. Zwiększam ogień, żeby kawałki ładnie się zbrązowiły, a cukier trochę skarmelizował.
Gotowe, jeszcze tylko posypać cukrem pudrem.
Kod analizy, czyli całą tę notkę w formacie quarto (wariant rmarkdown) znajdziecie tutaj. ↩︎
Przed policzeniem komponentów zmienne zostały wyskalowane, tak żeby średnia każdej z nich była równa 0, a odchylenie standardowe równe 1. ↩︎
Oczywiście, istnieją znacznie bardziej “fachowe” metody. Analiza sylwetek sugerowałaby, że mamy raczej do czynienia z pięcioma grupami, natomiast statystyka GAP potwierdza, że mamy cztery grupy. ↩︎