From 1f98b6813c0db9ad150c38f1636a2fcf66dee54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Sk=C3=B3rzewski?= Date: Fri, 25 Mar 2022 08:51:48 +0100 Subject: [PATCH] =?UTF-8?q?Reprezentacja=20danych=20-=20uzupe=C5=82nienie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wyk/04a_Reprezentacja_danych.ipynb | 315 ++++++++++++++++++++++++----- 1 file changed, 266 insertions(+), 49 deletions(-) diff --git a/wyk/04a_Reprezentacja_danych.ipynb b/wyk/04a_Reprezentacja_danych.ipynb index bdb86c1..0ee073a 100644 --- a/wyk/04a_Reprezentacja_danych.ipynb +++ b/wyk/04a_Reprezentacja_danych.ipynb @@ -14,15 +14,23 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Na tym wykładzie dowiemy się, w jaki sposób reprezentować różnego rodzaju dane tak, żeby można było używać ich do uczenia maszynowego." ] }, { "cell_type": "code", - "execution_count": 14, - "metadata": {}, + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, "outputs": [], "source": [ "# Przydatne importy\n", @@ -37,15 +45,23 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Plik *mieszkania4.tsv* zawiera dane wydobyte z serwisu *gratka.pl* dotyczące cen mieszkań w Poznaniu." ] }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -86,7 +102,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Jak widać powyżej, w pliku *mieszkania4.tsv* znajdują się dane różnych typów:\n", "* dane numeryczne (po prostu liczby):\n", @@ -101,35 +121,52 @@ " * garaż\n", "* dane kategoryczne (wybór jednej z kilku kategorii):\n", " * typ zabudowy\n", + " * materiał budynku\n", "* dane tekstowe (dowolny tekst):\n", " * opis" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Algorytmy uczenia maszynowego działają na danych liczbowych. Z tego powodu musimy znaleźć właściwy sposób reprezentowania pozostałych danych." ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Dane numeryczne" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Dane numeryczne to takie, które są liczbami. W większości przypadków możemy na nich operować bezpośrednio. Przykładem takich danych jest kolumna *Powierzchnia w m2* z powyższego przykładu:" ] }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -168,15 +205,23 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Czasami w danej kolumnie oprócz liczb występują również inne wartości. Przykładem takiej cechy może być *Piętro*:" ] }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -192,26 +237,78 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 7, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1 897\n", + "parter 833\n", + "2 719\n", + "3 669\n", + "4 549\n", + "5 260\n", + "7 78\n", + "8 63\n", + "9 59\n", + "6 55\n", + "11 39\n", + "12 35\n", + "10 32\n", + "14 25\n", + "13 25\n", + "16 11\n", + "poddasze 5\n", + "15 4\n", + "niski parter 1\n", + "Name: Piętro, dtype: int64" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "alldata['Piętro'].value_counts() # ile razy która wartość występuje" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Jak widać powyżej, tutaj oprócz liczb pojawiają się pewne tekstowe wartości specjalne, takie jak `parter`, `poddasze` czy `niski parter`." ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Takie wartości należy zamienić na liczby. Jak?\n", "* Wydaje się, że `parter` czy `niski parter` można z powodzeniem potraktować jako piętro „zerowe” i zamienić na `0`.\n", "* Z poddaszem sytuacja nie jest już tak oczywista. Czy mają Państwo jakieś propozycje?\n", " * Może zamienić `poddasze` na wartość NaN (zobacz poniżej)?\n", - " * Może wykorzystać w tym celu wartość z sąsiedniej kolumny *Liczba pięter w budynku*?" + " * Może wykorzystać w tym celu wartość z sąsiedniej kolumny *Liczba pięter w budynku*?\n", + " * Skoro `poddasze` pojawia się tylko w nielicznych przykładach, może w ogóle odrzucić te przykłady?" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Można w tym celu wykorzystać funkcje [apply](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html?highlight=apply#pandas.DataFrame.apply) i [to_numeric](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_numeric.html) z biblioteki `pandas`." ] @@ -219,7 +316,11 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -244,7 +345,11 @@ { "cell_type": "code", "execution_count": 19, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -277,14 +382,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "### Wartości NaN" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Wartość NaN (zob. też na [Wikipedii](https://pl.wikipedia.org/wiki/NaN)) – to wartość numeryczna oznaczająca „nie-liczbę”, „wartość niezdefiniowaną”, np. niezdefiniowany wynik działania lub brak danych:" ] @@ -292,7 +405,11 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -325,7 +442,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Co można zrobić z wartością NaN?\n", "* Czasami można wartość NaN zamienić na `0`, np. być może w kolumnie „przychód” wartość NaN oznacza brak przychodu. Należy jednak być z tym ostrożnym. **W większości przypadków wstawienie 0 zamiast NaN będzie niepoprawne**, np. „rok 0” to nie to samo co „rok nieznany”. Nawet w kolumnie „cena” wartość NaN raczej oznacza, że cena jest nieznana, a to przecież nie to samo, co „cena równa 0 zł”.\n", @@ -336,7 +457,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Przydatne artykuły na temat usuwania wartości niezdefiniowanych ze zbioru danych:\n", "* [Working with missing data in machine learning](https://towardsdatascience.com/working-with-missing-data-in-machine-learning-9c0a430df4ce)\n", @@ -345,7 +470,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Biblioteka `pandas` dostarcza narzędzi do automatycznego usuwania wartości NaN: [dropna](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html)" ] @@ -353,7 +482,11 @@ { "cell_type": "code", "execution_count": 21, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -374,14 +507,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Dane boole'owskie" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "W przypadku danych typu prawda/fałsz, wystarczy zamienić wartości `True` na `1`, a `False` na `0`:" ] @@ -389,7 +530,11 @@ { "cell_type": "code", "execution_count": 22, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -419,7 +564,11 @@ { "cell_type": "code", "execution_count": 23, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -452,14 +601,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Dane kategoryczne" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "O danych kategorycznych mówimy, jeżeli dane mogą przyjmować wartości ze skończonej listy („kategorii”), np.:" ] @@ -467,7 +624,11 @@ { "cell_type": "code", "execution_count": 27, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -488,7 +649,11 @@ { "cell_type": "code", "execution_count": 28, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -508,7 +673,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Cechę kategoryczną można rozbić na skończoną liczbę cech boole'owskich:" ] @@ -516,7 +685,11 @@ { "cell_type": "code", "execution_count": 29, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [], "source": [ "# Skopiujmy dane, żeby przedstawić 2 alternatywne rozwiązania\n", @@ -528,7 +701,11 @@ { "cell_type": "code", "execution_count": 30, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -588,7 +765,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Nie trzeba tego robić ręcznie. Można do tego celu użyć funkcji [get_dummies](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html) z biblioteki `pandas`:" ] @@ -596,7 +777,11 @@ { "cell_type": "code", "execution_count": 31, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -705,14 +890,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Zwróćmy uwagę, że dzięki użyciu `get_dummies` nowe kolumny zostały utworzone i nazwane automatycznie, nie trzeba też już ręcznie konwertować wartości boole'owskich do numerycznych." ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Funkcja `get_dummies` do określenia, na ile i jakich kolumn podzielić daną kolumnę kategoryczną, używa bieżącej zawartości tabeli. Dlatego należy jej użyć przed dokonaniem podziału na zbiory uczący i testowy.\n", "\n", @@ -721,21 +914,33 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## Dane tekstowe" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Przetwarzanie danych tekstowych to szeroki temat, którym można zapełnić cały wykład. Dlatego tutaj przedstawię tylko najważniejsze metody." ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Możemy na przykład tworzyć cechy sprawdzające występowanie poszczególnych wyrazów lub ciągów znaków w tekście:" ] @@ -743,7 +948,11 @@ { "cell_type": "code", "execution_count": 15, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "outputs": [ { "name": "stdout", @@ -773,14 +982,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Można też zamienić tekst na wektory używając algorytmów TF–IDF, Word2Vec lub podobnych." ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, "source": [ "Ciekawy artykuł na temat przygotowywania danych tekstowych do uczenia maszynowego można znaleźć na przykład tutaj: https://machinelearningmastery.com/prepare-text-data-machine-learning-scikit-learn/" ]