Laboratoria 3. Reprezentacja danych
This commit is contained in:
parent
88d5ee3c40
commit
af70714c8a
@ -8,7 +8,7 @@
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"### AITech — Uczenie maszynowe — laboratoria\n",
|
||||
"### Uczenie maszynowe — laboratoria\n",
|
||||
"# 1. Podstawowe narzędzia uczenia maszynowego"
|
||||
]
|
||||
},
|
||||
@ -2220,7 +2220,7 @@
|
||||
"metadata": {
|
||||
"celltoolbar": "Slideshow",
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"display_name": "Python 3.10.6 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -2234,11 +2234,16 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.4"
|
||||
"version": "3.10.6"
|
||||
},
|
||||
"livereveal": {
|
||||
"start_slideshow_at": "selected",
|
||||
"theme": "amu"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"### AITech — Uczenie maszynowe — laboratoria\n",
|
||||
"### Uczenie maszynowe — laboratoria\n",
|
||||
"# 2. Wczytywanie i prezentowanie danych"
|
||||
]
|
||||
},
|
||||
@ -932,7 +932,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.4"
|
||||
"version": "3.10.6"
|
||||
},
|
||||
"livereveal": {
|
||||
"start_slideshow_at": "selected",
|
||||
|
756
lab/03_Reprezentacja_danych.ipynb
Normal file
756
lab/03_Reprezentacja_danych.ipynb
Normal file
@ -0,0 +1,756 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "-"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"### Uczenie maszynowe — laboratoria\n",
|
||||
"# 3. Reprezentacja danych"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Na tych zajęciach 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": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plik *mieszkania4.tsv* zawiera dane wydobyte z serwisu *gratka.pl* dotyczące cen mieszkań w Poznaniu."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" cena Powierzchnia w m2 Liczba pokoi Garaż Liczba pięter w budynku \\\n",
|
||||
"0 290386 46 2 False 5.0 \n",
|
||||
"1 450000 59 2 False 3.0 \n",
|
||||
"2 375000 79 3 False 16.0 \n",
|
||||
"3 400000 63 3 True 2.0 \n",
|
||||
"4 389285 59 3 False 13.0 \n",
|
||||
"\n",
|
||||
" Piętro Typ zabudowy Materiał budynku Rok budowy \\\n",
|
||||
"0 parter apartamentowiec cegła 2017.0 \n",
|
||||
"1 2 kamienica cegła 1902.0 \n",
|
||||
"2 5 blok płyta 1990.0 \n",
|
||||
"3 2 blok cegła 2009.0 \n",
|
||||
"4 12 blok NaN NaN \n",
|
||||
"\n",
|
||||
" opis \n",
|
||||
"0 Polecam mieszkanie 2 pokojowe o metrażu 46,68 ... \n",
|
||||
"1 Ekskluzywna oferta - tylko u nas! Projekt arch... \n",
|
||||
"2 Polecam do kupna przestronne mieszkanie trzypo... \n",
|
||||
"3 Dla rodziny albo pod wynajem. Świetna lokaliza... \n",
|
||||
"4 NaN \n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Wczytanie danych (mieszkania) przy pomocy biblioteki pandas\n",
|
||||
"\n",
|
||||
"import numpy as np\n",
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"alldata = pd.read_csv(\n",
|
||||
" \"mieszkania4.tsv\",\n",
|
||||
" header=0,\n",
|
||||
" sep=\"\\t\",\n",
|
||||
" usecols=[\n",
|
||||
" \"cena\",\n",
|
||||
" \"Powierzchnia w m2\",\n",
|
||||
" \"Liczba pokoi\",\n",
|
||||
" \"Garaż\",\n",
|
||||
" \"Liczba pięter w budynku\",\n",
|
||||
" \"Piętro\",\n",
|
||||
" \"Typ zabudowy\",\n",
|
||||
" \"Materiał budynku\",\n",
|
||||
" \"Rok budowy\",\n",
|
||||
" \"opis\",\n",
|
||||
" ],\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(alldata[:5])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Jak widać powyżej, w pliku *mieszkania4.tsv* znajdują się dane różnych typów:\n",
|
||||
"* dane numeryczne (po prostu liczby):\n",
|
||||
" * cena\n",
|
||||
" * powierzchnia w m<sup>2</sup>\n",
|
||||
" * liczba pokoi\n",
|
||||
"* dane częściowo numeryczne (liczby oraz wartości specjalne):\n",
|
||||
" * liczba pięter w budynku\n",
|
||||
" * piętro\n",
|
||||
" * rok budowy\n",
|
||||
"* dane boole'owskie (prawda/fałsz):\n",
|
||||
" * garaż\n",
|
||||
"* dane kategoryczne (wybór jednej z kilku kategorii):\n",
|
||||
" * typ zabudowy\n",
|
||||
"* dane tekstowe (dowolny tekst):\n",
|
||||
" * opis"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": {},
|
||||
"source": [
|
||||
"## Dane numeryczne"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[ 46 59 79 63 90 66 32 38 68 43 185 64\n",
|
||||
" 165 71 73 51 70 48 42 33 203 88 41 31\n",
|
||||
" 45 62 60 295 53 84 170 56 47 228 44 67\n",
|
||||
" 49 37 87 36 55 57 118 65 30 28 230 54\n",
|
||||
" 52 95 50 26 171 282 77 40 150 300 39 145\n",
|
||||
" 370 140 225 29 61 135 27 270 177 85 92 132\n",
|
||||
" 75 200 74 219 220 96 235 20 153 318 104 58\n",
|
||||
" 72 117 189 81 111 35 280 141 195 120 250 97\n",
|
||||
" 154 114 76 287 34 180 160 176 148 98 217 86\n",
|
||||
" 260 198 78 183 80 163 82 100 156 320 89 103\n",
|
||||
" 159 125 340 149 175 237 110 182 186 106 233 197\n",
|
||||
" 136 162 157 240 211 83 196 69 102 91 108 130\n",
|
||||
" 510 143 1200 178 226 190 151 138 161 142 683 146\n",
|
||||
" 94 109 263 112 855 376 218 113 215 264 139 129\n",
|
||||
" 167 600 24 174 296 315 232 298 330 93 301 127\n",
|
||||
" 290 275 375 124 252 173 158 25 269 128 192 155\n",
|
||||
" 99 126 147 288 119 206 105 224 346 339 204 1100\n",
|
||||
" 392 243 101 18 202 205 107 199 137 134 144 216\n",
|
||||
" 172 239 116 364 121 23 267 369 11930 122 400 209\n",
|
||||
" 210 268 500 123 245 15 22 335 262 438 307 184\n",
|
||||
" 354 249 431 214 164 328 800 16 229 152 650 241\n",
|
||||
" 187 276 297 443 353 360 350 213 19 265]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(pd.unique(alldata[\"Powierzchnia w m2\"]))\n",
|
||||
"\n",
|
||||
"# (funkcja `pandas.unique` służy do pomijania duplikatów wartości)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['parter' '2' '5' '12' '1' '3' nan '8' '4' '16' '7' '6' 'poddasze' '9'\n",
|
||||
" '11' '13' '14' '10' '15' 'niski parter']\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(pd.unique(alldata[\"Piętro\"]))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": {},
|
||||
"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*?"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Przed zamianą:\n",
|
||||
"122 1\n",
|
||||
"123 2\n",
|
||||
"124 poddasze\n",
|
||||
"125 5\n",
|
||||
"126 parter\n",
|
||||
"127 3\n",
|
||||
"Name: Piętro, dtype: object\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(\"Przed zamianą:\")\n",
|
||||
"print(alldata[\"Piętro\"][122:128])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"Po zamianie:\n",
|
||||
"122 1.0\n",
|
||||
"123 2.0\n",
|
||||
"124 NaN\n",
|
||||
"125 5.0\n",
|
||||
"126 0.0\n",
|
||||
"127 3.0\n",
|
||||
"Name: Piętro, dtype: float64\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Zamiana wartości 'parter' i 'niski parter' w kolumnie 'Piętro' na 0.\n",
|
||||
"alldata[\"Piętro\"] = alldata[\"Piętro\"].apply(\n",
|
||||
" lambda x: 0 if x in [\"parter\", \"niski parter\"] else x\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Zamiana wszystkich wartości w kolumnie 'Piętro' na numeryczne.\n",
|
||||
"# Parametr errors='coerce' powoduje, że napotkane nieliczbowe wartości będą zamieniane na NaN.\n",
|
||||
"alldata[\"Piętro\"] = alldata[\"Piętro\"].apply(pd.to_numeric, errors=\"coerce\")\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"Po zamianie:\")\n",
|
||||
"print(alldata[\"Piętro\"][122:128])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Wartości NaN"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"nan\n",
|
||||
"nan\n",
|
||||
"nan\n",
|
||||
"nan\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/tmp/ipykernel_11063/3804580172.py:1: RuntimeWarning: invalid value encountered in sqrt\n",
|
||||
" print(np.sqrt(-1)) # niezdefiniowany wynik działania (pierwiastek z liczby ujemnej)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(np.sqrt(-1)) # niezdefiniowany wynik działania (pierwiastek z liczby ujemnej)\n",
|
||||
"\n",
|
||||
"print(alldata[\"Piętro\"][14]) # brak danych na temat piętra w rekordzie 14.\n",
|
||||
"\n",
|
||||
"# Jak uzyskać wartość NaN?\n",
|
||||
"print(float(\"NaN\"))\n",
|
||||
"print(np.nan)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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",
|
||||
"* **Najbezpieczniej jest usunąć cały rekord (wiersz), który zawiera jakąkolwiek wartość NaN**. Należy przy tym pamiętać, że pozbywamy się w ten sposób (być może wartościowych) danych. Jest to istotne zwłaszcza wtedy, gdy nasze dane zawierają dużo wartości niezdefiniowanych.\n",
|
||||
"* Wartość NaN można też zamienić na średnią, medianę, modę itp. z pozostałych wartości w zbiorze danych. To dobra opcja, jeżeli usunięcie całych wierszy zawierających NaN pozbawiłoby nas zbyt wielu rekordów.\n",
|
||||
"* Można użyć też bardziej zaawansowanych technik, np. [MICE](https://stats.stackexchange.com/questions/421545/multiple-imputation-by-chained-equations-mice-explained) czy KNN."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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",
|
||||
"* [What’s the best way to handle NaN values?](https://towardsdatascience.com/whats-the-best-way-to-handle-nan-values-62d50f738fc)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Liczba rekordów przed usunięciem NaN: 4938\n",
|
||||
"Liczba rekordów po usunięciu NaN: 888\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(\"Liczba rekordów przed usunięciem NaN:\", len(alldata))\n",
|
||||
"\n",
|
||||
"alldata = alldata.dropna() # usunięcie rekordów zawierających NaN\n",
|
||||
"\n",
|
||||
"print(\"Liczba rekordów po usunięciu NaN:\", len(alldata))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Dane boole'owskie"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"W przypadku danych typu prawda/fałsz, wystarczy zamienić wartości `True` na `1`, a `False` na `0`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Przed zamianą:\n",
|
||||
"0 False\n",
|
||||
"1 False\n",
|
||||
"2 False\n",
|
||||
"3 True\n",
|
||||
"13 False\n",
|
||||
" ... \n",
|
||||
"4909 False\n",
|
||||
"4917 True\n",
|
||||
"4918 False\n",
|
||||
"4920 False\n",
|
||||
"4937 False\n",
|
||||
"Name: Garaż, Length: 888, dtype: bool\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(\"Przed zamianą:\")\n",
|
||||
"print(alldata[\"Garaż\"])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"Po zamianie:\n",
|
||||
"0 0\n",
|
||||
"1 0\n",
|
||||
"2 0\n",
|
||||
"3 1\n",
|
||||
"13 0\n",
|
||||
" ..\n",
|
||||
"4909 0\n",
|
||||
"4917 1\n",
|
||||
"4918 0\n",
|
||||
"4920 0\n",
|
||||
"4937 0\n",
|
||||
"Name: Garaż, Length: 888, dtype: int64\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"alldata[\"Garaż\"] = alldata[\"Garaż\"].apply(lambda x: 1 if x == True else 0)\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"Po zamianie:\")\n",
|
||||
"print(alldata[\"Garaż\"])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Dane kategoryczne"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"O danych kategorycznych mówimy, jeżeli dane mogą przyjmować wartości ze skończonej listy („kategorii”), np.:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['apartamentowiec', 'kamienica', 'blok', 'dom wielorodzinny/szeregowiec', 'plomba']\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# \"Typ zabudowy\" może przyjmować jedną z następujących wartości:\n",
|
||||
"\n",
|
||||
"typ_zabudowy_values = list(pd.unique(alldata[\"Typ zabudowy\"]))\n",
|
||||
"\n",
|
||||
"print(typ_zabudowy_values)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['cegła', 'płyta', 'inne', 'pustak', 'silikat', 'beton']\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# \"Materiał budynku\" może przyjmować jedną z następujących wartości:\n",
|
||||
"\n",
|
||||
"material_budynku_values = list(pd.unique(alldata[\"Materiał budynku\"]))\n",
|
||||
"\n",
|
||||
"print(material_budynku_values)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Cechę kategoryczną można rozbić na skończoną liczbę cech boole'owskich:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Skopiujmy dane, żeby przedstawić 2 alternatywne rozwiązania\n",
|
||||
"\n",
|
||||
"alldata_1 = alldata.copy()\n",
|
||||
"alldata_2 = alldata.copy()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Nowo utworzone kolumny (cechy boole'owskie):\n",
|
||||
"['Czy apartamentowiec?', 'Czy kamienica?', 'Czy blok?', 'Czy dom wielorodzinny/szeregowiec?', 'Czy plomba?']\n",
|
||||
"\n",
|
||||
" Typ zabudowy Czy apartamentowiec? Czy kamienica? \\\n",
|
||||
"0 apartamentowiec True False \n",
|
||||
"1 kamienica False True \n",
|
||||
"2 blok False False \n",
|
||||
"3 blok False False \n",
|
||||
"13 blok False False \n",
|
||||
"... ... ... ... \n",
|
||||
"4909 apartamentowiec True False \n",
|
||||
"4917 dom wielorodzinny/szeregowiec False False \n",
|
||||
"4918 blok False False \n",
|
||||
"4920 dom wielorodzinny/szeregowiec False False \n",
|
||||
"4937 dom wielorodzinny/szeregowiec False False \n",
|
||||
"\n",
|
||||
" Czy blok? Czy dom wielorodzinny/szeregowiec? Czy plomba? \n",
|
||||
"0 False False False \n",
|
||||
"1 False False False \n",
|
||||
"2 True False False \n",
|
||||
"3 True False False \n",
|
||||
"13 True False False \n",
|
||||
"... ... ... ... \n",
|
||||
"4909 False False False \n",
|
||||
"4917 False True False \n",
|
||||
"4918 True False False \n",
|
||||
"4920 False True False \n",
|
||||
"4937 False True False \n",
|
||||
"\n",
|
||||
"[888 rows x 6 columns]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Rozwiązanie 1\n",
|
||||
"\n",
|
||||
"select_column_names = []\n",
|
||||
"for typ_zabudowy in typ_zabudowy_values:\n",
|
||||
" new_column_name = \"Czy {}?\".format(typ_zabudowy)\n",
|
||||
" alldata_1[new_column_name] = alldata_1[\"Typ zabudowy\"] == typ_zabudowy\n",
|
||||
" select_column_names.append(new_column_name)\n",
|
||||
"\n",
|
||||
"print(\"Nowo utworzone kolumny (cechy boole'owskie):\")\n",
|
||||
"print(select_column_names)\n",
|
||||
"\n",
|
||||
"select_column_names = [\"Typ zabudowy\"] + select_column_names\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(alldata_1[select_column_names])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "NameError",
|
||||
"evalue": "name 'pandas' is not defined",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[0;32mIn [14], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m alldata_2 \u001b[39m=\u001b[39m pandas\u001b[39m.\u001b[39mget_dummies(alldata_2, columns\u001b[39m=\u001b[39m[\u001b[39m\"\u001b[39m\u001b[39mTyp zabudowy\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mMateriał budynku\u001b[39m\u001b[39m\"\u001b[39m])\n\u001b[1;32m 3\u001b[0m \u001b[39mprint\u001b[39m(alldata_2)\n",
|
||||
"\u001b[0;31mNameError\u001b[0m: name 'pandas' is not defined"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"alldata_2 = pd.get_dummies(alldata_2, columns=[\"Typ zabudowy\", \"Materiał budynku\"])\n",
|
||||
"\n",
|
||||
"print(alldata_2)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": {},
|
||||
"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",
|
||||
"Więcej na ten temat można przeczytać w artykule [How to use pandas.get_dummies with the test set](http://fastml.com/how-to-use-pd-dot-get-dummies-with-the-test-set)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Do preprocessingu danych kategorycznych można też użyć narzędzi z biblioteki *scikit-learn*: https://scikit-learn.org/stable/modules/preprocessing.html#encoding-categorical-features"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Dane tekstowe"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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": {},
|
||||
"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:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" nowe_w_opisie opis\n",
|
||||
"0 True Polecam mieszkanie 2 pokojowe o metrażu 46,68 ...\n",
|
||||
"1 False Ekskluzywna oferta - tylko u nas! Projekt arch...\n",
|
||||
"2 False Polecam do kupna przestronne mieszkanie trzypo...\n",
|
||||
"3 False Dla rodziny albo pod wynajem. Świetna lokaliza...\n",
|
||||
"13 False Witam,Mam na imię Jędrzej i w biurze Platan po...\n",
|
||||
"... ... ...\n",
|
||||
"4909 True !!! Apartamenty w Lusówku oddawane w stanie de...\n",
|
||||
"4917 False Sprzedam lokal mieszkalny odrębna własność w b...\n",
|
||||
"4918 False Polecam do kupna mieszkanie 5 pokojowe o pow. ...\n",
|
||||
"4920 True Przestronne mieszkanie z pięknym widokiem!Dwup...\n",
|
||||
"4937 True Sprzedaż nowego mieszkania w FAŁKOWIE - Osiedl...\n",
|
||||
"\n",
|
||||
"[888 rows x 2 columns]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"alldata[\"nowe_w_opisie\"] = alldata[\"opis\"].apply(\n",
|
||||
" lambda x: True if \"nowe\" in x.lower() else False\n",
|
||||
")\n",
|
||||
"print(alldata[[\"nowe_w_opisie\", \"opis\"]])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Można też zamienić tekst na wektory używając algorytmów TF–IDF, Word2Vec lub podobnych."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Zadanie 7\n",
|
||||
"\n",
|
||||
"Na podstawie danych z pliku *flats.tsv* wytrenuj model, który przewidzi cenę mieszkania na podstawie różnych jego cech. Wykorzystaj cechy różnych typów (numeryczne, boole'owskie, kategoryczne, tekstowe). Dokonaj odpowiedniego preprocessingu danych.\n",
|
||||
"\n",
|
||||
"Zastanów się, jak poprawić wyniki uzyskane przez klasyfikator. Może przez stworzenie nowych cech pochodnych? Może przez odrzucenie mało wiarygodnych danych (obserwacji odstających)? Porównaj uzyskane wyniki z wynikami uzyskanymi w pierwszej części zadania."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"celltoolbar": "Slideshow",
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.10.6 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.6"
|
||||
},
|
||||
"livereveal": {
|
||||
"start_slideshow_at": "selected",
|
||||
"theme": "amu"
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
4939
lab/mieszkania4.tsv
Normal file
4939
lab/mieszkania4.tsv
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user