Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:ml:lab1 [2018/02/28 22:05] esimon [Laboratorium 1 - Wprowadzenie do Jupyter i Google Colab] |
pl:dydaktyka:ml:lab1 [2019/06/27 15:50] (aktualna) |
====== Laboratorium 1 - Wprowadzenie do Jupyter i Google Colab ====== | |
=====Informacje ogólne===== | |
- Pracujemy w środowisku [[https://colab.research.google.com/notebooks|Google Colab]] | |
- Jeśli ktoś woli pracować lokalnie, możliwe jest uruchomienie na komputerach z laboratorium lokalnej wersji Jupyter Notebook: <code bash>jupyter notebook</code> | |
- Jeśli ktoś woli pracować na swoim komputerze, najlepiej zainstalować [[https://www.anaconda.com/download/|Anaconda 3.6]] | |
| |
| |
===== Instrukcje do laboratorium ===== | |
- Notebook do pobrania: [[|Introduction.ipnb]] | |
- W celu załadowania, wybierz 'File->Upload Notebook' w Google Colab. W przypadku lokalnej wersji, po prostu nawiguj w oknie przeglądarki do miejsca gdzie zapisany jest notebook. | |
| |
===== Materiały ===== | ====== Laboratorium 1 - Wprowadzenie do GNU Octave ====== |
* Trochę wiedzy (ćwiczenia z rozwiązaniami dotyczących numpy): [[https://www.machinelearningplus.com/101-numpy-exercises-python/|numpy]] | Środowisko Octave jest wolnym odpowiednikiem pakietu MATLAB. |
* Trochę wiedzy (ćwiczenia z rozwiązaniami dotyczące pandas): [[https://github.com/guipsamora/pandas_exercises|pandas]] | |
* {{ :pl:dydaktyka:ml:kc_house_data.csv.zip |}} | [[http://www.gnu.org/software/octave/doc/interpreter/index.html|Dokumentacja]] |
* {{ :pl:dydaktyka:ml:crimes.csv.zip |}} | ===== Instalacja i uruchamianie ===== |
| |
| W przypadku większości systemów Linux, pakiet Octave można zainstalować bezpośrednio z repozytorium: <code>$ sudo apt-get install octave</code> |
| |
| W przypadku systemu Windows i OS X, oprogramowanie Octave można ściągnąć ze strony projektu: [[http://www.gnu.org/software/octave/download.html|GNU Octave]]. |
| |
| W systemie Linux uruchamiamy środowisko za pomocą polecenia <code>$ octave</code> W konsoli Octave możemy wykonywać wszystkie podstawowe polecenia umożliwiające nawigację w systemie plików (cd, ls, etc). |
| |
| ===== Składnia ===== |
| ==== Typy i zmienne ==== |
| |
| W języku Octave, nie prototypujemy zmiennych. Typy określane są automatycznie, tak jak w PHP, czy Bashu. |
| <code octave>zmienna = 'moja zmienna'; |
| zmienna = 12.34; |
| zmienna = [2 3 4; 3 4 5];</code> |
| |
| Jednym z podstawowych //typów// danych w Octave są wektory i macierze. |
| Definiujemy je za pomocą nawiasów kwadratowych. |
| Wartości w **wierszach** oddzielamy spacjami lub przecinkami. |
| Wiersze oddzielamy znakiem średnika. |
| |
| Załóżmy że chcemy zdefiniować następującą macierz i przypisać ją do zmiennej M: |
| $$M = \begin{bmatrix} |
| 5 & 6 & 0 \\ |
| 6 & 0 & 1 \\ |
| 0 & 6 & 1 |
| \end{bmatrix}$$ |
| |
| W Octave zapiszemy ją jako:<code octave>M = [5 6 0; 6 0 1; 0 6 1] </code> |
| |
| Aby odwołać się do danego elementu macierzy, lub wektora używamy nawiasów okrągłych.\\ |
| **Uwaga :!:** W Octave indeksowanie rozpoczyna się od 1 a nie jak w popularnych językach programowania od 0! Np. Aby pobrać/przypisać wartość elementu z pierwszego wiersza i drugiej kolumny macierzy M, piszemy: |
| <code octave>M(1,2)=7 </code> |
| |
| Jako wynik otrzymujemy: |
| $$M = \begin{bmatrix} |
| 5 & 7 & 0 \\ |
| 6 & 0 & 1 \\ |
| 0 & 6 & 1 |
| \end{bmatrix}$$ |
| |
| Octave umozliwia równiez odwoływanie się do całych kolumn i wierszy w danej macierzy: |
| <code octave> |
| M(:,3) % zwróci [0;1;1] |
| M(2,:) % zwróci [6 0 1] |
| </code> |
| |
| |
| Sprawdź co jak zadziała poniższy kod: |
| <code octave> |
| M = [5 6 0; 6 0 1; 0 6 1]; |
| M([2 3],[1 2]) |
| </code> |
| |
| ==== Zakresy ==== |
| Zakresy tworzy się za pomocą znaku dwukropka. Służą one do definiowania prostych zestawów danych, a także do odwoływania się do danych w wektorach i macierzach. |
| |
| Przetestuj działanie poniższych poleceń |
| <code octave>zeros(1,10) |
| zeros(2,10) |
| ones(1,10) |
| range = [1:10] |
| range = [1:0.3:10] |
| range(5:10) |
| </code> |
| |
| |
| |
| |
| ==== Operatory arytmetyczne==== |
| Octave udostępnia podstawowe operatory arytmetyczne zarówno dla macierzy jak i skalarów. Pełny zbiór operatorów dostępny jest w [[http://www.gnu.org/software/octave/doc/interpreter/Arithmetic-Ops.html#Arithmetic-Ops|dokumentacji Octave]]. |
| |
| **Uwaga :!:** Zwróć uwagę na działanie operatorów połączonych z kropką! \\ |
| Przetestuj działanie poniższego kodu. |
| <code octave> |
| A = [0.5 0.5; 1 1]; |
| B = [2 2; 2 2]; |
| |
| A * B |
| A .* B |
| B ^ 2 |
| B .^ D |
| </code> |
| |
| |
| ==== Instrukcje sterujące ==== |
| |
| Octave udostępnia powszechnie znane z innych języków programowania instrukcje sterujące. Pełny opis instrukcji sterujących można znaleźć w [[http://www.gnu.org/software/octave/doc/interpreter/Statements.html#Statements|dokumentacji Octave]] |
| |
| |
| ==== Definiowanie funkcji ==== |
| Szczegółowe dane na temat definiowania funkcji można znaleźć w [[http://www.gnu.org/software/octave/doc/interpreter/Functions-and-Scripts.html#Functions-and-Scripts|dokumentacji Octave]]. Poniżej kilka podstawowych infromacji: |
| * Funkcje najczęściej definiujemy w osobnych plikach z rozszerzeniem **.m** |
| * Nazwa funkcji musi zgadzać się z nazwą pliku! |
| * Wywoływanie funkcji odbywa się poprzez podanie jej nazwy i listy argumentów. |
| * Podczas wywoływania funkcji musimy znajdować się w katalogu w którym dana funkcja jest zapisana. |
| * W Octave nie zwracamy wartości za pomocą **return**. Po prostu przypisujemy ją do zmiennej podanej jako element zwracany |
| * Komentarze w kodzie wstawiamy za pomocą % |
| |
| Przykładowa definicja funkcji: |
| <file octave srednia.m> |
| function W = srednia(dane) |
| % funkcja obliczająca średnią elementów w wektorze |
| W = sum(dane)/length(dane); |
| end |
| </file> |
| |
| Aby wywołać funkcje z przykładu powyżej wykonujemy polecenie: |
| <code octave>Wynik = srednia([2 3 4 5 6 7 8]); </code> |
| |
| Jeśli funkcja ma zwracać więcej niż jeden argument, zapisujemy to w ten sposób: |
| <file octave myFind.m> |
| function [IndexX,IndexY] = myFind(M,V) |
| % Funkcja poszukująca wartości V w macierzy M |
| % Funkcja zwraca indeksy znalezionej wartości, lub -1,-1 |
| [rows,cols] = size(M); |
| IndexX = IndexY =-1; |
| for i=1:rows, |
| for j=1:cols |
| if M(i,j) == V |
| IndexX = i; |
| IndexY = j; |
| return; |
| endif |
| end |
| end |
| end |
| </file> |
| |
| Aby pobrać wartości zwracane przez funkcję powyżej wpisujemy np.: |
| <code octave> |
| [X,Y] = myFind(M,6); |
| </code> |
| |
| ==== Rysowanie wykresów ==== |
| Do rysowania wykresów używamy funkcji: |
| * plot - rysowanie wykresów 2D |
| * plot3d - rysowanie wykresów 3D |
| * mesh - rysowanie płaszczyzn |
| |
| Porównaj działanie funkcji na poniższych przykładach. Jaka jest różnica pomiędzy plot3 a mesh? |
| |
| **Plot2** |
| <code octave> |
| x = [0:0.01:10]; |
| y = sin(x); |
| plot(x,y); |
| </code> |
| |
| **Plot3** |
| <code octave> |
| t = 0:0.1:10*pi; |
| r = linspace (0, 1, numel (t)); |
| z = linspace (0, 1, numel (t)); |
| plot3 (r.*sin(t), r.*cos(t), z); |
| </code> |
| |
| **Mesh** |
| <code octave> |
| tx = ty = linspace (-8, 8, 41)'; |
| [xx, yy] = meshgrid (tx, ty); |
| r = sqrt (xx .^ 2 + yy .^ 2) + eps; |
| tz = sin (r) ./ r; |
| mesh (tx, ty, tz); |
| </code> |
| |
| |
| ===== Dobre praktyki ===== |
| * Jeśli tylko jest to możliwe, używaj funkcji wbudowanych. Na przykład zamiast pisać swoją własną funkcję **srednia** lepiej było wykorzystać wbudowaną funkcję **mean**. |
| * Jeśli to tylko możliwe, staraj się wykorzystywać operacje na macierzach, zamiast pętli. |
| * Zawsze definiuj wcześniej wektor/macierz z która pracujesz (chyba że jest ona bezpośrednim wynikiem jakichś operacji). Np.:<code octave>M = zeros(3,3); |
| [x,y] = size(M); |
| for i=1:x |
| for j=1:y |
| M(i,j) = rand; |
| end |
| end</code> |
| |
| ===== Ćwiczenia ===== |
| ==== Operacje podstawowe I==== |
| Zakładając, że mamy następującą macierz |
| $$A = \begin{bmatrix} |
| 16 & 2 & 3 & 13 \\ |
| 5 & 11& 10 & 8 \\ |
| 9 & 7 & 6 & 12 \\ |
| 4 & 14 & 15 & 1 |
| \end{bmatrix}$$ |
| |
| Jakie indeksowanie macierzy A pozwoli na wyciągnięcie z niej następującej macierzy: |
| $$B = \begin{bmatrix} |
| 16 & 2 \\ |
| 5 & 11 \\ |
| 9 & 7 \\ |
| 4 & 14 |
| \end{bmatrix}$$ |
| |
| |
| ==== Operacje podstawowe II==== |
| Napisz funkcję znajdującą najmniejszy i największy element w macierzy i zwracającą te wartości. |
| |
| **Podpowiedź** użyj zbudowanych funkcji //min// i //max//. |
| ==== Wartość wektora ==== |
| Napisz funkcje wyznaczającą długość (normę) wektora podanego jako parametr, która określona jest wzorem: |
| $$|A| = \sqrt{\sum\limits_{i=1}^n a_i^2} $$ |
| ==== Odchylenie standardowe I==== |
| Napisz funkcję wyznaczającą [[http://pl.wikipedia.org/wiki/Odchylenie_standardowe|odchylenie standardowe]] dla wartości wektora podanego jako parametr. Odchylenie standardowe dane jest wzorem: |
| $$\sigma = \sqrt{\frac{\sum\limits_{i=1}^{N} |
| \left(x_{i} - \mu)^{2}} |
| {N-1}}$$ |
| |
| Gdzie $\mu$ to średnia, a N to liczba wszystkich elementów w probie. |
| |
| ==== Odchylenie standardowe II==== |
| Przyjmij, że tym razem parametrem funkcji nie jest wektor, ale macierz. Funkcja powinna obliczyć odchylenia standardowe dla każdego wiersza macierzy osobno i zwrócić wektor odchylen standardowych. |
| |
| **Uwaga** Pamiętaj o zadaniu [[#Operacje_podstawowe_i|Operacje Podstawowe I i II]]! |
| ==== Wydajność I==== |
| Dla funkcji napisanych w poprzednich dwóch zadaniach ([[#dlugosc_wektora|Długość wektora]] oraz [[#odchylenie_standardowe_i|Odchylenie Standardowe I]]) dopisz ich odpowiedniki wektorowe (lub z użyciem pętli) i przetestuj ich działanie na wygenerowanym losowo zbiorze $10^6$ liczb. |
| |
| Aby wygenerować dane użyj:<code octave> data = rand(1,10^6); </code> |
| |
| Porównaj czasy wykonywania funkcji: |
| <code octave> |
| timestart = time(); |
| |
| %Wywolanie funkcji |
| |
| timestop = time(); |
| |
| printf('Czas wykonania to %d sekund.\n',(timestop-timestart)); |
| </code> |
| |
| Jak zmienią się czasy gdy zmienimy ilość danych z $10^6$ na $10^8$? |
| O ile wolniej (procentowo) wykonuje się algorytm wyznaczający odchylenie standardowe wykorzystujący wbudowaną funkcję obliczającą średnią od tego, który wykorzystuje funkcję //srednia// napisaną przez nas? |
| |
| ==== Wydajność II ==== |
| Jak poprawic wydajnośc następujących fragmentów kodu: |
| |
| **Przykład I** |
| <code octave>A = zeros(10,10) |
| v = zeros(10, 1); |
| x = zeros(10, 1); |
| for i = 1:10 |
| for j = 1:10 |
| x(i) = v(i) + A(i, j) * v(j); |
| end |
| end |
| </code> |
| |
| **Przykład II** |
| <code octave> |
| for i = 1:7 |
| for j = 1:7 |
| A(i, j) = log (X(i, j)); |
| B(i, j) = X(i, j) ^ 2; |
| C(i, j) = X(i, j) + 1; |
| D(i, j) = X(i, j) / 4; |
| end |
| end |
| </code> |
| ==== Rysowanie wykresu funkcji ==== |
| |
| Napisz funkcję która będzie wyznaczała wartości funkcji z obrazka poniżej. Wyrysuj wartości tej funkcji na wykresie w przedziale od -10 do 10 z krokiem 0.5. |
| |
| {{:pl:dydaktyka:ml:absfun.png|Wartość bezwzględna}} |
| |
| |