Compare commits

..

No commits in common. "master" and "sacred-mongo" have entirely different histories.

15 changed files with 1616 additions and 12188 deletions

View File

@ -1,13 +0,0 @@
name: github-actions-hello
on: [push]
jobs:
hello-job:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2.2.2
with:
python-version: '3.7'
- run: python3 --version

View File

@ -180,7 +180,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.16" "version": "3.9.12"
}, },
"slideshow": { "slideshow": {
"slide_type": "slide" "slide_type": "slide"

View File

@ -509,7 +509,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.16" "version": "3.9.12"
}, },
"slideshow": { "slideshow": {
"slide_type": "slide" "slide_type": "slide"

View File

@ -248,7 +248,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.16" "version": "3.9.12"
}, },
"slideshow": { "slideshow": {
"slide_type": "slide" "slide_type": "slide"

View File

@ -981,25 +981,13 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "slide" "slide_type": "slide"
} }
}, },
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"total 16\r\n",
"-rw-r--r-- 1 tomek tomek 77 May 28 2022 config.json\r\n",
"-rw-r--r-- 1 tomek tomek 159 May 28 2022 cout.txt\r\n",
"-rw-r--r-- 1 tomek tomek 2 May 28 2022 metrics.json\r\n",
"-rw-r--r-- 1 tomek tomek 1659 May 28 2022 run.json\r\n"
]
}
],
"source": [ "source": [
"!ls -l my_runs/1" "!ls -l my_runs/1"
] ]
@ -1567,7 +1555,7 @@
} }
}, },
"source": [ "source": [
"## Zadanie [15 pkt] (do 2023-06-?)\n", "## Zadanie [15 pkt] (do 2023-05-12)\n",
"1. \"Owiń\" wywołanie swojego eksperymentu za pomocą Sacred, w ten sposób, żeby zapisane zostały [10pkt]:\n", "1. \"Owiń\" wywołanie swojego eksperymentu za pomocą Sacred, w ten sposób, żeby zapisane zostały [10pkt]:\n",
" - parametry, z którymi wywołany był trening\n", " - parametry, z którymi wywołany był trening\n",
" - powstały plik z modelem (jako artefakt)\n", " - powstały plik z modelem (jako artefakt)\n",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n", "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n", "<div class=\"alert alert-block alert-info\">\n",
"<h1> Inżynieria uczenia maszynowego </h1>\n", "<h1> Inżynieria uczenia maszynowego </h1>\n",
"<h2> 11. <i>Github actions</i> [laboratoria]</h2> \n", "<h2> 11. <i>Github actions i CML</i> [laboratoria]</h2> \n",
"<h3> Tomasz Ziętkiewicz (2023)</h3>\n", "<h3> Tomasz Ziętkiewicz (2022)</h3>\n",
"</div>\n", "</div>\n",
"\n", "\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)" "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
@ -70,8 +70,8 @@
"source": [ "source": [
"### Terminologia Github Actions\n", "### Terminologia Github Actions\n",
" - *Workflow* - workflow odpowiada \"Pipeline\" z Jenkinsa.\n", " - *Workflow* - workflow odpowiada \"Pipeline\" z Jenkinsa.\n",
" - *Event* - zdarzenie, które odapala (\"triggers\") \"Workflow\". Np. wypchnięcie zmiany do repozytorium (\"push\"), utworzenie Pull requesta. [Pełna lista](https://docs.github.com/en/actions/reference/events-that-trigger-workflows)\n", " - *Event* - zdażenie, które odapala (\"triggers\") uruchomienie \"Workflow\". Np. wypchnięcie zmiany do repozytorium (\"push\"), utworzenie Pull requesta. [Pełna lista](https://docs.github.com/en/actions/reference/events-that-trigger-workflows)\n",
" - *Job* - workflow składa się z jednego lub kilku zadań (\"jobs\"). Każde z nich może być wykonywane równolegle na innej maszynie (patrz \"runner\")\n", " - *Job* - workflow składa się z jednego lub kilku \"jobs\". Każdy z nich może być wykonywany równolegle na innej maszynie (patrz \"runner\")\n",
" - *Step* - odpowiednik \"Stage\" z Jenkinsa - służu do grupowania \"Actions\"\n", " - *Step* - odpowiednik \"Stage\" z Jenkinsa - służu do grupowania \"Actions\"\n",
" - *Action/command* - odpowiednik \"Step\" z Jenkinsa - pojedyncze polecenie do wykonania, np. dodanie komentarze do Pull requesta, wykonanie polecenia systemowego itp.\n", " - *Action/command* - odpowiednik \"Step\" z Jenkinsa - pojedyncze polecenie do wykonania, np. dodanie komentarze do Pull requesta, wykonanie polecenia systemowego itp.\n",
" - *Runner* - odpowiednik Jenkinsowego \"Agent\" - serwer, na którym mogą być wykonywane zadania (\"jobs\")\n", " - *Runner* - odpowiednik Jenkinsowego \"Agent\" - serwer, na którym mogą być wykonywane zadania (\"jobs\")\n",
@ -103,7 +103,33 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 1,
"id": "955585a9",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/home/tomek/AITech/repo/aitech-ium-private/IUM_11\n",
"Initialized empty Git repository in /home/tomek/AITech/repo/aitech-ium-private/IUM_11/github-actions-hello/.git/\r\n"
]
}
],
"source": [
"%cd IUM_11\n",
"!mkdir github-actions-hello;\\\n",
"cd github-actions-hello;\\\n",
"git init"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f4916c1f", "id": "f4916c1f",
"metadata": { "metadata": {
"slideshow": { "slideshow": {
@ -115,53 +141,18 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"/home/tomek/repos/aitech-ium/IUM_11/github-actions-hello\n" "/home/tomek/AITech/repo/aitech-ium-private/IUM_11/github-actions-hello\n"
] ]
} }
], ],
"source": [ "source": [
"!mkdir -p IUM_11/github-actions-hello\n", "%cd github-actions-hello\n",
"%cd IUM_11/github-actions-hello\n",
"!mkdir -p .github/workflows" "!mkdir -p .github/workflows"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 6,
"id": "88ce689f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Reinitialized existing Git repository in /home/tomek/repos/aitech-ium/IUM_11/github-actions-hello/.git/\n",
"Enumerating objects: 6, done.\n",
"Counting objects: 100% (6/6), done.\n",
"Delta compression using up to 4 threads\n",
"Compressing objects: 100% (4/4), done.\n",
"Writing objects: 100% (6/6), 780 bytes | 780.00 KiB/s, done.\n",
"Total 6 (delta 0), reused 0 (delta 0), pack-reused 0\n",
"To github.com:TomekZet/ium-ga-hello.git\n",
" * [new branch] main -> main\n",
"Branch 'main' set up to track remote branch 'main' from 'origin'.\n"
]
}
],
"source": [
"!git init\n",
"!git branch -M main\n",
"!git remote add origin git@github.com:TomekZet/ium-ga-hello.git\n",
"!git push -u origin main"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "dde8d432", "id": "dde8d432",
"metadata": { "metadata": {
"slideshow": { "slideshow": {
@ -173,7 +164,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Overwriting .github/workflows/workflow.yml\n" "Writing .github/workflows/workflow.yml\n"
] ]
} }
], ],
@ -194,164 +185,6 @@
" - run: python3 --version" " - run: python3 --version"
] ]
}, },
{
"cell_type": "code",
"execution_count": 22,
"id": "ff1e011e",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"On branch main\n",
"Your branch is up to date with 'origin/main'.\n",
"\n",
"nothing to commit, working tree clean\n",
"Everything up-to-date\n"
]
}
],
"source": [
"!git add .github/workflows/workflow.yml\n",
"!git commit -m \"Github Actions Workflow\"\n",
"!git push"
]
},
{
"cell_type": "markdown",
"id": "3e237076",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Zakładka actions na stronie repozytorium:\n",
"https://github.com/TomekZet/ium-ga-hello/actions"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "32701383",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"total 16\r\n",
"drwxr-sr-x 2 tomek tomek 4096 May 17 11:51 .\r\n",
"drwxr-sr-x 3 tomek tomek 4096 May 17 11:51 ..\r\n",
"-rw-r--r-- 1 tomek tomek 456 May 17 11:51 parametrized.yml\r\n",
"-rw-r--r-- 1 tomek tomek 305 May 17 12:01 workflow.yml\r\n"
]
}
],
"source": [
"!ls -al .github/workflows"
]
},
{
"cell_type": "markdown",
"id": "1c01acb5",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Ręczne wywoływanie\n",
"Workflow można również wywołać ręcznie, podając parametry.\n",
"Więcej informacji np. tutaj: https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "a7250bf7",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting .github/workflows/parametrized.yml\n"
]
}
],
"source": [
"%%writefile .github/workflows/parametrized.yml\n",
"name: github-actions-hello-parametrized\n",
"on: \n",
" workflow_dispatch:\n",
" inputs:\n",
" input_text:\n",
" description: 'Text to display' \n",
" required: true\n",
" default: 'Hello World'\n",
"jobs:\n",
" hello-job:\n",
" runs-on: ubuntu-latest\n",
" steps:\n",
" - name: Checkout repo\n",
" uses: actions/checkout@v2\n",
" - name: Install dependencies\n",
" run:\n",
" sudo apt update;\n",
" sudo apt install -y figlet\n",
" - name: Write\n",
" run:\n",
" figlet \"${{ github.event.inputs.input_text }}\""
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "36ddaac0",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[main a98938d] just dispatch\n",
" 1 file changed, 6 deletions(-)\n",
"Enumerating objects: 9, done.\n",
"Counting objects: 100% (9/9), done.\n",
"Delta compression using up to 4 threads\n",
"Compressing objects: 100% (3/3), done.\n",
"Writing objects: 100% (5/5), 411 bytes | 411.00 KiB/s, done.\n",
"Total 5 (delta 1), reused 0 (delta 0), pack-reused 0\n",
"remote: Resolving deltas: 100% (1/1), completed with 1 local object.\u001b[K\n",
"To github.com:TomekZet/ium-ga-hello.git\n",
" 6c4a361..a98938d main -> main\n"
]
}
],
"source": [
"!git add -u .github/workflows\n",
"!git commit -m \"just dispatch\"\n",
"!git push"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ed780dea", "id": "ed780dea",
@ -386,339 +219,6 @@
" - z [Github Marketplace](https://github.com/marketplace?type=actions)" " - z [Github Marketplace](https://github.com/marketplace?type=actions)"
] ]
}, },
{
"cell_type": "markdown",
"id": "a764cc0d",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Akcje wykonywane w kontenerze Docker\n",
"Akcja może być wywołana w kontenerze Docker (pobranym z Docker hub albo zbudowanym z Dockerfile)\n",
"W tym celu należy stworzyć własną akcję w pliku action.yaml i potem użyć jej w Workflow"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "ff4dab8c",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting action.yml\n"
]
}
],
"source": [
"%%writefile action.yml\n",
"name: 'Hello World'\n",
"description: 'Greet someone and record the time'\n",
"inputs:\n",
" who-to-greet: # id of input\n",
" description: 'Who to greet'\n",
" required: true\n",
" default: 'World'\n",
"outputs:\n",
" time: # id of output\n",
" description: 'The time we greeted you'\n",
"runs:\n",
" using: 'docker'\n",
" image: 'Dockerfile'\n",
" args:\n",
" - ${{ inputs.who-to-greet }}"
]
},
{
"cell_type": "code",
"execution_count": 80,
"id": "f1aaff7c",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting Dockerfile\n"
]
}
],
"source": [
"%%writefile Dockerfile\n",
"# Container image that runs your code\n",
"FROM ubuntu:latest\n",
" \n",
"RUN apt update && apt install -y figlet\n",
"\n",
"# Copies your code file from your action repository to the filesystem path `/` of the container\n",
"COPY entrypoint.sh /entrypoint.sh\n",
"\n",
"VOLUME /github/workspace/\n",
"\n",
"WORKDIR /github/workspace/\n",
"\n",
"# Code file to execute when the docker container starts up (`entrypoint.sh`)\n",
"ENTRYPOINT [\"/entrypoint.sh\"]"
]
},
{
"cell_type": "code",
"execution_count": 84,
"id": "7f778025",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting entrypoint.sh\n"
]
}
],
"source": [
"%%writefile entrypoint.sh\n",
"#!/bin/sh -l\n",
"\n",
"figlet \"Hello $1\" | tee figlet.txt\n",
"echo \"Entrypoint invoked in: $PWD\"\n",
"readlink -f figlet.txt\n",
"time=$(date)\n",
"echo \"time=$time\" >> $GITHUB_OUTPUT"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "911975de",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"!chmod +x entrypoint.sh"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "483e0498",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting .github/workflows/docker.yml\n"
]
}
],
"source": [
"%%writefile .github/workflows/docker.yml\n",
"name: github-actions-hello-docker\n",
"on: \n",
" workflow_dispatch:\n",
" inputs:\n",
" input_text:\n",
" description: 'Who to greet' \n",
" required: true\n",
" default: 'World'\n",
"jobs:\n",
" hello-job:\n",
" runs-on: ubuntu-latest\n",
" steps:\n",
" - name: Checkout repo\n",
" uses: actions/checkout@v2\n",
" - name: Use docker action\n",
" id: hello\n",
" uses: ./\n",
" with:\n",
" who-to-greet: \"${{ github.event.inputs.input_text }}\"\n",
" # Use the output from the `hello` step\n",
" - name: Get the output time\n",
" run: echo \"The time was ${{ steps.hello.outputs.time }}\"\n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "bc24dff3",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[main 22a5094] Fix path\n",
" 1 file changed, 1 insertion(+)\n",
"Enumerating objects: 9, done.\n",
"Counting objects: 100% (9/9), done.\n",
"Delta compression using up to 4 threads\n",
"Compressing objects: 100% (5/5), done.\n",
"Writing objects: 100% (5/5), 570 bytes | 570.00 KiB/s, done.\n",
"Total 5 (delta 1), reused 0 (delta 0), pack-reused 0\n",
"remote: Resolving deltas: 100% (1/1), completed with 1 local object.\u001b[K\n",
"To github.com:TomekZet/ium-ga-hello.git\n",
" 97c7272..22a5094 main -> main\n"
]
}
],
"source": [
"!git add .github entrypoint.sh Dockerfile\n",
"!git commit -m \"Fix path\"\n",
"!git push"
]
},
{
"cell_type": "markdown",
"id": "12af9d1b",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Archiwizowanie artefaktów\n",
"https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts\n",
"\n",
"Do archiwizowania artefaktów służy akcja \"upload-artifact\":\n",
"\n",
"```yaml\n",
" - name: Archive artifacts\n",
" uses: actions/upload-artifact@v3\n",
" with:\n",
" name: figlet-output\n",
" path: figlet.txt\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "245f7c8a",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting .github/workflows/docker-artifact.yml\n"
]
}
],
"source": [
"%%writefile .github/workflows/docker-artifact.yml\n",
"name: github-actions-hello-docker-artifact\n",
"on: \n",
" workflow_dispatch:\n",
" inputs:\n",
" input_text:\n",
" description: 'Who to greet' \n",
" required: true\n",
" default: 'World'\n",
"jobs:\n",
" hello-job:\n",
" name: \"Do all the hard stuff\"\n",
" runs-on: ubuntu-latest\n",
" steps:\n",
" - name: Checkout repo\n",
" uses: actions/checkout@v2\n",
" - name: Use docker action\n",
" id: hello\n",
" uses: ./\n",
" with:\n",
" who-to-greet: \"${{ github.event.inputs.input_text }}\"\n",
" # Use the output from the `hello` step\n",
" - name: Get the output time\n",
" run: echo \"The time was ${{ steps.hello.outputs.time }}\" > time.txt\n",
" - name: Archive artifacts\n",
" uses: actions/upload-artifact@v3\n",
" with:\n",
" name: figlet-output\n",
" path: |\n",
" figlet.txt\n",
" time.txt\n",
" publish:\n",
" name: \"Publish as github comment\"\n",
" runs-on: ubuntu-latest\n",
" needs: hello-job\n",
" steps:\n",
" - uses: actions/checkout@v3\n",
" #We need to download the artifact first, jobs do not share workflow files\n",
" - name: get-artifact \n",
" uses: actions/download-artifact@v3\n",
" with:\n",
" name: figlet-output\n",
" - name: display_artifact_contents\n",
" run:\n",
" cat time.txt ; tr ' ' '#' < figlet.txt\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "47e301f9",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[main 5a40228] Archive in one job, use in other\n",
" 1 file changed, 1 insertion(+)\n",
"Enumerating objects: 9, done.\n",
"Counting objects: 100% (9/9), done.\n",
"Delta compression using up to 4 threads\n",
"Compressing objects: 100% (5/5), done.\n",
"Writing objects: 100% (5/5), 622 bytes | 622.00 KiB/s, done.\n",
"Total 5 (delta 2), reused 0 (delta 0), pack-reused 0\n",
"remote: Resolving deltas: 100% (2/2), completed with 2 local objects.\u001b[K\n",
"To github.com:TomekZet/ium-ga-hello.git\n",
" 4df6dc0..5a40228 main -> main\n"
]
}
],
"source": [
"!git add -u\n",
"!git commit -m \"Archive in one job, use in other\"\n",
"!git push"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "805622e8", "id": "805622e8",
@ -1047,26 +547,22 @@
} }
}, },
"source": [ "source": [
"## Zadania [20 pkt] (termin: 24.05.2023)\n", "## Zadania [15 pkt]\n",
"1. Utwórz konto na Github (jeśli jeszcze nie masz)\n", "1. Utwórz konto na Github (jeśli jeszcze nie masz)\n",
"2. Stwórz publiczne repozytorium. Link do niego wklej do kolumny \"Link Github\" w arkuszu [\"Zapisy na zbiory\"](https://teams.microsoft.com/l/file/F62B5988-A797-418D-B085-52E0AF8BD55E?tenantId=73689ee1-b42f-4e25-a5f6-66d1f29bc092&fileType=xlsx&objectUrl=https%3A%2F%2Fuam.sharepoint.com%2Fsites%2F2021SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11%2FShared%20Documents%2FGeneral%2FZapisy%20na%20zbiory.xlsx&baseUrl=https%3A%2F%2Fuam.sharepoint.com%2Fsites%2F2021SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11&serviceName=teams&threadId=19:d67b0dc2ee0849eba517a2aa8507df9c@thread.tacv2&groupId=8cd6b30e-edd9-48db-85ab-259fc11d0c5b) [1 pkt]\n", "2. Stwórz publiczne repozytorium. Link do niego wklej do kolumny \"Link Github\" w arkuszu [\"Zapisy na zbiory\"](https://teams.microsoft.com/l/file/F62B5988-A797-418D-B085-52E0AF8BD55E?tenantId=73689ee1-b42f-4e25-a5f6-66d1f29bc092&fileType=xlsx&objectUrl=https%3A%2F%2Fuam.sharepoint.com%2Fsites%2F2021SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11%2FShared%20Documents%2FGeneral%2FZapisy%20na%20zbiory.xlsx&baseUrl=https%3A%2F%2Fuam.sharepoint.com%2Fsites%2F2021SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11&serviceName=teams&threadId=19:d67b0dc2ee0849eba517a2aa8507df9c@thread.tacv2&groupId=8cd6b30e-edd9-48db-85ab-259fc11d0c5b) [1 pkt]\n",
"2. Stwórz prosty Github workflow który:\n", "2. Stwórz prosty Github workflow wykorzystujący akcje CML, który:\n",
" - zrobi checkout Twojego repozytorium [1 pkt]\n", " - zrobi checkout Twojego repozytorium [2 pkt]\n",
" - ściągnie pliki trenujące. Najlepiej byłoby to zrobić za pomocą DVC, ale tym razem uprośćmy zadanie ze względu na komplikacje, które mogą się pojawić przy konfiguracji uwierzytelniania. Pliki można po prostu dodać do repozytorium albo ściągnąć przez wget jeśli są publicznie dostępne [2 pkt]\n", " - ściągnie pliki trenujące. Najlepiej byłoby to zrobić za pomocą DVC, ale tym razem uprośćmy zadanie ze względu na koplikacje, które mogą się pojawić przy konfiguracji uwierzytelniania. Pliki można po prostu dodać do repozytorium albo ściągnąć przez wget jeśli są publicznie dostępne [2 pkt]\n",
" - będzie wywoływalny przez \"Workflow dispatch\" z parametrami trenowania [2 pkt]\n", " - dokona trenowania i ewaluacji [8 pkt]\n",
" - składał się będzie z co najmniej 3 jobów:\n", " - wyniki opublikuje za pomocą `cml-send-github-check` i/lub `cml-send-comment` [2 pkt]"
" 1. dokona trenowania jako osobnej akcji wykonanej w Dockerze [8 pkt]\n",
" 2. dokona ewaluacji modelu [6 pkt]\n",
" 3. zarchiwizuje plik z modelem"
] ]
} }
], ],
"metadata": { "metadata": {
"author": "Tomasz Ziętkiewicz", "author": "Tomasz Ziętkiewicz",
"celltoolbar": "Slideshow",
"email": "tomasz.zietkiewicz@amu.edu.pl", "email": "tomasz.zietkiewicz@amu.edu.pl",
"kernelspec": { "kernelspec": {
"display_name": "Python 3", "display_name": "Python 3 (ipykernel)",
"language": "python", "language": "python",
"name": "python3" "name": "python3"
}, },
@ -1081,7 +577,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.16" "version": "3.10.4"
}, },
"slideshow": { "slideshow": {
"slide_type": "slide" "slide_type": "slide"

@ -1 +0,0 @@
Subproject commit 5a40228be54897d47e0480318adcdbdec0e74d60

View File

@ -22,11 +22,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "a5f10a0e", "id": "a5f10a0e",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"# Abstract\n", "# Abstract\n",
"- Umiejętność pisania artykułu naukowego może okazać się przydatna dla osób zajmujących się uczeniem maszynowym.\n", "- Umiejętność pisania artykułu naukowego może okazać się przydatna dla osób zajmujących się uczeniem maszynowym.\n",
@ -37,17 +33,13 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "35d3630d", "id": "35d3630d",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"# Introduction\n", "## Introduction\n",
"\n", "\n",
"- Uczenie maszynowe i jego zastosowania to prężnie rozwijająca się dziedzina nauki\n", "- Uczenie maszynowe i jego zastosowania to prężnie rozwijająca się dziedzina nauki\n",
"- Żeby nadążyć za jej rozwojem musimy czytać artykuły naukowe\n", "- Żeby nadążyć za jej rozwojem musimy czytać artykuły naukowe\n",
"- A jeśli nasza praca ma charakter badawczy, to warto efekty naszej pracy od zebrać w postaci artykułu i opublikować\n", "- A jeśli nasza praca ma charakter badawczy, to warto taki artykuł napisać i opublikować\n",
"- Nasz pracodawca może od nas tego wymagać lub przynajmniej zachęcać\n", "- Nasz pracodawca może od nas tego wymagać lub przynajmniej zachęcać\n",
"- Dlatego zapoznamy się z:\n", "- Dlatego zapoznamy się z:\n",
"1. Strukturą artykułu naukowego\n", "1. Strukturą artykułu naukowego\n",
@ -57,13 +49,9 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "1033fc4d", "id": "1033fc4d",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"# Related work\n", "### Related work\n",
"\n", "\n",
"Jak napisać artykuł naukowy z dziedziny ML:\n", "Jak napisać artykuł naukowy z dziedziny ML:\n",
"- http://www.isle.org/~langley/papers/craft.ml2k.pdf / https://icml.cc/Conferences/2002/craft.html\n", "- http://www.isle.org/~langley/papers/craft.ml2k.pdf / https://icml.cc/Conferences/2002/craft.html\n",
@ -78,13 +66,9 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "2c7eb238", "id": "2c7eb238",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"# Methods" "## Methods"
] ]
}, },
{ {
@ -92,7 +76,7 @@
"id": "changed-president", "id": "changed-president",
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "slide"
} }
}, },
"source": [ "source": [
@ -101,7 +85,8 @@
"\n", "\n",
"0. Abstrakt (**A**bstract) - Dlaczego, jak, \n", "0. Abstrakt (**A**bstract) - Dlaczego, jak, \n",
"1. Wprowadzenie (**I**ntroduction) - \"Dlaczego?\"\n", "1. Wprowadzenie (**I**ntroduction) - \"Dlaczego?\"\n",
" 1. Related work - \"Kontekst naukowy\"\n", " \n",
" 1.1 Related work - \"Kontekst naukowy\"\n",
"2. Metody (**M**ethod) - \"Jak?\"\n", "2. Metody (**M**ethod) - \"Jak?\"\n",
"3. Wyniki (**R**esults) - \"Co?\"\n", "3. Wyniki (**R**esults) - \"Co?\"\n",
"4. Wnioski (**D**iscussion/Conclusions) - \"Interpretacja wyników\"" "4. Wnioski (**D**iscussion/Conclusions) - \"Interpretacja wyników\""
@ -110,11 +95,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "8cb9b025", "id": "8cb9b025",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"<img src=\"https://upload.wikimedia.org/wikipedia/commons/7/75/Wineglass_model_for_IMRaD_structure..png\"/>" "<img src=\"https://upload.wikimedia.org/wikipedia/commons/7/75/Wineglass_model_for_IMRaD_structure..png\"/>"
] ]
@ -122,11 +103,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "d3e245eb", "id": "d3e245eb",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Tytuł\n", "#### Tytuł\n",
"- powinien odzwierciedlać treść artykułu ;)\n", "- powinien odzwierciedlać treść artykułu ;)\n",
@ -139,11 +116,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "1f150ddb", "id": "1f150ddb",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Abstrakt\n", "#### Abstrakt\n",
"\n", "\n",
@ -155,15 +128,10 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "6005b4bd", "id": "6005b4bd",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Wprowadzenie\n", "#### Wprowadzenie\n",
" - Kontekst badań\n", " - Kontekst badań\n",
" - Od ogółu do szczegółu\n",
" - Motywacja\n", " - Motywacja\n",
" - Co chcemy właściwie zbadać - sformułowanie hipotezy badawczej" " - Co chcemy właściwie zbadać - sformułowanie hipotezy badawczej"
] ]
@ -171,28 +139,20 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "1308de25", "id": "1308de25",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Related work\n", "#### Related work\n",
" - Kontekst naukowy\n", " - Kontekst naukowy\n",
" - Co zrobiono przed nami\n", " - Co zrobiono przed nami\n",
" - Musimy się do tego odnieść w dalszej części i zaznaczyć co nasze badania wnoszą nowego do dziedziny\n", " - Musimy się do tego odnieść w dalszej części i zaznaczyć co nasze badania wnoszą nowego do dziedziny\n",
" - Cytujemy najważniejsze prace\n", " - Cytujemy najważniejsze prace\n",
" - Najlepiej zacząć szeroko i w przeszłości i stopniowo przechodzili do coraz nowszych i bardziej szczegółowych badań, bliżej związanych z tematyką poruszaną w naszym artykule." " - Najlepiej zaczącć szeroko i w przeszłości i stopniowo przechodzili do coraz nowszych i bardziej szczegółowych badań, bliżej związanych z tematyką poruszaną w naszym artykule."
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "b6cf4464", "id": "b6cf4464",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Metody\n", "#### Metody\n",
"- Jak przeprowadziliśmy nasze badania/eksperymenty\n", "- Jak przeprowadziliśmy nasze badania/eksperymenty\n",
@ -208,11 +168,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "5aee7988", "id": "5aee7988",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Wyniki\n", "#### Wyniki\n",
"- Jakie wyniki otrzymaliśmy\n", "- Jakie wyniki otrzymaliśmy\n",
@ -223,11 +179,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "7be88b24", "id": "7be88b24",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"#### Konkluzje\n", "#### Konkluzje\n",
"- Interpretacja wyników\n", "- Interpretacja wyników\n",
@ -239,13 +191,9 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "4753cf22", "id": "4753cf22",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"## Latex\n", "### Latex\n",
"\n", "\n",
"- LaTeX (wym. *Latech*) to system składu tekstu\n", "- LaTeX (wym. *Latech*) to system składu tekstu\n",
"- Najbardziej popularny w dziedzinach technicznych\n", "- Najbardziej popularny w dziedzinach technicznych\n",
@ -261,11 +209,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "918e3b39", "id": "918e3b39",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"### Struktura\n", "### Struktura\n",
"```latex\n", "```latex\n",
@ -401,11 +345,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "3ea5c879", "id": "3ea5c879",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"```bibtex\n", "```bibtex\n",
"\n", "\n",
@ -468,29 +408,10 @@
" - intagracja z Git/GitHub" " - intagracja z Git/GitHub"
] ]
}, },
{
"cell_type": "markdown",
"id": "ba75e390",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## arXiv.org\n",
" - https://arxiv.org/\n",
" - baza artykułów, uporządkowanych według kategorii\n",
" - umożliwia samodzielne opublikowanie artykułu jeszcze przed wysłaniem go do czasopisma/na konferencję. Artykuły tam dostępne nie są recenzowane, ale jest to sposób na otrzymanie feedbacku od społeczności poza oficjalnym procesem publikacyjnym."
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "e1822b3c", "id": "e1822b3c",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"### JupyterBook\n", "### JupyterBook\n",
"https://jupyterbook.org/en/stable/intro.html\n" "https://jupyterbook.org/en/stable/intro.html\n"
@ -499,11 +420,7 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ceef2f3f", "id": "ceef2f3f",
"metadata": { "metadata": {},
"slideshow": {
"slide_type": "slide"
}
},
"source": [ "source": [
"### The Turing Way\n", "### The Turing Way\n",
"*The Turing Way handbook to reproducible, ethical and collaborative data science*\n", "*The Turing Way handbook to reproducible, ethical and collaborative data science*\n",
@ -520,11 +437,11 @@
} }
}, },
"source": [ "source": [
"### Conclusions\n", "## Conclusions\n",
"### Zadanie [30pkt][2023-06-07] (zmiana terminu!)\n", "### Zadanie [30pkt]\n",
"1. Wybierz konferencję naukową z dziedziny ML/AI/Computer Science\n", "1. Wybierz konferencję naukową z dziedziny ML/AI/Computer Science\n",
"2. Używając szablonu Latex udostępnionego przez organizatorów konferencji, stwórz szkic artykułu naukowego opisującego wyniki eksperymentów ML, które przeprowadziłaś/eś w trakcie zajęć.\n", "2. Używając szablonu Latex udostępnionego przez organizatorów konferencji, stwórz szkic artykułu naukowego opisującego wyniki eksperymentów ML, które przeprowadziłaś/eś w trakcie zajęć.\n",
"3. Napisz artykuł używając Overleaf. Udostępnij w [arkuszu z zapisami](https://uam.sharepoint.com/:x:/r/sites/2023SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11/Shared%20Documents/General/IUM-2023-zapisy.xlsx?d=w49d444e07d864d2997ef7d72c5a47da0&csf=1&web=1&e=RT11aP) link udostępniający dokument ([jak stworzyć taki link](https://www.overleaf.com/learn/how-to/What_is_Link_Sharing%3F))\n", "3. Napisz artykuł używając Overleaf. Udostępnij w [arkuszu z zapisami](https://uam.sharepoint.com/:x:/r/sites/2022SL06-DIUMUI0LABInynieriauczeniamaszynowego-Grupa11/Shared%20Documents/General/Zapisy%20zbiory%20danych.xlsx?d=wb3e003a2d1364e88871c4bf951f13e88&csf=1&web=1&e=cXzeeV) link udostępniający dokument ([jak stworzyć taki link](https://www.overleaf.com/learn/how-to/What_is_Link_Sharing%3F))\n",
"4. Artykuł musi zawierać co najmniej:\n", "4. Artykuł musi zawierać co najmniej:\n",
" - 6 niepustych sekcji (abstract, introduction, related work, method, results, conclusions)\n", " - 6 niepustych sekcji (abstract, introduction, related work, method, results, conclusions)\n",
" - jedną tabelkę (np. opisującą dane lub wyniki)\n", " - jedną tabelkę (np. opisującą dane lub wyniki)\n",
@ -532,7 +449,6 @@
" - 5 cytowań (można np. zacytować artykuły opisujące użytą metodę, zbiory danych, narzędzia. Zazwyczaj popularne biblioteki, datasety podają w README jak należy je cytować)\n", " - 5 cytowań (można np. zacytować artykuły opisujące użytą metodę, zbiory danych, narzędzia. Zazwyczaj popularne biblioteki, datasety podają w README jak należy je cytować)\n",
" - 1 wzór matematyczny\n", " - 1 wzór matematyczny\n",
"5. Artykuł powinien być zgodny z wytycznymi konferencji dotyczącymi formy artykułów (oczywiście poza liczbą stron)\n", "5. Artykuł powinien być zgodny z wytycznymi konferencji dotyczącymi formy artykułów (oczywiście poza liczbą stron)\n",
"6. Na przedostatnich i ostatnich zajęciach będą Państwo prezentować artykuł i wtedy też zostanie on oceniony\n",
" \n", " \n",
"\n", "\n",
"Zapewne w napisanym artykule nie opiszą państwo niczego nowatorskiego i wartego publikacji - tutaj udajemy, że zastosowaliśmy metodę po raz pierwszy, osiągnęliśmy nieosiągalne dotąd wyniki itp. Liczy się forma i struktura pracy. Można dodać komentarz wyjaśniający prawdziwy cel artykuły w sekcji/przypisie \"Disclaimer\", żeby nikt Państwa nie posądzał o pisanie nieprawdy.\n", "Zapewne w napisanym artykule nie opiszą państwo niczego nowatorskiego i wartego publikacji - tutaj udajemy, że zastosowaliśmy metodę po raz pierwszy, osiągnęliśmy nieosiągalne dotąd wyniki itp. Liczy się forma i struktura pracy. Można dodać komentarz wyjaśniający prawdziwy cel artykuły w sekcji/przypisie \"Disclaimer\", żeby nikt Państwa nie posądzał o pisanie nieprawdy.\n",
@ -555,7 +471,7 @@
"metadata": { "metadata": {
"celltoolbar": "Slideshow", "celltoolbar": "Slideshow",
"kernelspec": { "kernelspec": {
"display_name": "Python 3", "display_name": "Python 3 (ipykernel)",
"language": "python", "language": "python",
"name": "python3" "name": "python3"
}, },
@ -569,7 +485,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.16" "version": "3.10.4"
} }
}, },
"nbformat": 4, "nbformat": 4,

View File

@ -1,159 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "3c047009",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Kubernetes\n",
"\n",
"<img style=\"height: 150px;\" src=\"img/kubernetes_logo.png\"/>"
]
},
{
"cell_type": "markdown",
"id": "9a21632b",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Kubernetes (aka. K8s) - system służący do automatyzacji:\n",
" - deploymentu\n",
" - skalowania\n",
" - zarządzania\n",
" \n",
" skonteneryzowanymi aplikacjami"
]
},
{
"cell_type": "markdown",
"id": "7bb1198e",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Motywacja\n",
"- Kubernetes jest środowiskiem, w którym działa Kubeflow - system stworzony z myślą o rozwoju i deploymencie modeli ML"
]
},
{
"cell_type": "markdown",
"id": "abe1d606",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Instalacja\n",
"- Instalacja do nauki i eksperymentów (nieprodukcyjna): https://minikube.sigs.k8s.io/docs/start/"
]
},
{
"cell_type": "markdown",
"id": "4ed97706",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Hello Minikube - interaktywny samouczek\n",
"1. Otwórz stronę: https://kubernetes.io/pl/docs/tutorials/hello-minikube/\n",
"2. Kliknij na \"Launch Terminal\" i wykonuj polecenia w otwartym terminalu (możesz klikać na fragmentach kodu a same przekopiują się do terminala i uruchomią)\n",
"\n",
"Większość interaktywnych samouczków z kubernetes.io przestała działać z końcem marca (https://kubernetes.io/blog/2023/02/14/kubernetes-katacoda-tutorials-stop-from-2023-03-31/), ale ten powyżej (i czasami niektóre inne, jeśli macie szczęście) wciąż działa"
]
},
{
"cell_type": "markdown",
"id": "eded46b6",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Terminologia\n",
"- Pod - (z angielskiego \"strąk\", np. strąk groszku, ale też grupa wielorybów <\"pod of whales\">)\n",
" grupa jednego lub więcej kontenerów wraz z przynależnymi wolumenami (volumes), adresem IP i informacją jak mogą być uruchomione\n",
"<img style=\"height: 200px;\" src=\"img/pod.jpg\"/>\n",
"- Node (węzeł) - pody (jeden lub więcej) są uruchamiane na węzłach - maszynach (fizycznych lub wirtualnych). Na każdym węźle jest uruchomiony proces \"kublet\", służący do komunikacji z \"control plane\", czyli serwerem kontrolującym klaster"
]
},
{
"cell_type": "markdown",
"id": "9d5b11fe",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"- Cluster - grupa węzłów\n",
"- Service - abstrakcja zapewniająca stabilny dostęp do Podów. Ponieważ Pod-y są efemeryczne, mogą być uruchamiane automatczynie np. w wyniki awarii węzła. Service definiuje jakie Pod-y (np. z jaką etykietą) są dostępne pod danym portem (więcej informacji: https://kubernetes.io/docs/concepts/services-networking/service/)\n",
"\n",
"- Schemat klastra: https://kubernetes.io/docs/concepts/overview/components/"
]
},
{
"cell_type": "markdown",
"id": "70932230",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Materiały\n",
"Zapoznaj się z następującymi materiałami:\n",
"1. https://kubernetes.io/pl/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro/\n",
"1. https://kubernetes.io/pl/docs/tutorials/kubernetes-basics/explore/explore-intro/\n",
"2. https://kubernetes.io/pl/docs/tutorials/kubernetes-basics/expose/expose-intro/"
]
},
{
"cell_type": "markdown",
"id": "8af62811",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Zadanie\n",
"Brak ;) ale patrz nowy termin zadania z zajęć \"12. Publikacja\" (07.06.2023)"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3",
"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.9.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB