Compare commits

..

No commits in common. "master" and "knowledgebase" have entirely different histories.

290 changed files with 787 additions and 23271 deletions

View File

View File

View File

@ -1,30 +0,0 @@
enabled: true
folders:
- pages
- themes
- config
sync:
on_save: true
on_delete: true
on_media: true
cron_enable: false
cron_at: '0 12,23 * * *'
local_repository: null
repository: 'git@git.kemt.fei.tuke.sk:KEMT/zpwiki.git'
no_user: '0'
user: zpwikiuser
password: gitsync-def502001df1df627230ddf8dbdcf2e009a33ef7eb2378430c12aabb4de1dc42d30c522473512dbeccab4782d87d16488303c5062a05a4fc155fa5379268f878650d714188f5614a7bf10a8d465410f276913bd9c28cda221a8deab71c6701fb
webhook: /_git-sync-9ad6430986a6
webhook_enabled: '0'
webhook_secret: 58488c5ff4bad574a21fc3f34b71d275ffbdaa0b1cdcafe4
branch: master
remote:
name: origin
branch: master
git:
author: gravuser
message: '(Grav GitSync) Automatic Commit'
name: GitSync
email: git-sync@trilby.media
bin: git
logging: false

View File

@ -1,4 +0,0 @@
enabled: true
active: true
start: '1'
depth: '6'

View File

View File

@ -1 +0,0 @@
salt: xZBMvDjawspOYb

View File

@ -1,20 +0,0 @@
title: 'Záverečné práce'
default_lang: en
author:
name: 'Joe Bloggs'
email: joe@example.com
taxonomies:
- category
- tag
- author
metadata:
description: 'Grav is an easy to use, yet powerful, open source flat-file CMS'
summary:
enabled: true
format: short
size: 300
delimiter: '==='
redirects: null
routes: null
blog:
route: /blog

View File

View File

@ -1,179 +0,0 @@
absolute_urls: false
timezone: ''
default_locale: null
param_sep: ':'
wrapped_site: false
reverse_proxy_setup: false
force_ssl: false
force_lowercase_urls: true
custom_base_url: ''
username_regex: '^[a-z0-9_-]{3,16}$'
pwd_regex: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
intl_enabled: true
http_x_forwarded:
protocol: true
host: false
port: true
ip: true
languages:
supported: { }
default_lang: null
include_default_lang: true
pages_fallback_only: false
translations: true
translations_fallback: true
session_store_active: false
http_accept_language: false
override_locale: false
home:
alias: /home
hide_in_urls: false
pages:
theme: mytheme
order:
by: default
dir: asc
list:
count: 20
dateformat:
default: null
short: 'jS M Y'
long: 'F jS \a\t g:ia'
publish_dates: true
process:
markdown: true
twig: false
twig_first: false
never_cache_twig: false
events:
page: true
twig: true
markdown:
extra: false
auto_line_breaks: false
auto_url_links: false
escape_markup: false
special_chars:
'>': gt
'<': lt
valid_link_attributes:
- rel
- target
- id
- class
- classes
types:
- html
- htm
- xml
- txt
- json
- rss
- atom
append_url_extension: ''
expires: 604800
cache_control: null
last_modified: false
etag: false
vary_accept_encoding: false
redirect_default_route: false
redirect_default_code: 302
redirect_trailing_slash: true
ignore_files:
- .DS_Store
ignore_folders:
- .git
- .idea
ignore_hidden: true
hide_empty_folders: false
url_taxonomy_filters: true
frontmatter:
process_twig: false
ignore_fields:
- form
- forms
cache:
enabled: true
check:
method: file
driver: auto
prefix: g
purge_at: '0 4 * * *'
clear_at: '0 3 * * *'
clear_job_type: standard
clear_images_by_default: true
cli_compatibility: false
lifetime: 604800
gzip: false
allow_webserver_gzip: false
redis:
socket: false
twig:
cache: true
debug: true
auto_reload: true
autoescape: false
undefined_functions: true
undefined_filters: true
umask_fix: false
assets:
css_pipeline: false
css_pipeline_include_externals: true
css_pipeline_before_excludes: true
css_minify: true
css_minify_windows: false
css_rewrite: true
js_pipeline: false
js_pipeline_include_externals: true
js_pipeline_before_excludes: true
js_minify: true
enable_asset_timestamp: false
collections:
jquery: 'system://assets/jquery/jquery-2.x.min.js'
errors:
display: true
log: true
log:
handler: file
syslog:
facility: local6
debugger:
enabled: false
shutdown:
close_connection: true
twig: true
images:
default_image_quality: 85
cache_all: false
cache_perms: '0755'
debug: false
auto_fix_orientation: false
seofriendly: false
media:
enable_media_timestamp: false
unsupported_inline_types: { }
allowed_fallback_types: { }
auto_metadata_exif: false
upload_limit: 2097152
session:
enabled: true
initialize: true
timeout: 1800
name: grav-site
uniqueness: path
secure: false
httponly: true
split: true
path: null
gpm:
releases: stable
proxy_url: null
method: auto
verify_peer: true
official_gpm_only: true
accounts:
type: data
storage: file
strict_mode:
yaml_compat: true
twig_compat: true

View File

@ -1,13 +0,0 @@
streams:
schemes:
theme:
type: ReadOnlyStream
prefixes:
'': [user/themes/mytheme, user/themes/knowledge-base]
display_of_git_sync_repo_link: page
type_of_git_sync_repo_link: edit
custom_git_sync_repo_link_icon: null
custom_git_sync_repo_link_text: null
git_sync_edit_note_text: null
custom_git_sync_repo_presentation_link_text: null
git_sync_repo_link: 'https://git.kemt.fei.tuke.sk/KEMT/zpwiki/src/branch/master'

View File

@ -1,112 +0,0 @@
import os
import sys
import re
import posixpath
import argparse
from pathlib import Path
from shutil import copyfile
import yaml
name_reg = re.compile(r"(/[0-9][0-9]\.)+")
def filter_string(string, string_replace='/', regex=name_reg):
return re.sub(regex, string_replace, string)
# Input: dirname_from: where you want to migrate from. migrate_rootpath: path including the new root dir of the structure
def transform_wiki(dirname_from, migrate_rootpath):
# New file structure
Path(migrate_rootpath).mkdir(parents=True, exist_ok=True)
dir_path_new = None
for root, dirs, files in os.walk('./' + dirname_from, topdown=False):
# Filter the new names i dst
root_src = root
root_dst = filter_string(root, '/', name_reg)
# Make a new regural dirs (without bottom dir which is replaced by .md file)
path = '/'.join(root_dst.split('/')[2:-1]) # The path following the root dir (./Pages)
dir_path_new = migrate_rootpath + '/' + path
Path(dir_path_new).mkdir(parents=True, exist_ok=True)
for file_name in files:
# File path in original structure
file_path_scr = root_src + "/" + file_name
# Test for only altering .md-files
if not file_name.endswith(".md"):
# Copy other files from scr
src = file_path_scr
dst = '/'.join([dir_path_new, file_name])
copyfile(src, dst)
continue
# Open original file
with open(file_path_scr) as f_from:
try:
# New name convention for .md-files migrated to new structure
new_filepath = dir_path_new + '/' + os.path.basename(root_dst) + '.md'
with open(new_filepath, 'w') as f_to:
lines = []
yamlfront = []
inyamlfront = False
for l in f_from:
line = l.rstrip()
if len(lines) == 0 and line.startswith("---"):
inyamlfront = True
elif inyamlfront:
if line.startswith("---"):
inyamlfront = False
print(yamlfront)
front = yaml.load("\n".join(yamlfront))
if "taxonomy" in front:
taxonomy = front["taxonomy"]
del front["taxonomy"]
tags = []
if "tags" in taxonomy:
tags = taxonomy["tags"]
if "categories" in taxonomy:
for tag in taxonomy["categories"]:
tags.append("cat:" + tag)
del taxonomy["categories"]
if len(tags) > 0:
taxonomy["tags"] = tags
for k,v in taxonomy.items():
front[k] = v
del yamlfront[:]
yamlfront.append("---")
yamlfront.append(yaml.dump(front))
yamlfront.append("---")
else:
yamlfront.append(line)
else:
lines.append(line)
if len(yamlfront) > 0:
for line in yamlfront:
print(line,file=f_to)
for line in lines:
print(line,file=f_to)
except UnicodeDecodeError:
print("UnocodeError in :" + file_path_scr)
if __name__ == "__main__":
'''
path = 'pages_migrated_example/55.usaa/cvicenia/05.linked.md'
#path = '05.linked.md'
print(path)
path = filter_string(path, '/', name_reg)
print(path)
'''
parser = argparse.ArgumentParser()
parser.add_argument("dirname", type=str)
parser.add_argument("migrate_root",type=str)
args = parser.parse_args()
transform_wiki(args.dirname, args.migrate_root)

View File

@ -1,6 +1,6 @@
--- ---
title: Bakalárske práce 2018/2019 title: Bakalárske práce 2018/2019
category: bp2019 category: bp2021
published: true published: true
--- ---

View File

@ -1,5 +1,5 @@
--- ---
title: Bakalárska práca 2019/2020 title: Bakalárska práca 2020
category: bp2020 category: bp2020
published: true published: true
--- ---

View File

@ -1,7 +1,3 @@
---
title: Bakalárske práce 2020/2021
category: bp2021
---
# Bakalárske práce 2021 # Bakalárske práce 2021
## Témy ## Témy
@ -24,4 +20,3 @@ category: bp2021
- natrénovanie modelu QA s databázy SQUAD? - natrénovanie modelu QA s databázy SQUAD?
- Využitie existujúceho anglického modelu? - Využitie existujúceho anglického modelu?

View File

@ -1,76 +0,0 @@
---
title: Bakalárske práce 2021/2022
category: bp2022
---
# Bakalárske práce 2022
Ak ste študentom 2. alebo 3. ročníka odboru Počítačové siete na KEMT a máte záujem o niektorú z týchto tém, napíšte e-mail na daniel.hladek@tuke.sk.
Naučíte sa:
- niečo o spracovaní prirodzeného jazyka
- vytvárať webové aplikácie
- pracovať s nástrojmi v jazyku Python
- prekonávať technické problémy
Požiadavky:
- chcieť sa naučiť niečo nové
## Témy
### Automatické odpovede z Wikipédie
1. Vypracujte prehľad aktuálnych metód pre generovanie odpovede na otázku v prirodzenom jazyku
2. Natrénujte existujúci systém pre generovanie odpovede na otázku v prirodzenom jazyku.
3. Vytvorte demonštračnú webovú aplikáciu.
4. Navrhnite zlepšenia systému pre generovanie odpovede.
- Natrénujte existujúci systém pre generovanie odpovede na otázku v prirodzenom jazyku.
- Vytvorte demonštračnú webovú aplikáciu.
### Strojový preklad slovenského jazyka
- Zoberte existujúci systém pre strojový preklad.
- Pripravte existujúci paralelný korpus pre trénovanie.
- Vytvorte model pre strojový preklad slovenského jazyka.
1. Vypracujte prehľad aktuálnych metód pre generovanie odpovede na otázku v prirodzenom jazyku
2. Natrénujte existujúci systém pre generovanie odpovede na otázku v prirodzenom jazyku.
3. Vytvorte demonštračnú webovú aplikáciu.
4. Navrhnite zlepšenia systému pre generovanie odpovede.
### Rozpoznávanie pomenovaných entít v slovenskom jazyku
- Zlepšite model pre rozpoznávanie pomenovaných entít.
- Anotujte korpus, navrhnite lepší klasifikátor.
Pomenované entity sú väčšinou vlastné podstatné mená v texte. Ich rozpoznanie nám pomôže určiť o čom text je. To sa často využíva v chatbotoch alebo vo vyhľadávaní v texte.
1. Vypracujte prehľad metód rpre rozpoznávanie pomenovaných entít v texte.
2. Vyberte vhodnú metódu a natrénujte model pre rozpoznávanie pomenovaných entít.
3. Vykonajte viacero experimentov a zistite s akými parametrami má model najvyššiu presnosť.
4. Navrhnite ďalšie zlepšenia modelu pre rozpoznávanie pomenovaných entít.
### Vyhľadávač na slovenskom internete
Databáza dokumentov je k dispozícii. Na vytvorenie indexu je možné použiť Elasticsearch alebo podobný systém.
Dokument je potrebné spracovať pomocou skriptu v jazyku Python alebo Javascript.
- Vytvorte index pre vyhľadávanie v databáze slovenských stránok (Cassandra, Elasticseaech).
- Vytvorte webové rozhranie k vyhľadávaču.
1. Vypracujte prehľad metód pre získavanie informácií.
2. Vytvorte vyhľadávací index dokumentov zo slovenského internetu.
3. Vytvorte demonštračnú webovú aplikáciu pre vyhľadávanie na slovenskom internete.
4. Navrhnite zlepšenia vyhľadávania.
### Model Spacy pre spracovanie prirodzeného jazyka
Knižnica Spacy je často používaný nástroj na spracovanie prirodzeného jazyka.
Dobrý model slovenčiny pomože pri vývoji virtuálnych asistentov a iných nástrojov.
1. Zistite ako pracuje knižnica Spacy a opíšte metódy ktoré používa.
2. Natrénujte model pre spracovanie slovenského prirodzeného jazyka.
3. Indentifikujte slabé miesta a zlepšite presnosť spracovania.
4. Vykonajte viacero experimentov a zistite presnosť pri rôznych parametroch.

View File

@ -1,7 +1,51 @@
--- ---
title: Diplomové práce 2020/2021 title: Spracovanie prirodzeného jazyka a jazyk Python
category: dp2021
published: true published: true
--- ---
# Tímový projekt 2019
[Daniel Hládek](../) - odporúčaný čas konzultácie: štvrtok o 9:00
Ciele:
- [Spracovanie prirodzeného jazyka](/topics/nlp), [Programovanie v jazyku Python](/topics/python)
- špecifikovať zadanie diplomovej práce
- naučiť sa pracovať s [odbornou literatúrou](../zp)
- oboznámiť kolegov s obsahom vykonanej práce
## Podmienky na zápočet
- Vypracovaný tutoriál alebo rešerš vybranej metódy (8. a 13. týždeň). Rozsah výstupu min. 3 A4 kvalitného textu, vypracovaný prehľad literatúry vybranej metódy (min. 10 odkazov) ,odovzdanie textu cez [MOOODLE](https://moodle.tuke.sk/moodle35/course/view.php?id=874) kľúč je TP2019 a cez Váš osobný profil
- Vypracovanie osobného profilu podľa [šablóny](../../../../students/2016/vzorny_student).
- Dohodnuté znenie názvu a zadania záverečnej práce
## Študenti a témy
- [Maroš Harahus](../../../../students/2016/maros_harahus) "Part of Speet Tagging" pomocou Spacy
- [Lukáš Pokrývka](../../../../students/2016/lukas_pokryvka) "Paralelné trénovanie sémantických modelov prirodzeného jazyka" (word2vec, word embeddings, GloVe, fastText)
- [Ján Holp](../../../../students/2016/jan_holp) (získavanie informácií)
- [Dárius Lindvai](../../../../students/2016/darius_lindvai) (punctuation restoration, [tutorial](https://medium.com/@praneethbedapudi/deepcorrection2-automatic-punctuation-restoration-ac4a837d92d9), pytorch, LSTM tutorial)
- [Jakub Maruniak](../../../../students/2016/jakub_maruniak) (prodigy, vytvorenie korpusu, [named-entity](../prodigy),
- [Dominik Nagy](../../../../students/2016/dominik_nagy) (spelling correction, fairseq)
## Dátumy stretnutí
- 10.10 - Harahus, Holp
- 14.10. - Nagy, Maruniak, Pokrývka (prečítať knihu, vybrať tému)
- 17.10 - Harahus, Lindvai (Prečítať knihu, prejsť Spacy tutoriál, nainštalovať Anaconda)
- 24.10 - Pracovná cesta
- 28.10 o 9:00, Holp, Harahus
- 31.10 - Dekanské voľno
- 4.11 - Maruniak
- 7.11 o 13:40 - Lindvai, Nagy, Pokrývka, Harahus
- 14.11 - Lindvai, Harahus, Holp
- 21.11 - Lindvai
- 28.11 - Harahus, Holp
- 5.12. - Harahus
- 12.12. - Holp, Harahus
- 15.1. Nagy
- 23.1. Harahus, Pokrývka, Holp, Maruniak, Nagy, Lindvai

View File

@ -1,30 +0,0 @@
---
title: Diplomové práce 2021/2022
category: dp2022
published: true
---
Naučíte sa:
- Niečo viac o neurónových sieťach.
- Vytvárať jednoduché programy na úpravu dát.
- Zapojiť sa do reálneho výskumu.
### Morfologická analýza s podporou predtrénovania
- Zoberte existujúci model pre morfologickú analýzu slovenského jazyka a vyhodnotte ho.
- Použite BERT model na natrénovanie morfologickej anotácie a porovnajte presnosť so základným modelom.
### Slovné jednotky v predspracovaní pre strojový preklad
- Natrénujte systém pre strojový preklad
- Vytvorte niekoľko modelov pre rozdelenie slov na menšie jednotky v slovenskom jazyku. Pre každý model rozdelenia slov natrénujte systém pre strojový preklad.
- Porovnajte výsledky strojového prekladu s rôznymi rozdeleniami slov.
### Spracovanie veľkých dát pre účely získavania informácií
- Naučte sa pracovať s databázou Cassandra a Python
- indexujte dáta z webu
- implementujte techniku vyhodnotenia dokumentov

View File

@ -1,13 +0,0 @@
---
title: Diplomové práce 2022/2023
category: dp2023
---
# Diplomové práce 2022/2023
## Témy
1. Strojový preklad pomocou neurónových sietí (Jancura)
2. Generatívne jazykové modely (Megela)
3. Detekcia emócií z textu:
- https://github.com/savan77/EmotionDetectionBERT

View File

@ -1,52 +0,0 @@
---
title: Tímový projekt 2020
category: tp2020
---
# Tímový projekt 2020
[Daniel Hládek](../) - odporúčaný čas konzultácie: štvrtok o 9:00
Ciele:
- [Spracovanie prirodzeného jazyka](/topics/nlp), [Programovanie v jazyku Python](/topics/python)
- špecifikovať zadanie diplomovej práce
- naučiť sa pracovať s [odbornou literatúrou](../zp)
- oboznámiť kolegov s obsahom vykonanej práce
## Podmienky na zápočet
- Vypracovaný tutoriál alebo rešerš vybranej metódy (8. a 13. týždeň). Rozsah výstupu min. 3 A4 kvalitného textu, vypracovaný prehľad literatúry vybranej metódy (min. 10 odkazov) ,odovzdanie textu cez [MOOODLE](https://moodle.tuke.sk/moodle35/course/view.php?id=874) kľúč je TP2019 a cez Váš osobný profil
- Vypracovanie osobného profilu podľa [šablóny](../../../../students/2016/vzorny_student).
- Dohodnuté znenie názvu a zadania záverečnej práce
## Študenti a témy
- [Maroš Harahus](../../../../students/2016/maros_harahus) "Part of Speet Tagging" pomocou Spacy
- [Lukáš Pokrývka](../../../../students/2016/lukas_pokryvka) "Paralelné trénovanie sémantických modelov prirodzeného jazyka" (word2vec, word embeddings, GloVe, fastText)
- [Ján Holp](../../../../students/2016/jan_holp) (získavanie informácií)
- [Dárius Lindvai](../../../../students/2016/darius_lindvai) (punctuation restoration, [tutorial](https://medium.com/@praneethbedapudi/deepcorrection2-automatic-punctuation-restoration-ac4a837d92d9), pytorch, LSTM tutorial)
- [Jakub Maruniak](../../../../students/2016/jakub_maruniak) (prodigy, vytvorenie korpusu, [named-entity](../prodigy),
- [Dominik Nagy](../../../../students/2016/dominik_nagy) (spelling correction, fairseq)
## Dátumy stretnutí
- 10.10 - Harahus, Holp
- 14.10. - Nagy, Maruniak, Pokrývka (prečítať knihu, vybrať tému)
- 17.10 - Harahus, Lindvai (Prečítať knihu, prejsť Spacy tutoriál, nainštalovať Anaconda)
- 24.10 - Pracovná cesta
- 28.10 o 9:00, Holp, Harahus
- 31.10 - Dekanské voľno
- 4.11 - Maruniak
- 7.11 o 13:40 - Lindvai, Nagy, Pokrývka, Harahus
- 14.11 - Lindvai, Harahus, Holp
- 21.11 - Lindvai
- 28.11 - Harahus, Holp
- 5.12. - Harahus
- 12.12. - Holp, Harahus
- 15.1. Nagy
- 23.1. Harahus, Pokrývka, Holp, Maruniak, Nagy, Lindvai

View File

@ -1,17 +0,0 @@
---
title: Tímový projekt 2021
category: tp2021
---
# Tímový projekt 2021
Ciele:
- špecifikovať zadanie diplomovej práce
- naučiť sa pracovať s odbornou literatúrou
- oboznámiť kolegov s obsahom vykonanej práce
## Podmienky na zápočet
- Vypracovaný tutoriál alebo rešerš vybranej metódy (8. a 13. týždeň). Rozsah výstupu min. 4 A4 kvalitného textu, vypracovaný prehľad literatúry vybranej metódy (min. 10 odkazov) ,odovzdanie textu cez [MOOODLE](https://moodle.tuke.sk/moodle35/course/view.php?id=874) kľúč je TP2019 a cez Váš osobný profil
- Dohodnuté znenie názvu a zadania záverečnej práce

View File

@ -1,41 +0,0 @@
---
title: Vedecký projekt 2020/2021
category: vp2021
---
## Vedecký projekt 2021
Príprava na bakalársky projekt pre študentov 2. ročníka programu Počítačové siete. Letný semester.
Vedúci: Ing. Daniel Hládek PhD.
Požiadavky:
- Chuť naučiť sa niečo nové.
### Dialógový systém pomocou RASA framework
Cieľom projektu je naučiť sa niečo o dialógových systémoch a oboznámiť sa so základnými nástrojmi.
- Nainštalujte a oboznámte sa s [RASA frameworkom](https://rasa.com/docs/). Pri inštalácii využite systém [Anaconda](https://docs.anaconda.com/anaconda/user-guide/getting-started/).
- Vyberte a prejdite najmenej jeden tutoriál pre prácu s RASA frameworkom.
- Napíšte krátky report na 2 strany kde napíšete čo ste urobili a čo ste sa dozvedeli.
### Klaudové služby pre získavanie informácií
Cieľom projektu je zistiť ako fungujú klaudové služby pre umelú inteligenciu
a ako fungujú webové vyhľadávače.
- Zistite čo je to získavanie informácií.
- Oboznámte sa s [Azure Cognitive Search](https://azure.microsoft.com/en-us/services/search/) a získajte prístup k službe. Pre prihlásenie môžete použiť Váše študentské prihlasovacie údaje.
- Vypracujte minimálne jeden tutoriál pre prácu s Azure Cognitive Search.
- Vypracujte krátky report na 2 strany kde napíšete čo ste robili a čo ste sa dozvedeli.
### Rozpoznávanie pomenovaných entít
Cieľom projektu je zistiť ako sa robia základné úlohy spracovania prirodzeného jazyka - rozpoznávanie vlastných podstatných mien a oboznámenie sa zo základnými nástrojmi.
- Zistite čo je to pomenovaná entita a prečo je rozpoznávanie pomenovaných entít v prirodzenom jazyku dôležité.
- Vyznačte [pomenované entity v textoch z Wikipédie](https://zp.kemt.fei.tuke.sk/topics/named-entity/navod).
- Nainštalujte si [framework Spacy](https://spacy.io/) a vyskúšajte, ako funguje rozpoznávanie pomenovaných entít v anglickom jazyku. Pri inštalácii využite systém [Anaconda](https://docs.anaconda.com/anaconda/user-guide/getting-started/).
- Napíšte krátku správu na cca 2 strany kde napíšete čo ste robili a čo ste sa dozvedeli.

View File

@ -1,31 +0,0 @@
---
title: Vedecký projekt 2021/2022
category: vp2022
---
## Vedecký projekt 2022
Príprava na bakalársky projekt pre študentov 2. ročníka programu Počítačové siete. Letný semester.
Vedúci: Ing. Daniel Hládek PhD.
Požiadavky:
- Chuť naučiť sa niečo nové.
Obsah:
- Naštudujete si zadanú problematiku.
- Naučte sa základy jazyka Python.
- Podrobne si prejdite minimálne dva tutoriály.
- Napíšte krátky report na 2 strany kde napíšete čo ste urobili a čo ste sa dozvedeli.
### Extrakcia informácií z webových stránok
- Naštudujete si knižnicu BeautifulSoup a navrhnete skripty pre parsovanie niekoľkých webových stránok
### Dotrénovanie jazykových modelov
- Naučte sa pracovať s knižnicou HuggingFace transformers.
- Naučíte sa základy neurónových jazykových modelov.
- Dorénujete neurónovú sieť na vybraný problém.

View File

@ -3,3 +3,5 @@ title: Daniel Hladek
author: Daniel Hladek author: Daniel Hladek
--- ---
Duis cotidieque an vel, ex impetus suscipit consetetur duo. Mutat vivendo ex sit! Eu quas iusto putant eum, amet modo vix ne, ne nam habeo inimicus? An civibus intellegat ius, etiam invidunt dignissim vix an, habeo vocent ocurreret in ius! Ei nec augue populo, decore accusamus cotidieque nec an. Ne vis unum nusquam, pertinax sententiae quaerendum his in!

View File

@ -1,5 +0,0 @@
---
title: Maroš Harahus
author: Maroš Harahus
---

View File

@ -12,13 +12,9 @@ taxonomy:
- [Ako písať záverečnú prácu](http://akopisatprace.sk/wp-content/uploads/ako_pisat_zav_prace_final_skratene2_6.pdf) - [Ako písať záverečnú prácu](http://akopisatprace.sk/wp-content/uploads/ako_pisat_zav_prace_final_skratene2_6.pdf)
- [Odovzdanie a šablóna](https://portal.lib.tuke.sk/etd/) - [Odovzdanie a šablóna](https://portal.lib.tuke.sk/etd/)
## Osnova záverečnej práce Predstavte čitateľovi problém a možné spôsoby riešenia. Z možných spôsobov vyberte jeden a odôvodnite prečo ste ho vybrali.
V praktickej časti opíšte vykonané experimenty a výsledky uch vyhodnotenia tak aby ich bolo možné opakovať.
1. Úvod: Predstavte čitateľovi problém V závere identifikujte slabé miesta a navrhnite zlepšenia.
2. Teória (State-of-the-art): Vysvetlíte možné spôsoby riešenia definovaného problému a vysvetlíte dôležité pojmy. Mali by ste sa odvolávať na najnovšie vedecké články a knihy.
3. Riešenie: Z možných spôsobov riešenia vyberte jeden a odôvodnite prečo ste ho vybrali. Opíšte ho podrobnejšie.
4. Vyhodnotenie (Experimenty): Vaše riešenie predstavte vo viacerých modelových situáciách a navrhnite experimenty ktoré číselne vyhodnotia Vaše riešenie. Experimenty navrhnite a opíšte tak, aby ich bolo možné zopakovať a aby Vaše výsledky boli porovnateľné s inými.
5. Záver (Diskusia). Identifikujte slabé miesta Vášho prístupu navrhnite zlepšenia. Definujte ako by mal vyzerať budúci výskum v oblasti riešenia Vášho problému. Zhrňte Vášu prácu a Váš prínos do vybranej oblasti.
## Ako citovať ## Ako citovať

View File

@ -12,61 +12,21 @@ taxonomy:
Wiki stánka pre spoluprácu na záverečných prácach. Wiki stánka pre spoluprácu na záverečných prácach.
- [Často kladené otázky](/topics/faq) - [Často kladené otázky](/info/faq)
- [Ako napíšem záverečnú prácu](/topics/akopisat) - [Ako napíšem záverečnú prácu](/info/akopisat)
- [Prostredie Anaconda a jazyk Python pre strojové učenie](/topics/python)
## Vedúci
- [Daniel Hládek](/authors/daniel-hladek)
- [Maroš Harahus](/authors/maros-harahus)
## Predmety ## Predmety
- [Diplomové práce 2024](/categories/dp2024) - [Bakalárske práce 2020](/categories/bp2020)
- [Bakalárske práce 2024](/categories/bp2024)
## Vedecké projekty
- [Dialógový systém](/topics/chatbot)
- Rozpoznávanie nenávistnej reči (Hate Speech Detection)
- [Hate Speech Project Page](/topics/hatespeech)
- Rozpoznávanie pomenovaných entít
- [Projektová stránka](/topics/named-entity)
- [Anotujte korpus](/topics/named-entity/navod)
- [Ostatné projekty](/categories/projects)
## Ukončené projekty
- [Podpora slovenčiny v knižnici Spacy](/topics/spacy)
- [Slovenský BERT model](/topics/bert)
- [AI4Steel](/topics/steel)
- Korpus otázok a odpovedí
- [Projektová stránka](/topics/question)
- [Vytvorte otázky a odpovede](/topics/question/navod)
- [Validujte otázky a odpovede](/topics/question/validacie)
- [Vytvorte nezodpovedateľné otázky a odpovede](/topics/question/nezodpovedatelne)
## Uzavreté predmety
## 2023
- [Diplomové práce 2023](/categories/dp2023)
- [Bakalárske práce 2023](/categories/bp2023)
## 2022
- [Diplomové práce 2022](/categories/dp2022)
- [Bakalárske práce 2022](/categories/bp2022)
## 2021
- [Bakalárske práce 2021](/categories/bp2021)
- [Vedecký projekt 2021](/categories/vp2021)
- [Bakalárske práce 2021](/categories/bp2021)
- [Diplomové práce 2021](/categories/dp2021) - [Diplomové práce 2021](/categories/dp2021)
## 2020 ## Projekty
- [Spracovanie prirodzeného jazyka](/topics/nlp)
- [Podpora slovenčiny v knižnici Spacy](/topics/spacy)
- [Anotácia textových korpusov](/topics/prodigy)
- [Rozpoznávanie pomenovaných entít](/topics/named-entity)
- [Dialógový systém](/topics/chatbot)
- [Výsledky Tímového projektu 2020](/categories/tp2020)
- [Bakalárske práce 2020](/categories/bp2020)

View File

@ -20,24 +20,30 @@ Stránky môžte editovať cez web rozhranie systému alebo lokálne pomocou V
## Čo tu nájdem? ## Čo tu nájdem?
Nájdete tu materiály súvisiace s vypracovaním záverečnej práce. Kažý študent tu nájde svoj záznam o projekte. Nájdete tu materiály súvisiace s vypracovaním záverečnej práce.
- `/home` : Domovská stránka
- `/teachers`: Projekty pod vedením pedagógov (zapisuje hlavne pedagog).
- `/topics`: Iné informácie (Zapisujú hlavne pedagógovia)
- `/students`: Študentské výstupy (Zapisuje hlavne študent)
Každý prihlásený používateľ ma svoj osobný profil, za ktorý je zodpovedný.
- `/teachers/komensky`": Stránka s profilom pedagóga
- `/teachers/komensky/bp2020`: Stránka s bakalárskymi prácami pedagóga
Študenti sú organizovaní do skupín podľa roku nástupu na štúdium: Študenti sú organizovaní do skupín podľa roku nástupu na štúdium:
- `/students/rok_nastupu_na_studium/meno_priezvisko`: Stránka s profilom študenta a prácami na ktorých pracoval. - `/students/2016/ab123cd`: Stránka s profilom študenta a prácami na ktorých pracoval.
## Ako upravím stránky cez webové rozhranie ## Ako upravím stránky cez webové rozhranie
Prihláste sa na katedrový systém GIT. Vyhľadajte repozitár [KEMT/zpwiki](https://git.kemt.fei.tuke.sk/KEMT/zpwiki). Do tohto repozitára môžte vykonávať zmeny pomocou webového editora, kotrý Vám uľahčí prácu s formátom Markdown.
Zobrazte si stránku kotrú chcete upraviť. ´Tuknite na odkaz "Edit this page".
Na editovanie sa potrebujete prihlásiť do GIT servra pomocou Vašich študentských prístupových údajov.
Zmeny môžete vykonávať pomocou webového editora, kotrý Vám uľahčí prácu s formátom Markdown. Cez webové rozhranie nájdite adresár, ktorý patrí k stránke. Ťuknite na súbor `README.md`. V pravom hornom rohu ťuknite na ikonku s perom. Otvorí sa Vám editor v ktorom môžte upravovať.
V pravom hornom rohu ťuknite na ikonku s perom. Otvorí sa Vám editor v ktorom môžte upravovať. Keď skončíte s úpravami, ťuknite na zelené tlačítko "Commit changes/Potvrď zmeny" celkom dole na stránke. Pre vytvorenie nového adresára stačí dopísať jeho meno pred názov nového súboru a adresár sa vytvorí automaticky.
Keď skončíte s úpravami, ťuknite na zelené tlačítko "Commit changes/Potvrď zmeny" celkom dole na stránke. Zmena na GITe sa automaticky zobrazí aj na wiki stránke.
Pre vytvorenie nového adresára stačí dopísať jeho meno pred názov nového súboru a adresár sa vytvorí automaticky.
## Ako upravím stránky pomocu môjho textového editora ## Ako upravím stránky pomocu môjho textového editora
@ -66,20 +72,16 @@ Text vo formáte Markdown vytvoríte pomocou textového editora alebo pomocou we
## Ako vytvorím odkaz ## Ako vytvorím odkaz
Meno stránky je totožné s adresárom v ktorom sa nachádza. Na stránku sa odkážete podobne ako na adresár v ktorom sa nachádza. Meno stránky je totožné s adresárom v ktorom sa nachádza. Na stránku sa odkážete podobne ako na adresár v ktorom sa nachádza.
Napr. odkaz na stránku s Vašim projektom zo stránky predmetu `/teachers/hladek/bp2020`:
Takto odkážete na stránku Vášho kolegu: [Text odkazu](../../students/ab123cd/bp)
[Môj obľúbený kolega](/students/2016/vzorny_student)
## Ako vložím obrázok ## Ako vložím obrázok
Uložte súbor s obrázkom do adresára s Vašou stránkou. Do textu pridajte odkaz na obrázok a pridajte výkričník: Uložte súbor s obrázkom do adresára s Vašou stránkou. Do textu pridajte odkaz na obrázok a pridajte výkričník:
![Text odkazu](./obrazok.jpg) ![Text odkazu](./obrazok.jpg)
Na vloženie obrázka môžete použiť aj web rozhranie. Ťuknite na "Edit page" a potom cez Git na "New file".
## Čo ak som našiel preklep? ## Čo ak som našiel preklep?
Môžte ho sám opraviť. Môžte ho sám opraviť.

View File

@ -1,16 +1,5 @@
---
title: Cesar Abascal Gutierrez
published: true
taxonomy:
category: [iaeste]
tag: [ner,nlp]
author: Daniel Hladek
---
## Named entity annotations ## Named entity annotations
Intern, probably summer 2019
Cesar Abascal Gutierrez <cesarbielva1994@gmail.com> Cesar Abascal Gutierrez <cesarbielva1994@gmail.com>
## Goals ## Goals

View File

@ -1,66 +0,0 @@
---
title: Oliver Pejic
published: true
taxonomy:
category: [iaeste]
tag: [hatespeech,nlp]
author: Daniel Hladek
---
Oliver Pejic
IAESTE Intern Summer 2024, 12 weeks in August, September and October.
Goal:
- Help with the [Hate Speech Project](/topics/hatespeech)
- Help with evaluation of sentence transformer models using toolkit [MTEB](https://github.com/embeddings-benchmark/mteb)
Final Tasks:
- Prepare an MTEB evaluation task for [Slovak HATE speech](https://huggingface.co/datasets/TUKE-KEMT/hate_speech_slovak).
- Prepare an MTEB evaluation task for [Slovak question answering](https://huggingface.co/datasets/TUKE-KEMT/retrieval-skquad).
- [Machine translate](https://huggingface.co/google/madlad400-3b-mt) an SBERT evaluation set for multiple slavic languages.
- Write a short scientific paper with results.
Meeting 3.10.:
State:
- Prepared a pull request for Retrieval SK Quad.
- Prepared a pull request for Hate Speech Slovak.
Tasks:
- Make the pull request compatible with the MTEB Contribution guidelines. Discuss it when it is done.
- Submit pull requests to MTEB project.
- Machine Translate a database (HotpotQA, DB Pedia, FEVER) . Pick a database that is short, because translation might be slow.
Non priority tasks:
- Prepare databse and subnit it to HuggingFace Hub.
- Prepare a MTEB PR for the databse.
Meeting 3.9:
State: Studied MTEB framework and transformers.
Tasks:
- Prepare and try MTEB evaluation tasks for the database. For evaluation you can try me5-base model.
- Make a fork of MTEB and do necessary modification, including the documentation references for the task.
- Prepare 2 GITHUB pull requests for the databases, preliminary BEIR script given.
Future tasks:
- Prepare a machine translation system to create another slovak/multilingual evaluation task from English task.
Preparation (7.8.2024):
- Get familiar with [SentenceTransformer](https://sbert.net/) framework, study fundamental papers and write down notes.
- Get familiar with [MTEB](https://github.com/embeddings-benchmark/mteb) evaluation framework.
- Prepare a working environment on Google Colab or on school server or Anaconda.
- Get familiar with [existing finetuning scripts](https://git.kemt.fei.tuke.sk/dano/slovakretrieval).

View File

@ -1,104 +0,0 @@
---
title: Sevval Bulburu
published: true
taxonomy:
category: [iaeste]
tag: [hatespeech,nlp]
author: Daniel Hladek
---
Sevval Bulburu
IAESTE Intern Summer 2023, two months
Goal: Help with the [Hate Speech Project](/topics/hatespeech)
Meeting 12.10.2023
[Github Repo with results](https://github.com/sevvalbulburu/Hate_Speech_Detection_Slovak)
State:
- Proposed and tried extra layers above BERT model to make a classifier in seriees of experiments. There is a single sigmoid neuron on the output.
- Manually adjusted the slovak HS dataset. Slovak dataset is not balanced. Tried some methods for "balancing" the dataset. By google translate - augmentation. Other samples are "generated" by translation into random langauge and translating back. This creates "paraphrases" of the original samples. It helps.
- Tried SMOTE upsampling, it did not work.
- Is date and user name an important feature?
- tried some grid search for hyperparameter of the neural network - learning rate, dropout, epoch size, batch size. Batch size 64 no good.
- Tried multilingal models for Slovak dataset (cnerg), result are not good.
Tasks:
- Please send me your work report. Please upload your scripts and notebooks on git and send me a link. git is git.kemt.fei.tuke.sk or github. Prepare some short comment about scripts.You can also upload the slovak datasetthere is some work done on it.
Ideas for a paper:
Possible names:
- "Data set balancing for Multilingual Hate Speech Detection"
- "BERT embeddings for HS Detection in Low Resource Languages" (Turkish and Slovak).
(Possible) Tasks for paper:
- Create a shared draft document, e.g. on Overleaf or Google Doc
- Write a good introduction and literature overview (Zuzka).
- Try 2 or 3 class Softmax Layer for neural network.
- Change the dataset for 3 class classification.
- Prepare classifier for Slovak, English, Turkish and for multiple BERT models. Try to use multilingual BERT model for baseline embeddings.
- Measure the effect of balancing the dataset by generation of additional examples.
- Summarize experiments in tables.
Meeting 5.9.2023
State:
- Proposed own Flask application
- Created Django application with data model https://github.com/hladek/hate-annot
Tasks:
Meeting 22.8.2023
State:
- Familiar with Python, Anaconda, Tensorflow, AI projects
- created account at idoc.fei.tuke.sk and installed anaconda.
- Continue with previous open tasks.
- Read a website and pick a dataset from https://hatespeechdata.com/
- Evaluate (calculate p r f1) existing multilingual model. E.G. https://huggingface.co/Andrazp/multilingual-hate-speech-robacofi with any data
- Get familiar with Django.
Notes:
- ssh bulbur@idoc.fei.tuke.sk
- nvidia-smi command to check status of GPU.
- Use WinSCP to Copy Files. Use anaconda virtual env to create and activate a new python virtual environment. Use Visual Studio Code Remote to delvelop on your computer and run on remote computer (idoc.fei.tuke.sk). Use the same credentials for idoc server.
- Use WSL2 to have local linux just to play.
Tasks:
- [ ] Get familiar with the task of Hate speech detection. Find out how can we use Transformer neural networks to detect and categorize hate speech in internet comments created by random people.
- [ ] Get familiar with the basic tools: Huggingface Transformers, Learn how to use https://huggingface.co/Andrazp/multilingual-hate-speech-robacofi in Python script. Learn something about Transformer neural networks.
- [x] get familiar with Prodi.gy annotation tool.
- [-] Set up web-based annotation environment for students (open, cooperation with [Vladimir Ferko](/students/2021/vladimir_ferko) ).
Ideas for annotation tools:
- https://github.com/UniversalDataTool/universal-data-tool
- https://www.johnsnowlabs.com/top-6-text-annotation-tools/
- https://app.labelbox.com/
- https://github.com/recogito/recogito-js
- https://github.com/topics/text-annotation?l=javascript
Future tasks (to be decided):
- Translate existing English dataset into Slovak. Use OPUS English Slovak Marian NMT model. Train Slovak munolingual model.
- Prepare existing Slovak Twitter dataaset, train evaluate a model.

View File

@ -11,63 +11,13 @@ Rok začiatku štúdia: 2016
Repozitár so [zdrojovými kódmi](https://git.kemt.fei.tuke.sk/dl874wn/dp2021) Repozitár so [zdrojovými kódmi](https://git.kemt.fei.tuke.sk/dl874wn/dp2021)
Názov: Obnovenie interpunkcie pomocou hlbokých neurónových sietí
1. Vypracujte prehľad metód na obnovenie interpunkcie pomocou neurónových sietí.
2. Vyberte vhodnú metódu obnovenia interpunkcie pomocou neurónových sietí.
3. Pripravte množinu dát na trénovanie neurónovej siete, navrhnite a vykonajte sadu experimentov s rôznymi parametrami.
4. Vyhodnoťte experimenty a navrhnite možné zlepšenia.
## Diplomový projekt 2 2020 ## Diplomový projekt 2 2020
Stretnutie 25.1.2021
Stav:
- Vypracovaný report experimentov
- Prezentácia
Do ďalšieho stretnutia:
- Dopísať časť kde opíšete Vašu metódu
- Rozšíriť teoretickú časť - zistite a napíšte čo je Transformer, BERT, RNN a Adversarial (kontradiktórne učenie) learning.
Virtuálne stretnutie 20.11.2020
Stav:
- Urobené úlohy z ďalšieho stretnutia
- Práca na písomnej časti, ešte treba spracovať experimenty.
Do ďalšieho stretnutia:
- Finalizovať text.
Virtuálne stretnutie 6.11.2020
Stav:
- Vypracovaná tabuľka s 5 experimentami.
- vytvorený repozitár.
Na ďalšie stretnutie:
- nahrať kódy na repozitár.
- závislosťi (názvy balíčkov) poznačte do súboru requirements.txt.
- Prepracujte experiment tak aby akceptoval argumenty z príkazového riadka. (sys.argv)
- K experimentom zapísať skript na spustenie. V skripte by mali byť parametre s ktorými ste spustili experiment.
- dopracujte report.
- do teorie urobte prehľad metód punctuation restoration a opis Vašej metódy.
Virtuálne stretnutie 25.9.2020 Virtuálne stretnutie 25.9.2020
Urobené: Urobené:
- skript pre vyhodnotenie experimentov. - skript pre vyhodnotenie experimentov
Úlohy do ďalšieho stretnutia: Úlohy do ďalšieho stretnutia:
@ -87,6 +37,12 @@ Urobené:
- 3. Vykonať sadu experimentov na overenie presnosti klasifikácie zvolenej neurónovej siete - 3. Vykonať sadu experimentov na overenie presnosti klasifikácie zvolenej neurónovej siete
Názov: Obnovenie interpunkcie pomocou neurónových sietí
1. Vypracujte prehľad metód na obnovenie interpunkcie pomocou neurónových sietí.
2. Vyberte vhodnú metódu obnovenia interpunkcie pomocou neurónových sietí.
3. Pripravte množinu dát na trénovanie neurónovej siete, navrhnite a vykonajte sadu experimentov s rôznymi parametrami.
4. Vyhodnoťte experimenty a navrhnite možné zlepšenia.
## Zápis o činnosti ## Zápis o činnosti

View File

@ -1,11 +1,4 @@
---
title: Novinky v oblasti “Punctuation Restoration”
published: true
taxonomy:
category: [tp2020]
tag: [interpunction,nlp]
author: Dárius Lindvai
---
# Novinky v oblasti “Punctuation Restoration” # Novinky v oblasti “Punctuation Restoration”
Keďže interpunkcia a veľké písmená v slovách nemajú vplyv na výslovnosť slov, sú z výstupu **ASR** (*automatic speech recognition = automatické rozpoznávanie reči*) odstraňované, výsledkom čoho sú iba sekvencie slov alebo písmen. Systémy vykonávajúce doplňovanie **interpunkčných znamienok** a veľkých písmen sú potrebné najmä preto, lebo tieto výstupy bez interpunkcie a veľkých písmen väčšinou pre ľudí nie sú zrozumiteľné (v textovej forme). Interpunkcia a veľké písmená sú taktiež dôležité prvky aj pri **NLP** (*natural language processing = spracovanie prirodzeného jazyka*). Keďže interpunkcia a veľké písmená v slovách nemajú vplyv na výslovnosť slov, sú z výstupu **ASR** (*automatic speech recognition = automatické rozpoznávanie reči*) odstraňované, výsledkom čoho sú iba sekvencie slov alebo písmen. Systémy vykonávajúce doplňovanie **interpunkčných znamienok** a veľkých písmen sú potrebné najmä preto, lebo tieto výstupy bez interpunkcie a veľkých písmen väčšinou pre ľudí nie sú zrozumiteľné (v textovej forme). Interpunkcia a veľké písmená sú taktiež dôležité prvky aj pri **NLP** (*natural language processing = spracovanie prirodzeného jazyka*).

View File

@ -1,11 +1,4 @@
---
title: PYTORCH - LSTM TUTORIÁL
published: true
taxonomy:
category: [tp2020]
tag: [python,lstm,nn,nlp,pytorch,anaconda]
author: Dárius Lindvai
---
# PYTORCH - LSTM TUTORIÁL # PYTORCH - LSTM TUTORIÁL
### Čo je to Pytorch? ### Čo je to Pytorch?

View File

@ -2,7 +2,7 @@
title: Dominik Nagy title: Dominik Nagy
published: true published: true
taxonomy: taxonomy:
category: [dp2022,bp2019] category: [dp2021,bp2019]
tag: [translation,nlp] tag: [translation,nlp]
author: Daniel Hladek author: Daniel Hladek
--- ---
@ -10,99 +10,8 @@ taxonomy:
*Rok začiatku štúdia*: 2016 *Rok začiatku štúdia*: 2016
## Diplomová práca 2022
[GIT repozitár](https://git.kemt.fei.tuke.sk/dn161mb/dp2022)
*Názov diplomovej práce*: Neurónový strojový preklad pomocou knižnice Fairseq
*Meno vedúceho*: Ing. Daniel Hládek, PhD.
*Zadanie diplomovej práce*:
1. Vypracujte teoretický prehľad metód neurónového strojového prekladu.
2. Podrobne opíšte vybranú metódu neurónového strojového prekladu.
3. Natrénujte viacero modelov pre strojový preklad pomocou nástroja Fairseq a vyhodnoťte ich.
4. Na základe výsledkov experimentov navrhnite zlepšenia.
Stretnutie 11.1.2022
- Urobené všetky úlohy z minulého stretnutia, okrem textu a gitu.
- Natrénované modely fairseq pre obojsmerný preklad angličtina slovenčina.
Úlohy:
- dajte všetky skripty do repozitára dp2022
- Napíšte si osnovu diplomovej práce.
- Vypracujte draft (hrubý text) diplomovej práce.
- V texte DP sumarizujte vykonané experimenty.
- Pripravte si prezentáciu na obhajoby.
- Skontrolovať či sa robí tokenizácia správne pri vyhodnotení.
Zásobník úloh:
- Pripravte článok (pre vedúceho).
- Urobte experiment s architektúrou MBART. Porovnajte Vaše výsledky s výsledkami v článku MBART (Liu et al. : Multilingual Denoising Pre-training for Neural Machine Translation).
Stretnutie 17.12.2021
Stav:
- rozbehané trénovanie na slovensko-anglickom (LinDat) paralelnom korpuse.
- model z angličtiny do slovenčiny.
- tokenizácia subword NMT.
- rozbehané trénovanie na GPU, bez anaconda.
Úlohy:
- [x] Cieľ je aby Vaše experimenty boli zopakovateľné. Pridajte všetky trénovacie skripty do git repozitára. Nepridávajte dáta. Pridajte skripty alebo návody na to ako pripraviť dáta.
- [x] Zostavte tabuľku kde zapíšete parametre trénovania a dosiahnuté výsledky.
- Napíšte prehľad aktuálnych metód strojového prekladu pomocou neurónových sietí kde prečítate viacero vedeckých článkov a ku každému uvediete názov a čo ste sa z neho dozvedeli. Vyhľadávajte kľúčové slovíčka: "Survey of neural machine translation". Chceme sa dozvedieť aj o transformeroch a neurónových jazykových modeloch.
- [x] vyskúšajte trénovanie aj s inými architektúrami. Ku každému trénovaniu si poznačte skript, výsledky a dajte to na git.
Zásobník úloh:
- [x] Výskúšajte preklad v opačnom smere.
- [x] Vyskúšanie inej metódy tokenizácie (BPE, sentencepiece, wordpiece - huggingface tokenizers).
Stretnutie 6.7.2021
Stav:
- Podarilo sa rozbehať setup pre trénovanie slovensko anglického prekladu na korpuse 10 viet pomocou fairseq.
Úlohy:
- Pokračujte v trénovaní na servri IDOC, použite skript na príápravu prostredia ktorý som Vám dal.
- Pripravte veľký slovensko-anglický paralelný korpus a natrénujte z neho model.
- Model vyhodnotťe pomocou metriky BLEU. Naštudujte si metriku BLEU.
## Príprava na Diplomový projekt 2 2021
Zásobník úloh:
- Využiť BERT model pri strojovom preklade zo slovenčiny
Stretnutie 17.2.2021
Stav:
- Plán ukončiť v roku 2022
- Vypracovaný tutoriál https://fairseq.readthedocs.io/en/latest/getting_started.html#training-a-new-model a https://fairseq.readthedocs.io/en/latest/tutorial_simple_lstm.html
Do ďalšieho stretnutia:
- Treba zlepšiť teoretickú prípravu a písanie.
- Pripraviť slovensko-anglický korpus do podoby vhodnej na trénovanie. Zistite v akej podobe je potrebné dáta mať.
- Natrénovať model fairseq pre strojový preklad zo slovenčiny.
- Zistite ako prebieha neurónový strojový preklad, čo je to neurónová sieť, čo je to enkóder, dekóder model a napíšte to vlastnými slovami. Napíšte aj odkiaľ ste to zistili.
- Prečítajte si https://arxiv.org/abs/1705.03122 a https://arxiv.org/abs/1611.02344 a napíšte čo ste sa dozvedeli.
## Diplomový projekt 2 ## Diplomový projekt 2
Virtuálne stretnutie 25.9. Virtuálne stretnutie 25.9.
- Možnosť predĺženia štúdia - Možnosť predĺženia štúdia
@ -150,6 +59,18 @@ Stretnutie 6.3.2020.
- Pozrieť článok [fairseq: A Fast, Extensible Toolkit for Sequence Modeling](https://www.aclweb.org/anthology/N19-4009/) - Pozrieť článok [fairseq: A Fast, Extensible Toolkit for Sequence Modeling](https://www.aclweb.org/anthology/N19-4009/)
- Pozrieť prístup a článok https://github.com/pytorch/fairseq/blob/master/examples/joint_alignment_translation/README.md - Pozrieť prístup a článok https://github.com/pytorch/fairseq/blob/master/examples/joint_alignment_translation/README.md
## Diplomová práca 2021
*Názov diplomovej práce*: Prepis postupností pomocou neurónových sietí pre strojový preklad
*Meno vedúceho*: Ing. Daniel Hládek, PhD.
*Zadanie diplomovej práce*:
1. Vypracujte teoretický prehľad metód "sequence to sequence".
2. Pripravte si dátovú množinu na trénovanie modelu sequence to sequence pre úlohu strojového prekladu.
3. Vyberte minimálne dva rôzne modely a porovnajte ich presnosť na vhodnej dátovej množine.
4. Na základe výsledkov experimentov navrhnite zlepšenia.
## Tímový projekt 2019 ## Tímový projekt 2019

View File

@ -1,11 +1,3 @@
---
title: Sequence-to-sequence
published: true
taxonomy:
category: [tp2020]
tag: [nn,seq2seq,translation,nlp]
author: Dominik Nagy
---
# Sequence-to-sequence # Sequence-to-sequence
Hlboké neurónové siete (Deep Neural Networks DNN) sú veľmi výkonné modely strojového Hlboké neurónové siete (Deep Neural Networks DNN) sú veľmi výkonné modely strojového

View File

@ -3,162 +3,22 @@ title: Jakub Maruniak
published: true published: true
taxonomy: taxonomy:
category: [dp2021,bp2019] category: [dp2021,bp2019]
tag: [spacy,ner,annotation,nlp] tag: [spacy,ner,nlp]
author: Daniel Hladek author: Daniel Hladek
--- ---
# Jakub Maruniak # Jakub Maruniak
*Rok začiatku štúdia*: 2016 *Rok začiatku štúdia*: 2016
*Návrh na názov DP*:
Anotácia a rozpoznávanie pomenovaných entít v slovenskom jazyku.
[CRZP](https://opac.crzp.sk/?fn=detailBiblioForm&sid=ECC3D3F0B3159C4F3217EC027BE4)
1. Vypracujte teoretický úvod, kde vysvetlíte čo je to rozpoznávanie pomenovaných entít a akými najnovšími metódami sa robí. Vysvetlite, ako pracuje klasifikátor pre rozpoznávanie pomenovaných entít v knižnici Spacy.
2. Pripravte postup na anotáciu textového korpusu pre systém Prodigy pre trénovanie modelu vo vybranej úlohe spracovania prirodzeného jazyka.
3. Vytvorte množinu textových dát v slovenskom jazyku vhodných na trénovanie štatistického modelu spracovania prirodzeného jazyka pomocou knižnice Spacy.
4. Natrénujte štatistický model pomocou knižnice Spacy a zistite, aký vplyv má veľkosť trénovacej množiny na presnosť klasifikátora.
*Spolupráca s projektom*:
- [Podpora slovenčiny v Spacy](/topics/spacy)
- [Anotácia textových dát](/topics/prodigy)
- [Rozpoznávanie pomenovaných entít](/topics/named-entity)
- [Spracovanie prir. jazyka](/topics/nlp)
- [Programovanie v jazyku Python](/topics/python)
## Diplomová práca 2021
Stretnutie 12.3.
Stav:
- Anotovanie dát, vykonané experimenty s trénovaním.
- Dosiahli sme presnosť cca 72 percent.
- Výsledky sú zhrnuté v tabuľke.
Úlohy:
- Píšte prácu.
- Uložte trénovacie skripty na GIT.
## Diplomový projekt 2 ## Diplomový projekt 2
Ciele:
- Anotovať sadu dát s použitím produkčnej anotačnej schémy, natrénovať a vyhodnotiť model.
Zásobník úloh: Zásobník úloh:
- Anotovať sadu dát s použitím produkčnej anotačnej schémy
- Použiť model na podporu anotácie - Použiť model na podporu anotácie
- Do konca ZS vytvoriť report vo forme článku. - Do konca ZS vytvoriť report vo forme článku.
Stretnutie 12.2.:
- Prebrali sme článok. Treba vyhodiť a popresúvať niektoré časti, inak v poriadku.
Do budúceho stretnutia:
- Vybrať vhodný časopis na publikovanie
- Využiť pri trénovaní ďalšie anotované dáta.
Stretnutie 20.1.
Preberanie draftu práce.
- Do článku vyradiť príliš všeobecné časti - napr. o strojovom učení.
- V úvode zadefinujte problém, pojmy a bežné spôsoby riešenia problému. Čo je korpus? Ako sa vyrába? Na čo a ako sa používa?
- V jadre predstavte Vaše riešenie. Ako vyzerá korpus? Ako ste ho urobili?
- Na konci definujte metodiku vyhodnotenia, vyhodnotte riešenie a navrhnite zlepšenia. Akú presnosť má model vytvorený s pomocou korpusu?
Virtuálne stretnutie 18.12.2021:
Stav:
- Vytvorené anotácie do databázy, cca 1700 jednotiek.
- Začiatok článku.
Virtuálne stretnutie 27.11.2020:
- Zatiaľ zostávame pri ručnej extrakcii dát z anotačnej schémy.
- Vypracovaná [tabuľka s experimentami](./dp2021/train_experiments)
- [Dáta a skripty](./dp2021/annotation)
Úlohy:
- Pracovať na ďalších anotáciách, zlepšiť presnosť modelu.
- Urobiť ďalšie experimenty.
- Začať pracovať na článku. Niečo podobné ako [Znalosti](https://hi.kkui.fei.tuke.sk/daz2019/), alebo [AEI](http://www.aei.tuke.sk/). šablóna ieee alebo llncs.
Stretnutie 20.1.2021
- Draft článku
Virtuálne stretnutie 13.11.2020:
- výsledky skopírované do [adresára](./dp2021)
- prečítané 3 články - porovnanie manuálnej anotácie a poloautomatickej.
- začiatok práce na skripte pre počítanie anotovaných entít, treba ešte vylepšiť aby vznikla tabuľka.
- anotačná schéma vyzerá byť v poriadku, niektoré články treba odfiltrovať (zoznam obrázkov, prázdna kategória, nadpis).
Úlohy do ďalšieho stretnutia:
- vytvoriť spôsob pre získanie dát z produkčnej anotačnej schémy. (pre vedúceho)
- vytvorte ďalšie anotácie.
- Spísať pravidlá pre validáciu. Aký výsledok anotácie je dobrý? Je potrebné anotované dáta skontrolovať?
- Vytvorte tabuľku kde uvediete presnosť modelu s rôznym množstvom anotovaných dát.
- Aký je najlepší spôsob vyhodnotnenia? Vytvoriť jednotnú testovaciu množinu. Druhý spôsob je použiť "10 fold cross validation" (Všetky dáta sa rozdelia na 10 častí, 9 sa využije pri trénovaní, 1 pri testovaní. Trénovanie sa opakuje 10 krát stále pre inú testovaciu množinu, výsledky sa spriemerujú).
Virtuálne stretnutie 30.10.2020:
Stav:
- Vylepšený návod
- Vyskúšaný export dát a trénovanie modelu z databázy. Problém pri trénovaní Spacy - iné výsledky ako cez Prodigy trénovanie
- Práca na textovej časti.
Úlohy do ďalšieho stretnutia:
- Vytvorte si repozitár s názvom dp2021 a tam pridajte skripty a poznámky.
- Pokračujte v písaní práce. Vykonajte prieskum literatúry "named entity corpora" aj poznámky.
- Vytvorte systém pre zistenie množstva a druhu anotovaných dát. Koľko článkov? Koľko entít jednotlivvých typov? Výsledná tabuľka pôjde do práce.
- Pripraviť sa na produkčné anotácie. Je schéma pripravená?
Virtuálne stretnutie 16.10.2020:
Stav:
- Spísané stručné poznámky k procesu anotácie
- Pokusne anotovaných niekoľko článkov
Úlohy na ďálšie stretnutie:
- Vylepšiť oficiálny návod na anotáciu NER https://zp.kemt.fei.tuke.sk/topics/named-entity/navod podľa poznámok a skúsenosti pri anotácii. Pridajte pravidlá pre učenie Accept a Reject článku. Ktorý paragraf je vhodný na anotáciu?
- Pripraviť skript na výber anotovaných dát z databázy a úpravu do podoby vhodnej pre trénovanie.
- Spísať pravidlá pre validáciu. Aký výsledok anotácie je dobrý? Je potrebné anotované dáta skontrolovať?
- Pokračujte v písaní DP.
Virtuálne stretnutie 9.10.2020:
Stav:
- Vyskúšané trénovanie modelu podľa repozitára spacy-skmodel
- Začiatok práce na textovej časti (vo Worde do šablóny ZP).
Úlophy na ďalšie stretnutie:
- Prečítajte si návod na anotáciu a navrhnite zlepšenia návodu. Cieľ je napísať presnú metodiku anotácie.
- Pokusne antujte niekoľko článkov, spíšte problémové miesta.
Stretnutie 25.9.2020:
Urobené: Urobené:
Oboznámenie sa procesom anotácie NER Oboznámenie sa procesom anotácie NER
@ -173,6 +33,7 @@ Návrhny na zlepšenie:
Je potrebné rozbehať produkčnú anotáciu NER Je potrebné rozbehať produkčnú anotáciu NER
## Diplomový projekt 1 2020 ## Diplomový projekt 1 2020
Výstupy (18.6.2020): Výstupy (18.6.2020):
@ -251,3 +112,21 @@ Návrh možných entít na anotáciu:
*Písomná práca*: [Rešerš](./timovy_projekt) *Písomná práca*: [Rešerš](./timovy_projekt)
*Návrh na zadanie DP*:
1. Vypracujte prehľad metód prípravy textových korpusov pomocou crowdsourcingu.
2. Pripravte postup na anotáciu textového korpusu pre systém Prodigy pre trénovanie modelu vo vybranej úlohe spracovania prirodzeného jazyka.
3. Vytvorte množinu textových dát v slovenskom jazyku vhodných na trénovanie štatistického modelu spracovania prirodzeného jazyka pomocou knižnice Spacy.
4. Natrénujte štatistický model pomocou knižnice Spacy a zistite, aký vplyv má veľkosť trénovacej množiny na presnosť klasifikátora.
*Návrh na názov DP*:
Anotácia textových dát v slovenskom jazyku pomocou metódy crowdsourcingu
*Spolupráca s projektom*:
- [Podpora slovenčiny v Spacy](/topics/spacy)
- [Anotácia textových dát](/topics/prodigy)
- [Rozpoznávanie pomenovaných entít](/topics/named-entity)
- [Spracovanie prir. jazyka](/topics/nlp)
- [Programovanie v jazyku Python](/topics/python)

View File

@ -1,40 +1 @@
## Diplomový projekt 2 2020 DP2021
Stav:
- aktualizácia anotačnej schémy (jedná sa o testovaciu schému s vlastnými dátami)
- vykonaných niekoľko anotácii, trénovanie v Prodigy - nízka presnosť = malé množstvo anotovaných dát. Trénovanie v spacy zatiaľ nefunguje.
- Štatistiky o množstve prijatých a odmietnutých anotácii získame z Prodigy: prodigy stats wikiart. Zatiaľ 156 anotácii (151 accept, 5 reject). Na získanie prehľadu o množstve anotácii jednotlivých entít potrebujeme vytvoriť skript.
- Prehľad literatúry Named Entity Corpus
- Budovanie korpusu pre NER automatické vytvorenie už anotovaného korpusu z Wiki pomocou DBpedia jedná sa o anglický korpus, ale možno spomenúť v porovnaní postupov
- Building a Massive Corpus for Named Entity Recognition using Free Open Data Sources - Daniel Specht Menezes, Pedro Savarese, Ruy L. Milidiú
- Porovnanie postupov pre anotáciu korpusu (z hľadiska presnosti aj času) - Manual, SemiManual
- Comparison of Annotating Methods for Named Entity Corpora - Kanako Komiya, Masaya Suzuki
- Čo je korpus, vývojový cyklus, analýza korpusu (Už využitá literatúra cyklus MATTER)
- Natural Language Annotation for Machine Learning James Pustejovsky, Amber Stubbs
Aktualizácia 09.11.2020:
- Vyriešený problém, kedy nefungovalo trénovanie v spacy
- Vykonaná testovacia anotácia cca 500 viet. Výsledky trénovania pri 20 iteráciách: F-Score 47% (rovnaké výsledky pri trénovaní v Spacy aj Prodigy)
- Štatistika o počte jednotlivých entít: skript count.py
## Diplomový projekt 1 2020
- vytvorenie a spustenie docker kontajneru
```
./build-docker.sh
docker run -it -p 8080:8080 -v ${PWD}:/work prodigy bash
# (v mojom prípade:)
winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/annotation/work prodigy bash
```
### Spustenie anotačnej schémy
- `dataminer.csv` články stiahnuté z wiki
- `cd ner`
- `./01_text_to_sent.sh` spustenie skriptu *text_to_sent.py*, ktorý rozdelí články na jednotlivé vety
- `./02_ner_correct.sh` spustenie anotačného procesu pre NER s návrhmi od modelu
- `./03_ner_export.sh` exportovanie anotovaných dát vo formáte jsonl potrebnom pre spracovanie vo spacy

View File

@ -1,16 +1,17 @@
# > docker run -it -p 8080:8080 -v ${PWD}:/work prodigy bash # > docker run -it -p 8080:8080 -v ${PWD}:/work prodigy bash
# > winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/annotation-master/annotation/work prodigy bash # > winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/annotation/work prodigy bash
FROM python:3.8 FROM python:3.8
RUN mkdir /prodigy RUN mkdir /prodigy
WORKDIR /prodigy WORKDIR /prodigy
COPY ./prodigy-1.9.6-cp36.cp37.cp38-cp36m.cp37m.cp38-linux_x86_64.whl /prodigy COPY ./prodigy-1.9.6-cp36.cp37.cp38-cp36m.cp37m.cp38-linux_x86_64.whl /prodigy
RUN mkdir /work RUN mkdir /work
COPY ./ner /work/ner COPY ./ner /work
RUN pip install uvicorn==0.11.5 prodigy-1.9.6-cp36.cp37.cp38-cp36m.cp37m.cp38-linux_x86_64.whl RUN pip install prodigy-1.9.6-cp36.cp37.cp38-cp36m.cp37m.cp38-linux_x86_64.whl
RUN pip install https://files.kemt.fei.tuke.sk/models/spacy/sk_sk1-0.0.1.tar.gz RUN pip install https://files.kemt.fei.tuke.sk/models/spacy/sk_sk1-0.0.1.tar.gz
RUN pip install nltk RUN pip install nltk
EXPOSE 8080 EXPOSE 8080
ENV PRODIGY_HOME /work ENV PRODIGY_HOME /work
ENV PRODIGY_HOST 0.0.0.0 ENV PRODIGY_HOST 0.0.0.0
WORKDIR /work WORKDIR /work

View File

@ -1,11 +1,13 @@
## Diplomový projekt 2 2020 ## Diplomový projekt 1 2020
- vytvorenie a spustenie docker kontajneru - vytvorenie a spustenie docker kontajneru
``` ```
./build-docker.sh ./build-docker.sh
winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/annotation-master/annotation/work prodigy bash docker run -it -p 8080:8080 -v ${PWD}:/work prodigy bash
# (v mojom prípade:)
winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/annotation/work prodigy bash
``` ```
@ -15,33 +17,5 @@ winpty docker run --name prodigy -it -p 8080:8080 -v C://Users/jakub/Desktop/ann
- `dataminer.csv` články stiahnuté z wiki - `dataminer.csv` články stiahnuté z wiki
- `cd ner` - `cd ner`
- `./01_text_to_sent.sh` spustenie skriptu *text_to_sent.py*, ktorý rozdelí články na jednotlivé vety - `./01_text_to_sent.sh` spustenie skriptu *text_to_sent.py*, ktorý rozdelí články na jednotlivé vety
- `./02_ner_manual.sh` spustenie manuálneho anotačného procesu pre NER - `./02_ner_correct.sh` spustenie anotačného procesu pre NER s návrhmi od modelu
- `./03_export.sh` exportovanie anotovaných dát vo formáte json potrebnom pre spracovanie vo spacy. Možnosť rozdelenia na trénovacie (70%) a testovacie dáta (30%) (--eval-split 0.3). - `./03_ner_export.sh` exportovanie anotovaných dát vo formáte jsonl potrebnom pre spracovanie vo spacy
Pozn. aby --eval-split fungoval správne, je potrebné v inštalácii prodigy (cestu zistíme pomocou `prodigy stats`) v súbore `recipes/train.py` upraviť funkciu `data_to_spacy` (mal by byť riadok 327). V novej verzii by to malo byť opravené. Do riadku treba pridať parameter eval_split.
`json_data, eval_data, split = train_eval_split(json_data, eval_split)`
### Anotované databázy
- `./ner/skner/sknerv4.jsonl` - Aktuálna anotovaná databáza z https://skner.tukekemt.xyz/ (Celkovo cca 5000 článkov)
- `./ner/wikiart/wikiart2.jsonl` - Vlastná databáza, články rozdelené na vety (Celkovo cca 1300 viet)
- Presná štatistika o databázach bude doplnená
### Štatistika o anotovaných dátach
- `prodigy stats wikiart` - informácie o počte prijatých a odmietnutých článkov pre konkrétny dataset v prodigy
### Vizualizácia anotovaných dát
- `streamlit run visualizer.py visualize ./dataset.jsonl` - Vypíše anotácie zo zvolenej databázy na lokálnej adrese http://192.168.1.26:8501
### Trénovanie modelu
Založené na: https://git.kemt.fei.tuke.sk/dano/spacy-skmodel
- Na trénovanie NER využitá vstavaná funkcia spacy train
- Testované aj s custom skriptom na trénovanie - `custom_train.py` - približne rovnaké výsledky, neporovnateľne dlhší čas trénovania
### Scripts
`python scripts.py [command] [arguments]`
| Príkaz | Popis | Argumenty |
| ---------- | ------------------ | ------------------- |
| `count` | Vypíše štatistiky o databáze vo formáte JSONL z Prodigy.| dataset_path|
| `delete_annot` | Vytvorí samostatnú databázu s anotáciami iba od zvoleného anotátora.| annotator, dataset_path, new_dataset_path|
| `modelinfo`| Vypíše informácie o natrénovanom modeli (Precision, Recall a F-skóre), zároveň aj o jednotlivých entitách. | - |

View File

@ -1,152 +0,0 @@
"""Scripts used for training and evaluation of NER models
Usage example:
$ python custom_train.py train ./model ./train.jsonl ./eval.jsonl -o ./output_dir -n 15
Requirements:
spacy>=2.2.3
https://github.com/explosion/projects/tree/master/ner-drugs
"""
import spacy
from spacy.cli.train import _load_pretrained_tok2vec
from timeit import default_timer as timer
from pathlib import Path
import srsly
from wasabi import msg
import random
import plac
import sys
import tqdm
def format_data(data):
result = []
labels = set()
for eg in data:
if eg["answer"] != "accept":
continue
ents = [(s["start"], s["end"], s["label"]) for s in eg.get("spans", [])]
labels.update([ent[2] for ent in ents])
result.append((eg["text"], {"entities": ents}))
return result, labels
@plac.annotations(
model=("The base model to load or blank:lang", "positional", None, str),
train_path=("The training data (Prodigy JSONL)", "positional", None, str),
eval_path=("The evaluation data (Prodigy JSONL)", "positional", None, str),
n_iter=("Number of iterations", "option", "n", int),
output=("Optional output directory", "option", "o", str),
tok2vec=("Pretrained tok2vec weights to initialize model", "option", "t2v", str),
)
def train_model(
model, train_path, eval_path, n_iter=10, output=None, tok2vec=None,
):
"""
Train a model from Prodigy annotations and optionally save out the best
model to disk.
"""
spacy.util.fix_random_seed(0)
with msg.loading(f"Loading '{model}'..."):
if model.startswith("blank:"):
nlp = spacy.blank(model.replace("blank:", ""))
else:
nlp = spacy.load(model)
msg.good(f"Loaded model '{model}'")
train_data, labels = format_data(srsly.read_jsonl(train_path))
eval_data, _ = format_data(srsly.read_jsonl(eval_path))
ner = nlp.create_pipe("ner")
for label in labels:
ner.add_label(label)
nlp.add_pipe(ner)
t2v_cfg = {
"embed_rows": 10000,
"token_vector_width": 128,
"conv_depth": 8,
"nr_feature_tokens": 3,
}
optimizer = nlp.begin_training(component_cfg={"ner": t2v_cfg} if tok2vec else {})
if tok2vec:
_load_pretrained_tok2vec(nlp, Path(tok2vec))
batch_size = spacy.util.compounding(1.0, 32.0, 1.001)
best_acc = 0
best_model = None
row_widths = (2, 8, 8, 8, 8)
msg.row(("#", "L", "P", "R", "F"), widths=row_widths)
for i in range(n_iter):
random.shuffle(train_data)
losses = {}
data = tqdm.tqdm(train_data, leave=False)
for batch in spacy.util.minibatch(data, size=batch_size):
texts, annots = zip(*batch)
nlp.update(texts, annots, drop=0.2, losses=losses)
with nlp.use_params(optimizer.averages):
sc = nlp.evaluate(eval_data)
if sc.ents_f > best_acc:
best_acc = sc.ents_f
if output:
best_model = nlp.to_bytes()
acc = (f"{sc.ents_p:.3f}", f"{sc.ents_r:.3f}", f"{sc.ents_f:.3f}")
msg.row((i + 1, f"{losses['ner']:.2f}", *acc), widths=row_widths)
msg.text(f"Best F-Score: {best_acc:.3f}")
if output and best_model:
with msg.loading("Saving model..."):
nlp.from_bytes(best_model).to_disk(output)
msg.good("Saved model", output)
@plac.annotations(
model=("The model to evaluate", "positional", None, str),
eval_path=("The evaluation data (Prodigy JSONL)", "positional", None, str),
)
def evaluate_model(model, eval_path):
"""
Evaluate a trained model on Prodigy annotations and print the accuracy.
"""
with msg.loading(f"Loading model '{model}'..."):
nlp = spacy.load(model)
data, _ = format_data(srsly.read_jsonl(eval_path))
sc = nlp.evaluate(data)
result = [
("Precision", f"{sc.ents_p:.3f}"),
("Recall", f"{sc.ents_r:.3f}"),
("F-Score", f"{sc.ents_f:.3f}"),
]
msg.table(result)
@plac.annotations(
model=("The model to evaluate", "positional", None, str),
data=("Raw data as JSONL", "positional", None, str),
)
def wps(model, data):
"""
Measure the processing speed in words per second. It's recommended to
use a larger corpus of raw text here (e.g. a few million words).
"""
with msg.loading(f"Loading model '{model}'..."):
nlp = spacy.load(model)
texts = (eg["text"] for eg in srsly.read_jsonl(data))
n_docs = 0
n_words = 0
start_time = timer()
for doc in nlp.pipe(texts):
n_docs += 1
n_words += len(doc)
end_time = timer()
wps = int(n_words / (end_time - start_time))
result = [
("Docs", f"{n_docs:,}"),
("Words", f"{n_words:,}"),
("Words/s", f"{wps:,}"),
]
msg.table(result, widths=(7, 12), aligns=("l", "r"))
if __name__ == "__main__":
opts = {"train": train_model, "evaluate": evaluate_model, "wps": wps}
cmd = sys.argv.pop(1)
if cmd not in opts:
msg.fail(f"Unknown command: {cmd}", f"Available: {', '.join(opts)}", exits=1)
try:
plac.call(opts[cmd])
except KeyboardInterrupt:
msg.warn("Stopped.", exits=1)

View File

@ -0,0 +1,3 @@
prodigy ner.correct wikiart sk_sk1 ./textfile.csv --label OSOBA,MIESTO,ORGANIZACIA,PRODUKT

View File

@ -1,2 +0,0 @@
prodigy ner.manual wikiart sk_sk1 ./textfile.csv --label PER,LOC,ORG,MISC

View File

@ -1 +0,0 @@
prodigy data-to-spacy ./train.json ./eval.json --lang sk --ner wikiart --eval-split 0.3

View File

@ -0,0 +1 @@
prodigy db-out wikiart > ./annotations.jsonl

View File

@ -1,160 +0,0 @@
"""
Usage example:
$ python scripts.py delete_annot jakub.maruniak ./dataset.jsonl ./new_dataset.jsonl
To see available commands:
$ python scripts.py help
To see available arguments:
$ python scripts.py [command] --help
"""
import spacy
import srsly
from wasabi import msg
import plac
import sys
import re
import itertools
@plac.annotations(
dataset_path=("Path to dataset (Prodigy JSONL format)", "positional", None, str),
)
def count(
dataset_path
):
"""
Print statistics about Prodigy JSONL dataset.
Prints number of accepted, rejected and ignored articles.
Prints number of annotations of each entity type.
Prints how much annotations were made by each annotator.
"""
# load data
# filename = 'ner/skner/sknerv4spans.jsonl'
file = open(sys.argv[1], 'rt', encoding='utf-8')
text = file.read()
# count articles
countAccept = text.count('accept')
countReject = text.count('reject')
countSkip = text.count('ignore')
countSpans = text.count('tokens')
# count entities
countPER = text.count('PER')
countLOC = text.count('LOC')
countORG = text.count('ORG')
countMISC = text.count('MISC')
underline = '\033[04m'
reset = '\033[0m'
red = '\033[31m'
green='\033[32m'
gray='\033[37m'
# table v1
#from lib import TableIt
#table1 = [
# ['Prijatých', countAccept],
# ['Zamietnutých', countReject],
# ['Preskočených', countSkip],
# ['------------', '------------'],
# ['Spolu', countSpans]
#]
#
#table = [
# ['Entita', 'Počet'],
# ['PER', countPER],
# ['LOC', countLOC],
# ['ORG', countORG],
# ['MISC', countMISC]
#]
#print('\nPočet anotovaných článkov:')
#TableIt.printTable(table1)
#print('\nPočet jednotlivých entít:')
#TableIt.printTable(table, useFieldNames=True, color=(26, 156, 171))
# table v2
print(underline + '\nPočet anotovaných článkov:' + reset)
print(green + "%-15s %-20s" %("Prijatých", countAccept) + reset)
print(red + "%-15s %-15s" %("Zamietnutých", countReject) + reset)
print(gray + "%-15s %-15s" %("Preskočených", countSkip) + reset)
print("%-15s" %("---------------------"))
print("%-15s %-15s" %("Spolu", countSpans))
print(underline + '\nPočet jednotlivých entít:' + reset)
print("%-10s %-10s" %("Entita:", "Počet:"))
print("%-10s" %("----------------"))
print("%-10s %-10s" %("PER", countPER))
print("%-10s %-10s" %("LOC", countLOC))
print("%-10s %-10s" %("ORG", countORG))
print("%-10s %-10s" %("MISC", countMISC))
# kto anotoval koľko?
frequency = {}
#Open the sample text file in read mode.
#document_text = open('sample.txt', 'r')
#convert the string of the document in lowercase and assign it to text_string variable.
#text = document_text.read().lower()
regex1 = '"_session_id":(.*?),'
pattern = re.findall(regex1, text)
for word in pattern:
count = frequency.get(word,0)
frequency[word] = count + 1
frequency_list = frequency.keys()
print(underline + '\nKto anotoval koľko článkov?' + reset)
for words in frequency_list:
print(words, frequency[words])
@plac.annotations(
annotator=("Keep annotations from this annotator (email address or nickname)", "positional", None, str),
dataset_path=("Path to dataset (Prodigy JSONL format)", "positional", None, str),
new_dataset_path=("Path to save new dataset(Prodigy JSONL format)", "positional", None, str),
)
def delete_annot(
annotator, dataset_path, new_dataset_path
):
"""
Load Prodigy JSONL dataset,
and keep annotations only from one annotator.
"""
file1 = open(sys.argv[2], 'r', encoding='utf-8')
file2 = open(sys.argv[3],'w', encoding='utf-8')
for line in file1.readlines():
x = re.findall(sys.argv[1], line)
if x:
print(line)
file2.write(line)
file1.close()
file2.close()
def modelinfo(
):
"""
Print information about trained model (Precision, Recall and F-Score)
"""
with open('build/train/nerposparser/model-best/meta.json', 'rt') as f:
for line in itertools.islice(f, 31, 54):
print(line, end =" ")
def helpme(
):
print("Available commands:",
"\ncount - Print statistics about Prodigy JSONL dataset",
"\ndelete_annot - Create dataset with annotations from only specific annotator",
"\nmodelinfo - Prints informations about trained model (Precision, Recall and F-Score)")
if __name__ == "__main__":
opts = {"count": count,
"delete_annot": delete_annot,
"modelinfo": modelinfo,
"help": helpme}
cmd = sys.argv.pop(1)
if cmd not in opts:
msg.fail(f"Unknown command: {cmd}", f"Available: {', '.join(opts)}", exits=1)
try:
plac.call(opts[cmd])
except KeyboardInterrupt:
msg.warn("Stopped.", exits=1)

View File

@ -1,24 +0,0 @@
set -e
OUTDIR=build/train/output
TRAINDIR=build/train
# Delete old training results
rm -r $TRAINDIR
mkdir -p $TRAINDIR
mkdir -p $OUTDIR
mkdir -p dist
# Delete old training results
rm -rf $OUTDIR/*
# Train dependency and POS
spacy train sk $OUTDIR ./build/input/slovak-treebank ./build/input/ud-artificial-gapping --n-iter 15 -p tagger,parser
rm -rf $TRAINDIR/posparser
mv $OUTDIR/model-best $TRAINDIR/posparser
# Train NER
# custom script for training, but it takes too long... input is JSONL file (db from Prodigy)
# python custom_train.py train ./build/train/posparser ./train.jsonl ./eval.jsonl -o ./build/train/nerposparser -n 15
spacy train sk $TRAINDIR/nerposparser ./ner/experiments/34sknerfull.json ./ner/experiments/34wikiartfull.json --n-iter 15 -p ner
# Package model
spacy package $TRAINDIR/nerposparser dist --meta-path ./meta.json --force
cd dist/sk_sk1-0.2.0
python ./setup.py sdist --dist-dir ../

View File

@ -1,80 +0,0 @@
"""
Visualize the data with Streamlit and spaCy.
https://github.com/explosion/projects/blob/master/ner-drugs/streamlit_visualizer.py
Usage example:
$ streamlit run visualizer.py visualize ./dataset.jsonl
"""
import streamlit as st
from spacy import displacy
import srsly
import sys
import plac
from wasabi import msg
@plac.annotations(
dataset_path=("Path to dataset (Prodigy JSONL format)", "positional", None, str),
)
def visualize(
dataset_path
):
FILES = [sys.argv[1]]
MISC = "MISC"
HTML_WRAPPER = "<div style='border-bottom: 1px solid #ccc; padding: 20px 0'>{}</div>"
HTML_WRAPPER1 = "<div style='border-bottom: 2px solid #000; padding: 0 0 20px 0'>{}</div>"
SETTINGS = {"style": "ent", "manual": True, "options": {"colors": {MISC: "#d1bcff"}}}
@st.cache(allow_output_mutation=True)
def load_data(filepath):
return list(srsly.read_jsonl(filepath))
st.sidebar.title("Data visualizer")
st.sidebar.markdown(
"Visualize the annotations using [displaCy](https://spacy.io/usage/visualizers) "
"and view stats about the datasets."
)
data_file = st.sidebar.selectbox("Dataset", FILES)
data = load_data(data_file)
n_no_ents = 0
n_total_ents = 0
accepted = 0
rejected = 0
st.header(f"Dataset: {data_file} ({len(data)})")
st.markdown(HTML_WRAPPER1.format("Visualize only accepted examples and their annotations."), unsafe_allow_html=True)
for eg in data:
if eg["answer"] == "accept":
accepted += 1
if eg["answer"] != "accept":
rejected += 1
continue
row = {"text": eg["text"], "ents": eg.get("spans", [])}
answer = {"answer": eg.get("answer", [])}
n_total_ents += len(row["ents"])
if not row["ents"]:
n_no_ents += 1
html = displacy.render(row, **SETTINGS).replace("\n\n", "\n")
st.markdown(HTML_WRAPPER.format(html), unsafe_allow_html=True)
st.sidebar.markdown(
f"""
| `{data_file}` | |
| --- | ---: |
| Total examples | {len(data):,} |
| Accepted examples | {accepted:,} |
| Rejected examples | {rejected:,} |
| Total entities | {n_total_ents:,} |
| Examples with no entities | {n_no_ents:,} |
""", unsafe_allow_html=True
)
if __name__ == "__main__":
opts = {"visualize": visualize}
cmd = sys.argv.pop(1)
if cmd not in opts:
msg.fail(f"Unknown command: {cmd}", f"Available: {', '.join(opts)}", exits=1)
try:
plac.call(opts[cmd])
except KeyboardInterrupt:
msg.warn("Stopped.", exits=1)

View File

@ -1,137 +0,0 @@
# Trénovacie experimenty
Do tohto súboru sa budú postupne zapisovať štatistiky a poznámky ku vykonaným trénovacím experimentom.
V rámci experimentu pracujeme s dvomi databázami:
- Wikiart - vlastná anotovaná databáza článkov. Každý článok = 1 veta.
- Skner - anotovaná databáza z https://skner.tukekemt.xyz/ . Počet viet v jednotlivých článkoch je rôzny.
### Trénovanie Wikiart
1. Experiment - trénovanie modelu pomocou databázy Wikiart
![1.Wikiart](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/jakub_maruniak/dp2021/img/1wikiart.PNG)
Celkovo 501 článkov.
351 použitých na trénovanie, 150 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 55,55%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|85|41,66%|
|LOC|240|65,51%|
|ORG|30|0,0%|
|MISC|42|44,44%|
### Trénovanie Skner
2. Experiment - trénovanie modelu pomocou databázy skner.
![2.Skner](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/jakub_maruniak/dp2021/img/2skner.PNG)
1.
Celkovo 488 článkov.
342 použitých na trénovanie, 146 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 60,99%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|376|60,07%|
|LOC|885|67,39%|
|ORG|149|42,10%|
|MISC|80|8,69%|
2.
Celkovo 976 článkov.
684 použitých na trénovanie, 292 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 62,9%%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|684|60,68%|
|LOC|1417|70,45%|
|ORG|280|40,87%|
|MISC|416|43,08%|
3.
Celkovo 2696 článkov.
1871 použitých na trénovanie, 801 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 70.33%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|1886|71,08%|
|LOC|3678|79,01%|
|ORG|820|48,81%|
|MISC|1171|52,38%|
### 3. Experiment
3. Experiment - na natrénovanie modelu je využitá kompletná databáza Skner. Na testovanie modelu je využitá databáza Wikiart.
1.verzia databázy skner - 488 článkov
15 iterácii trénovania.
F-skóre natrénovaného modelu: 49,67%
| Entita | F-skóre |
|--|--|
|PER|39,08%|
|LOC|60,99%|
|ORG|27,77%|
|MISC|4,44%|
2.verzia databázy skner - 976 článkov
15 iterácii trénovania.
F-skóre natrénovaného modelu: 51,08%
| Entita | F-skóre |
|--|--|
|PER|38,22%|
|LOC|60,83%|
|ORG|33,33%|
|MISC|30,30%|
3.verzia databázy skner - 2672 článkov
15 iterácii trénovania.
F-skóre natrénovaného modelu: 56,26%
| Entita | F-skóre |
|--|--|
|PER|45,35%|
|LOC|67,25%|
|ORG|31,58%|
|MISC|39,47%|
### 4. Experiment
4. Experiment - Obe databázy sme zlúčili.
![4.Merged](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/jakub_maruniak/dp2021/img/4merged.PNG)
1. verzia
Celkovo 989 článkov.
693 použitých na trénovanie, 296 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 61,90%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|461|54,00%|
|LOC|1125|71,87%|
|ORG|179|42,00%|
|MISC|122|18,18%|
2. verzia
Celkovo 3197 článkov.
2222 použitých na trénovanie, 951 na testovanie.
15 iterácii trénovania.
F-skóre natrénovaného modelu: 70,48%
| Entita | Počet anotácii | F-skóre |
|--|--|--|
|PER|1971|69,18%|
|LOC|3918|80,52%|
|ORG|850|42,33%|
|MISC|1213|50,24%|

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -1,11 +1,3 @@
---
title: Crowdsourcing
published: true
taxonomy:
category: [tp2020]
tag: [annotation,nlp]
author: Jakub Maruniak
---
**Crowdsourcing** **Crowdsourcing**
Čo je to crowdsourcing? Výraz _crowdsourcing_ bol prvý krát použitý v júni 2006, kedy editor magazínu Wired, Jeff Howe, vydal článok „The Rise of Crowdsourcing&quot; [1]. V tomto článku a v ďalších príspevkoch na svojom blogu popisuje novú organizačnú formu, koncept, pri ktorom je problém zadaný neznámej skupine riešiteľov. Zákazníci, alebo žiadatelia môžu uverejniť požadované úlohy na crowdsourcingovú platformu, kde dodávatelia skupina, alebo jednotlivci vykonajú tieto úlohy na základe ich záujmov a schopností [2]. Čo je to crowdsourcing? Výraz _crowdsourcing_ bol prvý krát použitý v júni 2006, kedy editor magazínu Wired, Jeff Howe, vydal článok „The Rise of Crowdsourcing&quot; [1]. V tomto článku a v ďalších príspevkoch na svojom blogu popisuje novú organizačnú formu, koncept, pri ktorom je problém zadaný neznámej skupine riešiteľov. Zákazníci, alebo žiadatelia môžu uverejniť požadované úlohy na crowdsourcingovú platformu, kde dodávatelia skupina, alebo jednotlivci vykonajú tieto úlohy na základe ich záujmov a schopností [2].
@ -95,4 +87,4 @@ Model crowdsourcingu pre vytváranie korpusu môže mať 3 formy. Prvou formou j
[24] D. Jurgens and R. Navigli, &quot;It&#39;s All Fun and Games until Someone Annotates: Video Games with a Purpose for Linguistic Annotation.&quot; [24] D. Jurgens and R. Navigli, &quot;It&#39;s All Fun and Games until Someone Annotates: Video Games with a Purpose for Linguistic Annotation.&quot;
[25] &quot;Live Demo · Prodigy · An annotation tool for AI, Machine Learning &amp; NLP.&quot; [Online]. Available: https://prodi.gy/demo?view\_id=ner. [Accessed: 12-Nov-2019]. [25] &quot;Live Demo · Prodigy · An annotation tool for AI, Machine Learning &amp; NLP.&quot; [Online]. Available: https://prodi.gy/demo?view\_id=ner. [Accessed: 12-Nov-2019].

View File

@ -3,13 +3,14 @@ title: Ján Holp
published: true published: true
taxonomy: taxonomy:
category: [dp2021,bp2019] category: [dp2021,bp2019]
tag: [ir,nlp,pagerank] tag: [ir,nlp]
author: Daniel Hladek author: Daniel Hladek
--- ---
# Ján Holp # Ján Holp
*Rok začiatku štúdia*: 2016 *Rok začiatku štúdia*: 2016
## Diplomová práca 2021 ## Diplomová práca 2021
*Názov diplomovej práce*: Systém získavania informácií v slovenskom jazyku. *Názov diplomovej práce*: Systém získavania informácií v slovenskom jazyku.
@ -23,121 +24,16 @@ taxonomy:
3. Navrhnite a vypracujte experimenty, v ktorých vyhodnotíte vybrané metódy odhodnotenia dokumentov. 3. Navrhnite a vypracujte experimenty, v ktorých vyhodnotíte vybrané metódy odhodnotenia dokumentov.
4. Navrhnite možné zlepšenia presnosti vyhľadávania. 4. Navrhnite možné zlepšenia presnosti vyhľadávania.
Stretnutie 12.3. ## Diplomový projekt 2020
Stav:
- Implementovaný PageRank, indexovanie webových stránok
Úlohy:
- Pripravte experiment s PageRank, databáza SCNC2, vyhodnotenie pomocou P-R-F1
- Pozrite do knihy na metódy vyhodnotenta s PageRank
- Pozrite do knihy a skúste pripraviť inú metriku.
- Popri tom priprave demonštráciu s webovým rozhraním.
## Diplomový projekt 2 2020
Zásobník úloh: Zásobník úloh:
- Urobiť verejné demo - nasadenie pomocou systému Docker. Využiť veľké slovenské dáta z internetu. - Urobiť verejné demo - nasadenie pomocou systému Docker
- zlepšenie Web UI - zlepšenie Web UI
- vytvoriť REST api pre indexovanie dokumentu.
- V indexe prideliť ohodnotenie každému dokumentu podľa viacerých metód, napr. PageRank - V indexe prideliť ohodnotenie každému dokumentu podľa viacerých metód, napr. PageRank
- Využiť vyhodnotenie pri vyhľadávaní - Využiť vyhodnotenie pri vyhľadávaní
- **Použiť overovaciu databázu SCNC na vyhodnotenie každej metódy** - **Použiť overovaciu databázu SCNC na vyhodnotenie každej metódy**
- **Do konca zimného semestra vytvoriť "Mini Diplomovú prácu cca 8 strán s experimentami" vo forme článku** - **Do konca zimného semestra vytvoriť "Mini Diplomovú prácu" vo forme článku**
Virtuálne stretnutie 7.1.2020:
Dohoda na zmene smerovania práce. Chceme:
- Rozšíriť BP o vyhľadávanie pomocou PageRank
- Doplniť pagerank do indexu z BP
- zakomponovať Pagerank do vyhľadávania a zistiť ako to ovplyvnilo P-R
- Implementovať podobným spôsobom minimálne jednu ďalšiu metriku zo študijnej literatúry
- Zásobník úloh ostáva ak bude čas. Napr. vyrobiť demo aj z BP.
Virtuálne stretnutie 18.12:2020:
Žiaden pokrok.
Virtuálne stretnutie 3.1ľ:2020:
Riešenie technických problémov ako implementovať PageRank.
Virtuálne stretnutie 13.11:2020:
Stav:
- Vyriešené technické problémy s cassandrou. Vieme indexovať z Cassandra do ES.
Úlohy na ďalšie stretnutie:
- urobte návrh metódy PageRank.
- priprave Vaše kódy do formy web aplikácie a dajte ich do repozitára.
- backend s REST API.
- frontend s Javascriptom.
- skúste pripraviť Dockerfile s Vašou aplikáciou.
Virtuálne stretnutie 6.11:2020:
Stav:
- Riešenie problémov s cassandrou a javascriptom. Ako funguje funkcia then?
Úlohy na ďalšie stretnutie:
- vypracujte funkciu na indexovanie. Vstup je dokument (objekt s textom a metainformáciami). Fukcia zaindexuje dokument do ES.
- Naštudujte si ako funguje funkcia then a čo je to callback.
- Naštudujte si ako sa používa Promise.
- Naštudujte si ako funguje async - await.
- https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/
Virtuálne stretnutie 23.10:2020:
Stav:
- Riešenie problémov s cassandrou. Ako vybrať dáta podľa primárneho kľúča.
Do ďalšiehio stretnutia:
- pokračovať v otvorených úlohách.
- urobte funkciu pre indexovanie jedného dokumentu.
Virtuálne stretnutie 16.10.
Stav:
- Riešenie problémov s pripojením na Cassandru.
- Riešenie spôsobu výberu dát z databázy a indexovanie.
Do ďalšieho stretnutia:
- Pokračovať v otvorených úlohách z minulého stretnutia.
Virtuálne stretnutie 2.10.2020
Urobené:
- Výber a indexovanie dát z Cassandry
Do ďalšieho stretnutia:
- pracovať ďalej na indexovaní, použite Cassandra Javascript API
- urobte návrh metódy PageRank
- urobte si GIT repozitár nazvite ho dp2021 a dajte tam zdrojové kódy
- priprave Vaše kódy do formy web aplikácie
- backend s REST API
- frontend s Javascriptom
- skúste pripraviť Dockerfile s Vašou aplikáciou
## Diplomový projekt 2020
Virtuálne stretnutie 23.6.2020: Virtuálne stretnutie 23.6.2020:

View File

@ -1,82 +0,0 @@
//index.js
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
// instantiate an elasticsearch client
const client = new elasticsearch.Client({
hosts: [ 'http://localhost:9200']
});
//require Express
const express = require( 'express' );
// instanciate an instance of express and hold the value in a constant called app
const app = express();
//require the body-parser library. will be used for parsing body requests
const bodyParser = require('body-parser')
//require the path library
const path = require( 'path' );
//consts
// ping the client to be sure Elasticsearch is up
client.ping({
requestTimeout: 30000,
}, function(error) {
// at this point, eastic search is down, please check your Elasticsearch service
if (error) {
console.error('elasticsearch cluster is down!');
} else {
console.log('Everything is ok');
}
});
// use the bodyparser as a middleware
app.use(bodyParser.json())
// set port for the app to listen on
app.set( 'port', process.env.PORT || 3001 );
// set path to serve static files
app.use( express.static( path.join( __dirname, 'public' )));
// enable CORS
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// defined the base route and return with an HTML file called tempate.html
app.get('/', function(req, res){
res.sendFile('template2.html', {
root: path.join( __dirname, 'views' )
});
})
// define the /search route that should return elastic search results
app.get('/search', function (req, res){
// declare the query object to search elastic search and return only 200 results from the first result found.
// also match any data where the name is like the query string sent in
let body = {
size: 200,
from: 0,
query: {
match: {
body: req.query['q'] // demo veryia, tato cast skriptu sa upravi abz vzhladavalo v titulkoch a tele
}
}
}
// perform the actual search passing in the index, the search query and the type
client.search({index:'skweb2', body:body, type:'web_page'})
.then(results => {
res.send(results.hits.hits);
})
.catch(err=>{
console.log(err)
res.send([]);
});
})
// listen on the specified port
app .listen( app.get( 'port' ), function(){
console.log( 'Express server listening on port ' + app.get( 'port' ));
} );

View File

@ -1,143 +0,0 @@
//Jan Holp, DP 2021
//client2 = cassandra
//client1 = elasticsearch
//-----------------------------------------------------------------
//require for PageRank
var Pagerank = require('../lib/pagerank')
var fs = require('fs')
var path = require('path')
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
const client1 = new elasticsearch.Client({
hosts: [ 'localhost:9200']
});
client1.ping({
requestTimeout: 30000,
}, function(error) {
// at this point, eastic search is down, please check your Elasticsearch service
if (error) {
console.error('Elasticsearch cluster is down!');
} else {
console.log('ELasticSearch is ok');
}
});
//create new index - skweb2
client1.indices.create({
index: 'skweb2'
}, function(error, response, status) {
if (error) {
console.log(error);
} else {
console.log("created a new index", response);
}
});
//indexing method
const bulkIndex = function bulkIndex(index, type, data) {
let bulkBody = [];
//id = 1;
const errorCount = 0;
data.forEach(item => {
bulkBody.push({
index: {
_index: index,
_type: type,
_id : item.target_link, // documents id is url
}
});
bulkBody.push(item);
});
console.log(bulkBody);
//console.log(object_list.id);
client1.bulk({body: bulkBody})
.then(response => {
response.items.forEach(item => {
if (item.index && item.index.error) {
console.log(++errorCount, item.index.error);
}
});
console.log(
`Successfully indexed ${data.length - errorCount}
out of ${data.length} items`
);
})
.catch(console.err);
};
const cassandra = require('cassandra-driver');
const client2 = new cassandra.Client({ contactPoints: ['localhost:9042'], localDataCenter: 'datacenter1', keyspace: 'websucker' });
const query1 = 'SELECT domain_name FROM websucker.domain_quality WHERE good_count > 0 ALLOW FILTERING';
//const query2 = 'SELECT * from websucker.content WHERE domain_name = ' + domain_name[i] + 'ALLOW FILTERING'; // body_size > 0
//-------------------------------------------------------------------------
var domain_name = []; // pole domain name
var object_list = []; // pole ktore obsahuje vsetky dokumenty pre jednotilive domain name
const linkProb = 0.85; // high numbers are more stable (Pagerank)
const tolerance = 0.0001; // sensitivity for accuracy of convergence
client2.execute(query1) // vyselektujeme vsetky domenove mena a ulozime do pola
.then(result => {
let pole = result.rows.map(r => {
domain_name.push(r.domain_name)
});
console.log("Vsetky domenove mena : " , domain_name);
domain_name.forEach(name => { // pre kazde domenove meno spustime select nizsie, kt. vyberie vsetky clanky ktore niesu prazdne
let query = 'SELECT * from websucker.content WHERE domain_name = ' + "'" + name + "'" + ' and body_size > 0 ALLOW FILTERING';
client2.execute(query).then( res => {
object_list = res.rows.map(rr => {
return {
domain_name: rr.domain_name,
title: rr.title,
body: rr.body,
links: rr.links,
target_link: rr.target_link,
// pagerank: Pagerank(rr.links ,linkProb,tolerance, function (err, res) {
// return res;
// })
}
});
//console.log(object_list);
bulkIndex('skweb2', 'web_page', object_list);
}).catch(error => console.log(error));
})
}).catch(err => console.log(err));
//volanie funkcie pre vypocet Pageranku a definovane premenne
//Larger numbers (0.85) //var linkProb = 0.85;
//accuracy at which we terminate
//--------------Pagerank
// const linkProb = 0.85; // high numbers are more stable (Pagerank)
// const tolerance = 0.0001; // sensitivity for accuracy of convergence
/*
var nodeMatrix = [
[object_list.links]
];
*/
/*
const PR = function PR(nodeMatrix,linkProb,tolerance){
Pagerank(nodeMatrix, linkProb, tolerance, function (err, res) {
return res;
//console.log(res);
});
}
*/

View File

@ -1,28 +0,0 @@
(function () {
'use strict';
const elasticsearch = require('elasticsearch');
const esClient = new elasticsearch.Client({
host: '127.0.0.1:9200',
log: 'error'
});
const indices = function indices() {
return esClient.cat.indices({v: true})
.then(console.log)
.catch(err => console.error(`Error connecting to the es client: ${err}`));
};
// only for testing purposes
// all calls should be initiated through the module
const test = function test() {
console.log(`elasticsearch indices information:`);
indices();
};
test();
module.exports = {
indices
};
} ());

View File

@ -1,97 +0,0 @@
// From https://github.com/douglascrockford/JSON-js/blob/master/json2.js
if (typeof JSON.parse !== "function") {
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
JSON.parse = function(text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k;
var v;
var value = holder[key];
if (value && typeof value === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
rx_dangerous.lastIndex = 0;
if (rx_dangerous.test(text)) {
text = text.replace(rx_dangerous, function(a) {
return (
"\\u" +
("0000" + a.charCodeAt(0).toString(16)).slice(-4)
);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with "()" and "new"
// because they can cause invocation, and "=" because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
// replace all simple value tokens with "]" characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or "]" or
// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
if (
rx_one.test(
text
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval("(" + text + ")");
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return (typeof reviver === "function") ?
walk({
"": j
}, "") :
j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError("JSON.parse");
};
}

View File

@ -1,109 +0,0 @@
//data.js
const fs = require('fs');
const readline = require('readline');
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
// instantiate an Elasticsearch client
const client = new elasticsearch.Client({
hosts: [ 'http://localhost:9200']
});
// ping the client to be sure Elasticsearch is up
client.ping({
requestTimeout: 30000,
}, function(error) {
// at this point, eastic search is down, please check your Elasticsearch service
if (error) {
console.error('Elasticsearch cluster is down!');
} else {
console.log('Everything is ok');
}
});
client.indices.create({
index: 'skweb'
}, function(error, response, status) {
if (error) {
console.log(error);
} else {
console.log("created a new index", response);
}
});
const bulkIndex = function bulkIndex(index, type, data) {
let bulkBody = [];
id = 1;
const errorCount = 0;
data.forEach(item => {
bulkBody.push({
index: {
_index: index,
_type: type,
_id : id++,
}
});
bulkBody.push(item);
});
console.log(bulkBody);
client.bulk({body: bulkBody})
.then(response => {
response.items.forEach(item => {
if (item.index && item.index.error) {
console.log(++errorCount, item.index.error);
}
});
console.log(
`Successfully indexed ${data.length - errorCount}
out of ${data.length} items`
);
})
.catch(console.err);
};
async function indexData() {
let documents = [];
const readInterface = readline.createInterface({
input: fs.createReadStream('/home/jan/Documents/skweb/skusobny_subor.txt'),
// output: process.stdout,
console: false
});
readInterface.on('line', function(line) {
//const article = JSON.parse(line);
try {
const article = JSON.parse(line);
documents.push(article);
//console.log(JSON.parse(line));
} catch (article) {
if (article instanceof SyntaxError) {
console.log( "Chyba, neplatny JSON" );
} //else {
//console.log(article, "bezchyby");
//}
}
// documents.push(article);
});
readInterface.on('close', function() {
//console.log(documents);
bulkIndex('skweb', 'web_page', documents);
});
}
indexData();

File diff suppressed because one or more lines are too long

View File

@ -1,792 +0,0 @@
{
"name": "elastic-node",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/long": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
},
"@types/node": {
"version": "14.11.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.10.tgz",
"integrity": "sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA=="
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"adm-zip": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
"integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg=="
},
"agentkeepalive": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
"integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
"requires": {
"humanize-ms": "^1.2.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"array-filter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
"integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"assert": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz",
"integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==",
"requires": {
"es6-object-assign": "^1.1.0",
"is-nan": "^1.2.1",
"object-is": "^1.0.1",
"util": "^0.12.0"
}
},
"available-typed-arrays": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
"integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
"requires": {
"array-filter": "^1.0.0"
}
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
"requires": {
"bytes": "3.1.0",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"on-finished": "~2.3.0",
"qs": "6.7.0",
"raw-body": "2.4.0",
"type-is": "~1.6.17"
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"cassandra-driver": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.6.0.tgz",
"integrity": "sha512-OCYJ3Zuy2La0qf+7dfeYlG3X4C0ns1cbPu0hhpC3xyUWqTy1Ai9a4mlQjSBqbcHi51gdFB5UbS0fWJzZIY6NXw==",
"requires": {
"@types/long": "^4.0.0",
"@types/node": ">=8",
"adm-zip": "^0.4.13",
"long": "^2.2.0"
}
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"requires": {
"object-keys": "^1.0.12"
}
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"elasticsearch": {
"version": "16.7.1",
"resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-16.7.1.tgz",
"integrity": "sha512-PL/BxB03VGbbghJwISYvVcrR9KbSSkuQ7OM//jHJg/End/uC2fvXg4QI7RXLvCGbhBuNQ8dPue7DOOPra73PCw==",
"requires": {
"agentkeepalive": "^3.4.1",
"chalk": "^1.0.0",
"lodash": "^4.17.10"
}
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"es-abstract": {
"version": "1.18.0-next.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
"integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-negative-zero": "^2.0.0",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
},
"es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
"is-symbol": "^1.0.2"
}
},
"es6-object-assign": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
"requires": {
"accepts": "~1.3.7",
"array-flatten": "1.1.1",
"body-parser": "1.19.0",
"content-disposition": "0.5.3",
"content-type": "~1.0.4",
"cookie": "0.4.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.1.2",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.5",
"qs": "6.7.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.1.2",
"send": "0.17.1",
"serve-static": "1.14.1",
"setprototypeof": "1.1.1",
"statuses": "~1.5.0",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
}
},
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"humanize-ms": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
"integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
"requires": {
"ms": "^2.0.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"is-arguments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
},
"is-callable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
"integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
},
"is-date-object": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-generator-function": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
"integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
},
"is-nan": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz",
"integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==",
"requires": {
"define-properties": "^1.1.3"
}
},
"is-negative-zero": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
"integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE="
},
"is-regex": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
"requires": {
"has-symbols": "^1.0.1"
}
},
"is-symbol": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"requires": {
"has-symbols": "^1.0.1"
}
},
"is-typed-array": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz",
"integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==",
"requires": {
"available-typed-arrays": "^1.0.0",
"es-abstract": "^1.17.4",
"foreach": "^2.0.5",
"has-symbols": "^1.0.1"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"long": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz",
"integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"object-inspect": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
},
"object-is": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz",
"integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.1"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object.assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
"integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.0",
"has-symbols": "^1.0.1",
"object-keys": "^1.1.1"
}
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"pagerank.js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pagerank.js/-/pagerank.js-1.0.2.tgz",
"integrity": "sha1-jw2LK2jrb63eCq14DfBF0ib3dYQ="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
"requires": {
"forwarded": "~0.1.2",
"ipaddr.js": "1.9.1"
}
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"raw-body": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
"requires": {
"debug": "2.6.9",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "~1.7.2",
"mime": "1.6.0",
"ms": "2.1.1",
"on-finished": "~2.3.0",
"range-parser": "~1.2.1",
"statuses": "~1.5.0"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"serve-static": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
"requires": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.17.1"
}
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string.prototype.trimend": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
},
"string.prototype.trimstart": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"util": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz",
"integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==",
"requires": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"safe-buffer": "^5.1.2",
"which-typed-array": "^1.1.2"
}
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"which-typed-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz",
"integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==",
"requires": {
"available-typed-arrays": "^1.0.2",
"es-abstract": "^1.17.5",
"foreach": "^2.0.5",
"function-bind": "^1.1.1",
"has-symbols": "^1.0.1",
"is-typed-array": "^1.1.3"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
}
}
}

View File

@ -1,19 +0,0 @@
{
"name": "elastic-node",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"assert": "^2.0.0",
"body-parser": "^1.19.0",
"cassandra-driver": "^4.6.0",
"elasticsearch": "^16.7.1",
"express": "^4.17.1",
"pagerank.js": "^1.0.2"
},
"description": ""
}

View File

@ -1,149 +0,0 @@
//"use strict";
// pagerank.js 0.0.1
//Use a random surfer algorithm to determine the relative
//rank of nodes. The importance of each node is determined
//by the number of incoming links as well as the importance
//of those incoming links.
// Expose
// ----------
//Expose our library to be called externally
module.exports = function (nodeMatrix, linkProb, tolerance, callback, debug) {
if (!nodeMatrix || !linkProb || !tolerance || !callback) {
throw new Error("Provide 4 arguments: "+
"nodeMatrix, link probability, tolerance, callback");
}
//If debug is unset set it to false
if (!debug) {
debug=false;
}
return new Pagerank(nodeMatrix, linkProb, tolerance, callback, debug);
};
// Initialize
// ----------
function Pagerank(nodeMatrix, linkProb, tolerance, callback, debug) {
//**OutgoingNodes:** represents an array of nodes. Each node in this
//array contains an array of nodes to which the corresponding node has
//outgoing links.
this.outgoingNodes = nodeMatrix;
//console.log(this.outgoingNodes);
//**LinkProb:** a value ??
this.linkProb = linkProb;
//**Tolerance:** the point at which a solution is deemed optimal.
//Higher values are more accurate, lower values are faster to computer.
this.tolerance = tolerance;
this.callback = callback;
//Number of outgoing nodes
this.pageCount = Object.keys(this.outgoingNodes).length;
//console.log(this.pageCount);
//**Coeff:** coefficient for the likelihood that a page will be visited.
this.coeff = (1-linkProb)/this.pageCount;
this.probabilityNodes = !(nodeMatrix instanceof Array) ? {} : [];
this.incomingNodes = !(nodeMatrix instanceof Array) ? {} : [];
//console.log(this.incomingNodes);
this.debug=debug;
this.startRanking();
}
//Start ranking
// ----------
Pagerank.prototype.startRanking = function () {
//we initialize all of our probabilities
var initialProbability = 1/this.pageCount,
outgoingNodes = this.outgoingNodes, i, a, index;
//rearray the graph and generate initial probability
for (i in outgoingNodes) {
this.probabilityNodes[i]=initialProbability;
for (a in outgoingNodes[i]) {
index = outgoingNodes[i][a];
if (!this.incomingNodes[index]) {
this.incomingNodes[index]=[];
}
this.incomingNodes[index].push(i);
// console.log(this.incomingNodes);
}
}
//if debug is set, print each iteration
if (this.debug) this.reportDebug(1)
this.iterate(1);
};
//Log iteration to console
// ----------
Pagerank.prototype.reportDebug = function (count) {
//console.log("____ITERATION "+count+"____");
//console.log("Pages: " + Object.keys(this.outgoingNodes).length);
//console.log("outgoing %j", this.outgoingNodes);
//console.log("incoming %j",this.incomingNodes);
//console.log("probability %j",this.probabilityNodes);
};
//Calculate new weights
// ----------
Pagerank.prototype.iterate = function(count) {
var result = [];
var resultHash={};
var prob, ct, b, a, sum, res, max, min;
//For each node, we look at the incoming edges and
//the weight of the node connected via each edge.
//This weight is divided by the total number of
//outgoing edges from each weighted node and summed to
//determine the new weight of the original node.
for (b in this.probabilityNodes) {
sum = 0;
if( this.incomingNodes[b] ) {
for ( a=0; a<this.incomingNodes[b].length; a++) {
prob = this.probabilityNodes[ this.incomingNodes[b][a] ];
ct = this.outgoingNodes[ this.incomingNodes[b][a] ].length;
sum += (prob/ct) ;
}
}
//determine if the new probability is within tolerance.
res = this.coeff+this.linkProb*sum;
max = this.probabilityNodes[b]+this.tolerance;
min = this.probabilityNodes[b]-this.tolerance;
//if the result has changed push that result
if (min <= res && res<= max) {
resultHash[b]=res;
result.push(res);
}
//update the probability for node *b*
this.probabilityNodes[b]=res;
//console.log(this.probabilityNodes[b]);
//console.log(res);
}
//When we have all results (no weights are changing) we return via callback
if (result.length == this.pageCount) {
if( !(this.outgoingNodes instanceof Array)) {
return this.callback(null, resultHash);
}
return this.callback(null, result);
}
//if debug is set, print each iteration
if (this.debug) {
this.reportDebug(count);
}
++count;
return this.iterate(count);
};

View File

@ -1,20 +0,0 @@
funguje indexovanie z cassandry do ES
funguje vyhladavanie
navod na spustenie :
1. vymazanie indexu :
curl -XDELETE http://localhost:9200/skweb2/
2. spustenie indexovania :
nodejs cassandra.js
3. spustenie web aplikacie
nodejs app.js
4. otvorime prehliadac
http://localhost:3001/

View File

@ -1,124 +0,0 @@
<!-- template.html -->
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div class="container" id="app">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>Search engine for Slovak internet</h1>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-3">
<form action="" class="search-form">
<div class="form-group has-feedback">
<label for="search" class="sr-only">Search</label>
<input type="text" class="form-control" name="search" id="search" placeholder="search" v-model="query" >
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-md-3" v-for="result in results">
<div class="panel panel-default">
<div class="panel-heading">
{{ result._source.target_link}}
</div>
<div class="panel-heading">
{{ result._source.title}}
</div>
<div class="panel-body">
<!-- display the latitude and longitude of the city -->
<p>{{ result._source.body }}</p>
</div>
</div>
</div>
</div>
</div>
<!--- styling -->
<style>
.search-form .form-group {
float: right !important;
transition: all 0.35s, border-radius 0s;
width: 32px;
height: 32px;
background-color: #fff;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
border-radius: 25px;
border: 1px solid #ccc;
}
.search-form .form-group input.form-control {
padding-right: 20px;
border: 0 none;
background: transparent;
box-shadow: none;
display: block;
}
.search-form .form-group input.form-control::-webkit-input-placeholder {
display: none;
}
.search-form .form-group input.form-control:-moz-placeholder {
/* Firefox 18- */
display: none;
}
.search-form .form-group input.form-control::-moz-placeholder {
/* Firefox 19+ */
display: none;
}
.search-form .form-group input.form-control:-ms-input-placeholder {
display: none;
}
.search-form .form-group:hover,
.search-form .form-group.hover {
width: 100%;
border-radius: 4px 25px 25px 4px;
}
.search-form .form-group span.form-control-feedback {
position: absolute;
top: -1px;
right: -2px;
z-index: 2;
display: block;
width: 34px;
height: 34px;
line-height: 34px;
text-align: center;
color: #3596e0;
left: initial;
font-size: 14px;
}
</style>
<script>
var app = new Vue({
el: '#app',
data: {
results: [],
query: ''
},
methods: {
search: function() {
axios.get("http://127.0.0.1:3001/search?q=" + this.query)
.then(response => {
this.results = response.data;
console.log(response.data);
})
}
},
watch: {
query: function() {
this.search();
}
}
})
</script>

View File

@ -1,105 +0,0 @@
//Jan Holp, DP 2021
//client1 = cassandra
//client2 = elasticsearch
//-----------------------------------------------------------------
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
const client2 = new elasticsearch.Client({
hosts: [ 'localhost:9200']
});
client2.ping({
requestTimeout: 30000,
}, function(error) {
// at this point, eastic search is down, please check your Elasticsearch service
if (error) {
console.error('Elasticsearch cluster is down!');
} else {
console.log('Everything is ok');
}
});
//create new index skweb2
client2.indices.create({
index: 'skweb2'
}, function(error, response, status) {
if (error) {
console.log(error);
} else {
console.log("created a new index", response);
}
});
const cassandra = require('cassandra-driver');
const client1 = new cassandra.Client({ contactPoints: ['localhost:9042'], localDataCenter: 'datacenter1', keyspace: 'websucker' });
const query = 'SELECT title FROM websucker.content WHERE body_size > 0 ALLOW FILTERING';
client1.execute(query)
.then(result => console.log(result)),function(error) {
if(error){
console.error('Something is wrong!');
console.log(error);
} else{
console.log('Everything is ok');
}
};
/*
async function indexData() {
var i = 0;
const query = 'SELECT title FROM websucker.content WHERE body_size > 0 ALLOW FILTERING';
client1.execute(query)
.then((result) => {
try {
//for ( i=0; i<15;i++){
console.log('%s', result.row[0].title)
//}
} catch (query) {
if (query instanceof SyntaxError) {
console.log( "Neplatne query" );
}
}
});
}
/*
//indexing method
const bulkIndex = function bulkIndex(index, type, data) {
let bulkBody = [];
id = 1;
const errorCount = 0;
data.forEach(item => {
bulkBody.push({
index: {
_index: index,
_type: type,
_id : id++,
}
});
bulkBody.push(item);
});
console.log(bulkBody);
client.bulk({body: bulkBody})
.then(response => {
response.items.forEach(item => {
if (item.index && item.index.error) {
console.log(++errorCount, item.index.error);
}
});
console.log(
`Successfully indexed ${data.length - errorCount}
out of ${data.length} items`
);
})
.catch(console.err);
};
*/

View File

@ -1,11 +1,3 @@
---
title: Získavanie informácií
published: true
taxonomy:
category: [tp2020]
tag: [ir,nlp]
author: Ján Holp
---
# Tímový projekt # Tímový projekt
# Learning to Rank for Information Retrieval and Natural Language Processing # Learning to Rank for Information Retrieval and Natural Language Processing
@ -76,4 +68,4 @@ Kde w označuje slovo v dokumente d, a q, t𝒇(𝒘) označujú frekvenciu slov
[9] Langville, Amy N.; Meyer, Carl D. (2006). Google's PageRank and Beyond: The Science of Search Engine Rankings. Princeton University Press, [ cit. 19.december. 2019 ]. [9] Langville, Amy N.; Meyer, Carl D. (2006). Google's PageRank and Beyond: The Science of Search Engine Rankings. Princeton University Press, [ cit. 19.december. 2019 ].
[10] Michael Bendersky,W.Bruce Croft,andYanlei Diao. Quality-biased ranking of web documents. InWSDM,pages 95104,2011, [cit. 19.december. 2019 ]. [10] Michael Bendersky,W.Bruce Croft,andYanlei Diao. Quality-biased ranking of web documents. InWSDM,pages 95104,2011, [cit. 19.december. 2019 ].

View File

@ -10,117 +10,22 @@ taxonomy:
*Rok začiatku štúdia:* 2016 *Rok začiatku štúdia:* 2016
Názov: Paralelné trénovanie neurónových sietí
*Meno vedúceho:* Ing. Daniel Hládek, PhD.
## Diplomová práca 2021
1. Vypracujte prehľad literatúry na tému "Paralelné trénovanie neurónových sietí".
2. Vyberte vhodnú metódu paralelného trénovania.
3. Pripravte dáta a vykonajte sadu experimentov pre overenie funkčnosti a výkonu paralelného trénovania.
4. Navrhnite možné zlepšenia paralelného trénovania neurónových sietí.
Stretnutie: 5.3.2021
Stav:
- Urobené trénovanie na dvoch servroch pomocou distributed_data_parallel MNIST.
- Funguje LUNA dataset (na 1 stroji a na viacerých kartách).
## Diplomový projekt 2 2020
Ciele na semester:
- Pripraviť tabuľku s výsledkami experimentov v rôznych konfiguráciách
- Napísať stručný report (cca 8 strán) vo forme článku.
Zásobník úloh:
- Ten istý scenár spustiť v rôznych podmienkach a zmerať čas.
- Trénovanie na jednej karte na jednom stroji
- tesla
- xavier
- Trénovanie na dvoch kartách na jednom stroji
- idoc DONE
- titan
- možno trénovanie na 4 kartách na jednom
- quadra
- *Trénovanie na dvoch kartách na dvoch strojoch pomocou NCCL (idoc, tesla)*
- možno trénovanie na 2 kartách na dvoch strojoch (quadra plus idoc).
Virtuálne stretnutie 4.12.2020
Stav:
- Vyriešený problém s CUDA Compute Capability. Každý conda baliček podporuje inú verziu CC. Aktuálna verzia Pytorch pracuje iba s Compute Capability 3.7 a viac. Conda Pytorch 1.3 vyžaduje CC 3.7. Tesla karta podporuje iba 3.5. Podpora CC sa dá pridať inštaláciou zo zdroja. Funguje cuda 10.0.
- Podarilo sa natrénovať MNIST na dvoch strojoch naraz - idoc + tesla. Pytorch 1.4, wrapper distributed_data_paralel. NCCL backend. Na každom stroji sa používa rovnaký počet GPU. GPU môžu byť rôzne.
Úlohy:
- Doplniť tabuľku podpory CC v Pytorch.
- Opísať problém s Compute Capability. Čo je to CC?
- Napísať "tutoriál" ako paralelne trénovať pomocou distributed_data_parallel a NCCL. Napíšte aký setup (verzia pytorch, verzia cuda, požiaadavky na GPU ..) si paralelné trénovanie vyžaduje.
- Opísať testovacie úlohy ktoré používate
- Vypracujte tabuľku s vykonanými experimentami.
- Skúste trénovanie na xavier, skompilovaný Pytorch je v adresári hladek.
- Quadru prediskutovať (vedúci).
Virtuálne stretnutie 13.11.2020
Stav:
- Preštudovaná kniha "Deep Learning with PyTorch" o multi GPU tréningu.
- vyskúšaný LUNA dataset, CT torza pre detekciu rakoviny pľúc - 60GB dát. Dáta sa predpripravia a uložia do cache. 10 epoch trvá 1 hod na bežnom počítači. Nastal problém s "Compute Capability" - kompatibilita verzie CUDA, Pytorch a GPU Tesla V40.
- vyskúšaný wrapper data_paralel, distribute_data_parallel (trénovanie pytorch v klastri).
- Pytorch Lightning - cluster trénovanie Pytorch cez Slurm.
Úlohy na ďalšie stretnutie:
- Pracujte na písomnej časti.
- Pokračujte na benchmark experimentoch - trénovanie na viacerých strojoch (idoc a tesla) naraz.
Virtuálne stretnutie 27.10.2020
Stav:
- Trénovanie na procesore, na 1 GPU, na 2 GPU na idoc
- Príprava podkladov na trénovanie na dvoch strojoch pomocou Pytorch.
- Vytvorený prístup na teslu a xavier.
Úlohy na ďďalšie stretnutie:
- Štdúdium odbornej literatúry a vypracovanie poznámok.
- Pokračovať v otvorených úlohách zo zásobníka
- Vypracované skripty uložiť na GIT repozitár
- vytvorte repozitár dp2021
Stretnutie 2.10.2020
Urobené https://github.com/LukasPokryvka/YELP-on-GPU
- demonštračná úloha pre automatické hodnotenie reštaurácií na základe recenzie v anglickom jazyku, dátová sada yelp.
- preštudovaná kniha NLP with Pytorch, NLP in Action.
- trénovanie na NVIDIA RTX2070 Super.
Úlohy do ďalšieho stretnutia:
- Prejsť odborné publikácie na tému "benchmarking" a "parallel training of neural networks".
- Zapísať si relevantné bibliografické odkazy.
- Zapísať poznámky
- Použiť index scopus alebo scholar
- Trénovanie na jednej karte na jednom stroji
- tesla.fei.tuke.sk
- Trénovanie na dvoch kartách na jednom stroji - zistite čas trénovania a spotrebu pamäte.
- idoc
## Diplomový projekt 1 2020 ## Diplomový projekt 1 2020
Paralelné trénovanie neurónových sietí pomocou knižnice Pytorch. Paralelné trénovanie neurónových sietí pomocou knižnice Pytorch.
Zásobník úloh na ďalší semester:
- Vybrať a prejsť scenár trénovania neurónových sietí pomocou nástroja [Fairseq](https://github.com/pytorch/fairseq/tree/master/examples), napr. (https://github.com/pytorch/fairseq/blob/master/examples/roberta/README.pretraining.md)
- Prejsť odborné publikácie na tému "benchmarking" a "parallel training of neural networks".
- Ten istý scenár spustiť v rôznych podmienkach a zmerať čas.
- Trénovanie na jednej karte na jednom stroji (máme rôzne - idoc, nový xavier)
- Trénovanie na dvoch kartách na jednom stroji (idoc, nový server)
- *Trénovanie na dvoch kartách na dvoch strojoch pomocou NCCL (idoc, tesla)*
- možno trénovanie na 4 kartách na jednom stroji (quadra).
- možno trénovanie na 2 kartách na dvoch strojoch (quadra plus idoc).
Úlohy na semester: Úlohy na semester:
- podrobne si naštudovať vybranú metódu trénovania neurónových sietí - podrobne si naštudovať vybranú metódu trénovania neurónových sietí
@ -198,6 +103,18 @@ Stretnutie 9.3.2020
*Písomná práca:* [Paralelné spracovanie prirodzeného jazyka](./timovy_projekt) *Písomná práca:* [Paralelné spracovanie prirodzeného jazyka](./timovy_projekt)
## Diplomová práca 2021
### Paralelné trénovanie neurónových sietí
*Meno vedúceho:* Ing. Daniel Hládek, PhD.
*Návrh na zadanie DP:*
1. Vypracujte prehľad literatúry na tému "Paralelné trénovanie neurónových sietí".
2. Vyberte vhodnú metódu paralelného trénovania.
3. Pripravte dáta a vykonajte sadu experimentov pre overenie funkčnosti a výkonu paralelného trénovania.
4. Navrhnite možné zlepšenia paralelného trénovania neurónových sietí.
- Zaujímavá príručka [Word2vec na Spark](http://spark.apache.org/docs/latest/ml-features.html#word2vec) - Zaujímavá príručka [Word2vec na Spark](http://spark.apache.org/docs/latest/ml-features.html#word2vec)

View File

@ -1,4 +1 @@
## Všetky skripty, súbory a konfigurácie ## Všetky skripty, súbory a konfigurácie
https://github.com/pytorch/examples/tree/master/imagenet
- malo by fungovat pre DDP, nedostupny imagenet subor z oficialnej stranky

View File

@ -1,76 +0,0 @@
import argparse
import datetime
import os
import socket
import sys
import numpy as np
from torch.utils.tensorboard import SummaryWriter
import torch
import torch.nn as nn
import torch.optim
from torch.optim import SGD, Adam
from torch.utils.data import DataLoader
from util.util import enumerateWithEstimate
from p2ch13.dsets import Luna2dSegmentationDataset, TrainingLuna2dSegmentationDataset, getCt
from util.logconf import logging
from util.util import xyz2irc
from p2ch13.model_seg import UNetWrapper, SegmentationAugmentation
from p2ch13.train_seg import LunaTrainingApp
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
# log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)
class BenchmarkLuna2dSegmentationDataset(TrainingLuna2dSegmentationDataset):
def __len__(self):
# return 500
return 5000
return 1000
class LunaBenchmarkApp(LunaTrainingApp):
def initTrainDl(self):
train_ds = BenchmarkLuna2dSegmentationDataset(
val_stride=10,
isValSet_bool=False,
contextSlices_count=3,
# augmentation_dict=self.augmentation_dict,
)
batch_size = self.cli_args.batch_size
if self.use_cuda:
batch_size *= torch.cuda.device_count()
train_dl = DataLoader(
train_ds,
batch_size=batch_size,
num_workers=self.cli_args.num_workers,
pin_memory=self.use_cuda,
)
return train_dl
def main(self):
log.info("Starting {}, {}".format(type(self).__name__, self.cli_args))
train_dl = self.initTrainDl()
for epoch_ndx in range(1, 2):
log.info("Epoch {} of {}, {}/{} batches of size {}*{}".format(
epoch_ndx,
self.cli_args.epochs,
len(train_dl),
len([]),
self.cli_args.batch_size,
(torch.cuda.device_count() if self.use_cuda else 1),
))
self.doTraining(epoch_ndx, train_dl)
if __name__ == '__main__':
LunaBenchmarkApp().main()

View File

@ -1,401 +0,0 @@
import copy
import csv
import functools
import glob
import math
import os
import random
from collections import namedtuple
import SimpleITK as sitk
import numpy as np
import scipy.ndimage.morphology as morph
import torch
import torch.cuda
import torch.nn.functional as F
from torch.utils.data import Dataset
from util.disk import getCache
from util.util import XyzTuple, xyz2irc
from util.logconf import logging
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
# log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)
raw_cache = getCache('part2ch13_raw')
MaskTuple = namedtuple('MaskTuple', 'raw_dense_mask, dense_mask, body_mask, air_mask, raw_candidate_mask, candidate_mask, lung_mask, neg_mask, pos_mask')
CandidateInfoTuple = namedtuple('CandidateInfoTuple', 'isNodule_bool, hasAnnotation_bool, isMal_bool, diameter_mm, series_uid, center_xyz')
@functools.lru_cache(1)
def getCandidateInfoList(requireOnDisk_bool=True):
# We construct a set with all series_uids that are present on disk.
# This will let us use the data, even if we haven't downloaded all of
# the subsets yet.
mhd_list = glob.glob('data-unversioned/subset*/*.mhd')
presentOnDisk_set = {os.path.split(p)[-1][:-4] for p in mhd_list}
candidateInfo_list = []
with open('data/annotations_with_malignancy.csv', "r") as f:
for row in list(csv.reader(f))[1:]:
series_uid = row[0]
annotationCenter_xyz = tuple([float(x) for x in row[1:4]])
annotationDiameter_mm = float(row[4])
isMal_bool = {'False': False, 'True': True}[row[5]]
candidateInfo_list.append(
CandidateInfoTuple(
True,
True,
isMal_bool,
annotationDiameter_mm,
series_uid,
annotationCenter_xyz,
)
)
with open('data/candidates.csv', "r") as f:
for row in list(csv.reader(f))[1:]:
series_uid = row[0]
if series_uid not in presentOnDisk_set and requireOnDisk_bool:
continue
isNodule_bool = bool(int(row[4]))
candidateCenter_xyz = tuple([float(x) for x in row[1:4]])
if not isNodule_bool:
candidateInfo_list.append(
CandidateInfoTuple(
False,
False,
False,
0.0,
series_uid,
candidateCenter_xyz,
)
)
candidateInfo_list.sort(reverse=True)
return candidateInfo_list
@functools.lru_cache(1)
def getCandidateInfoDict(requireOnDisk_bool=True):
candidateInfo_list = getCandidateInfoList(requireOnDisk_bool)
candidateInfo_dict = {}
for candidateInfo_tup in candidateInfo_list:
candidateInfo_dict.setdefault(candidateInfo_tup.series_uid,
[]).append(candidateInfo_tup)
return candidateInfo_dict
class Ct:
def __init__(self, series_uid):
mhd_path = glob.glob(
'data-unversioned/subset*/{}.mhd'.format(series_uid)
)[0]
ct_mhd = sitk.ReadImage(mhd_path)
self.hu_a = np.array(sitk.GetArrayFromImage(ct_mhd), dtype=np.float32)
# CTs are natively expressed in https://en.wikipedia.org/wiki/Hounsfield_scale
# HU are scaled oddly, with 0 g/cc (air, approximately) being -1000 and 1 g/cc (water) being 0.
self.series_uid = series_uid
self.origin_xyz = XyzTuple(*ct_mhd.GetOrigin())
self.vxSize_xyz = XyzTuple(*ct_mhd.GetSpacing())
self.direction_a = np.array(ct_mhd.GetDirection()).reshape(3, 3)
candidateInfo_list = getCandidateInfoDict()[self.series_uid]
self.positiveInfo_list = [
candidate_tup
for candidate_tup in candidateInfo_list
if candidate_tup.isNodule_bool
]
self.positive_mask = self.buildAnnotationMask(self.positiveInfo_list)
self.positive_indexes = (self.positive_mask.sum(axis=(1,2))
.nonzero()[0].tolist())
def buildAnnotationMask(self, positiveInfo_list, threshold_hu = -700):
boundingBox_a = np.zeros_like(self.hu_a, dtype=np.bool)
for candidateInfo_tup in positiveInfo_list:
center_irc = xyz2irc(
candidateInfo_tup.center_xyz,
self.origin_xyz,
self.vxSize_xyz,
self.direction_a,
)
ci = int(center_irc.index)
cr = int(center_irc.row)
cc = int(center_irc.col)
index_radius = 2
try:
while self.hu_a[ci + index_radius, cr, cc] > threshold_hu and \
self.hu_a[ci - index_radius, cr, cc] > threshold_hu:
index_radius += 1
except IndexError:
index_radius -= 1
row_radius = 2
try:
while self.hu_a[ci, cr + row_radius, cc] > threshold_hu and \
self.hu_a[ci, cr - row_radius, cc] > threshold_hu:
row_radius += 1
except IndexError:
row_radius -= 1
col_radius = 2
try:
while self.hu_a[ci, cr, cc + col_radius] > threshold_hu and \
self.hu_a[ci, cr, cc - col_radius] > threshold_hu:
col_radius += 1
except IndexError:
col_radius -= 1
# assert index_radius > 0, repr([candidateInfo_tup.center_xyz, center_irc, self.hu_a[ci, cr, cc]])
# assert row_radius > 0
# assert col_radius > 0
boundingBox_a[
ci - index_radius: ci + index_radius + 1,
cr - row_radius: cr + row_radius + 1,
cc - col_radius: cc + col_radius + 1] = True
mask_a = boundingBox_a & (self.hu_a > threshold_hu)
return mask_a
def getRawCandidate(self, center_xyz, width_irc):
center_irc = xyz2irc(center_xyz, self.origin_xyz, self.vxSize_xyz,
self.direction_a)
slice_list = []
for axis, center_val in enumerate(center_irc):
start_ndx = int(round(center_val - width_irc[axis]/2))
end_ndx = int(start_ndx + width_irc[axis])
assert center_val >= 0 and center_val < self.hu_a.shape[axis], repr([self.series_uid, center_xyz, self.origin_xyz, self.vxSize_xyz, center_irc, axis])
if start_ndx < 0:
# log.warning("Crop outside of CT array: {} {}, center:{} shape:{} width:{}".format(
# self.series_uid, center_xyz, center_irc, self.hu_a.shape, width_irc))
start_ndx = 0
end_ndx = int(width_irc[axis])
if end_ndx > self.hu_a.shape[axis]:
# log.warning("Crop outside of CT array: {} {}, center:{} shape:{} width:{}".format(
# self.series_uid, center_xyz, center_irc, self.hu_a.shape, width_irc))
end_ndx = self.hu_a.shape[axis]
start_ndx = int(self.hu_a.shape[axis] - width_irc[axis])
slice_list.append(slice(start_ndx, end_ndx))
ct_chunk = self.hu_a[tuple(slice_list)]
pos_chunk = self.positive_mask[tuple(slice_list)]
return ct_chunk, pos_chunk, center_irc
@functools.lru_cache(1, typed=True)
def getCt(series_uid):
return Ct(series_uid)
@raw_cache.memoize(typed=True)
def getCtRawCandidate(series_uid, center_xyz, width_irc):
ct = getCt(series_uid)
ct_chunk, pos_chunk, center_irc = ct.getRawCandidate(center_xyz,
width_irc)
ct_chunk.clip(-1000, 1000, ct_chunk)
return ct_chunk, pos_chunk, center_irc
@raw_cache.memoize(typed=True)
def getCtSampleSize(series_uid):
ct = Ct(series_uid)
return int(ct.hu_a.shape[0]), ct.positive_indexes
class Luna2dSegmentationDataset(Dataset):
def __init__(self,
val_stride=0,
isValSet_bool=None,
series_uid=None,
contextSlices_count=3,
fullCt_bool=False,
):
self.contextSlices_count = contextSlices_count
self.fullCt_bool = fullCt_bool
if series_uid:
self.series_list = [series_uid]
else:
self.series_list = sorted(getCandidateInfoDict().keys())
if isValSet_bool:
assert val_stride > 0, val_stride
self.series_list = self.series_list[::val_stride]
assert self.series_list
elif val_stride > 0:
del self.series_list[::val_stride]
assert self.series_list
self.sample_list = []
for series_uid in self.series_list:
index_count, positive_indexes = getCtSampleSize(series_uid)
if self.fullCt_bool:
self.sample_list += [(series_uid, slice_ndx)
for slice_ndx in range(index_count)]
else:
self.sample_list += [(series_uid, slice_ndx)
for slice_ndx in positive_indexes]
self.candidateInfo_list = getCandidateInfoList()
series_set = set(self.series_list)
self.candidateInfo_list = [cit for cit in self.candidateInfo_list
if cit.series_uid in series_set]
self.pos_list = [nt for nt in self.candidateInfo_list
if nt.isNodule_bool]
log.info("{!r}: {} {} series, {} slices, {} nodules".format(
self,
len(self.series_list),
{None: 'general', True: 'validation', False: 'training'}[isValSet_bool],
len(self.sample_list),
len(self.pos_list),
))
def __len__(self):
return len(self.sample_list)
def __getitem__(self, ndx):
series_uid, slice_ndx = self.sample_list[ndx % len(self.sample_list)]
return self.getitem_fullSlice(series_uid, slice_ndx)
def getitem_fullSlice(self, series_uid, slice_ndx):
ct = getCt(series_uid)
ct_t = torch.zeros((self.contextSlices_count * 2 + 1, 512, 512))
start_ndx = slice_ndx - self.contextSlices_count
end_ndx = slice_ndx + self.contextSlices_count + 1
for i, context_ndx in enumerate(range(start_ndx, end_ndx)):
context_ndx = max(context_ndx, 0)
context_ndx = min(context_ndx, ct.hu_a.shape[0] - 1)
ct_t[i] = torch.from_numpy(ct.hu_a[context_ndx].astype(np.float32))
# CTs are natively expressed in https://en.wikipedia.org/wiki/Hounsfield_scale
# HU are scaled oddly, with 0 g/cc (air, approximately) being -1000 and 1 g/cc (water) being 0.
# The lower bound gets rid of negative density stuff used to indicate out-of-FOV
# The upper bound nukes any weird hotspots and clamps bone down
ct_t.clamp_(-1000, 1000)
pos_t = torch.from_numpy(ct.positive_mask[slice_ndx]).unsqueeze(0)
return ct_t, pos_t, ct.series_uid, slice_ndx
class TrainingLuna2dSegmentationDataset(Luna2dSegmentationDataset):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ratio_int = 2
def __len__(self):
return 300000
def shuffleSamples(self):
random.shuffle(self.candidateInfo_list)
random.shuffle(self.pos_list)
def __getitem__(self, ndx):
candidateInfo_tup = self.pos_list[ndx % len(self.pos_list)]
return self.getitem_trainingCrop(candidateInfo_tup)
def getitem_trainingCrop(self, candidateInfo_tup):
ct_a, pos_a, center_irc = getCtRawCandidate(
candidateInfo_tup.series_uid,
candidateInfo_tup.center_xyz,
(7, 96, 96),
)
pos_a = pos_a[3:4]
row_offset = random.randrange(0,32)
col_offset = random.randrange(0,32)
ct_t = torch.from_numpy(ct_a[:, row_offset:row_offset+64,
col_offset:col_offset+64]).to(torch.float32)
pos_t = torch.from_numpy(pos_a[:, row_offset:row_offset+64,
col_offset:col_offset+64]).to(torch.long)
slice_ndx = center_irc.index
return ct_t, pos_t, candidateInfo_tup.series_uid, slice_ndx
class PrepcacheLunaDataset(Dataset):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.candidateInfo_list = getCandidateInfoList()
self.pos_list = [nt for nt in self.candidateInfo_list if nt.isNodule_bool]
self.seen_set = set()
self.candidateInfo_list.sort(key=lambda x: x.series_uid)
def __len__(self):
return len(self.candidateInfo_list)
def __getitem__(self, ndx):
# candidate_t, pos_t, series_uid, center_t = super().__getitem__(ndx)
candidateInfo_tup = self.candidateInfo_list[ndx]
getCtRawCandidate(candidateInfo_tup.series_uid, candidateInfo_tup.center_xyz, (7, 96, 96))
series_uid = candidateInfo_tup.series_uid
if series_uid not in self.seen_set:
self.seen_set.add(series_uid)
getCtSampleSize(series_uid)
# ct = getCt(series_uid)
# for mask_ndx in ct.positive_indexes:
# build2dLungMask(series_uid, mask_ndx)
return 0, 1 #candidate_t, pos_t, series_uid, center_t
class TvTrainingLuna2dSegmentationDataset(torch.utils.data.Dataset):
def __init__(self, isValSet_bool=False, val_stride=10, contextSlices_count=3):
assert contextSlices_count == 3
data = torch.load('./imgs_and_masks.pt')
suids = list(set(data['suids']))
trn_mask_suids = torch.arange(len(suids)) % val_stride < (val_stride - 1)
trn_suids = {s for i, s in zip(trn_mask_suids, suids) if i}
trn_mask = torch.tensor([(s in trn_suids) for s in data["suids"]])
if not isValSet_bool:
self.imgs = data["imgs"][trn_mask]
self.masks = data["masks"][trn_mask]
self.suids = [s for s, i in zip(data["suids"], trn_mask) if i]
else:
self.imgs = data["imgs"][~trn_mask]
self.masks = data["masks"][~trn_mask]
self.suids = [s for s, i in zip(data["suids"], trn_mask) if not i]
# discard spurious hotspots and clamp bone
self.imgs.clamp_(-1000, 1000)
self.imgs /= 1000
def __len__(self):
return len(self.imgs)
def __getitem__(self, i):
oh, ow = torch.randint(0, 32, (2,))
sl = self.masks.size(1)//2
return self.imgs[i, :, oh: oh + 64, ow: ow + 64], 1, self.masks[i, sl: sl+1, oh: oh + 64, ow: ow + 64].to(torch.float32), self.suids[i], 9999

View File

@ -1,224 +0,0 @@
import math
import random
from collections import namedtuple
import torch
from torch import nn as nn
import torch.nn.functional as F
from util.logconf import logging
from util.unet import UNet
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
# log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)
class UNetWrapper(nn.Module):
def __init__(self, **kwargs):
super().__init__()
self.input_batchnorm = nn.BatchNorm2d(kwargs['in_channels'])
self.unet = UNet(**kwargs)
self.final = nn.Sigmoid()
self._init_weights()
def _init_weights(self):
init_set = {
nn.Conv2d,
nn.Conv3d,
nn.ConvTranspose2d,
nn.ConvTranspose3d,
nn.Linear,
}
for m in self.modules():
if type(m) in init_set:
nn.init.kaiming_normal_(
m.weight.data, mode='fan_out', nonlinearity='relu', a=0
)
if m.bias is not None:
fan_in, fan_out = \
nn.init._calculate_fan_in_and_fan_out(m.weight.data)
bound = 1 / math.sqrt(fan_out)
nn.init.normal_(m.bias, -bound, bound)
# nn.init.constant_(self.unet.last.bias, -4)
# nn.init.constant_(self.unet.last.bias, 4)
def forward(self, input_batch):
bn_output = self.input_batchnorm(input_batch)
un_output = self.unet(bn_output)
fn_output = self.final(un_output)
return fn_output
class SegmentationAugmentation(nn.Module):
def __init__(
self, flip=None, offset=None, scale=None, rotate=None, noise=None
):
super().__init__()
self.flip = flip
self.offset = offset
self.scale = scale
self.rotate = rotate
self.noise = noise
def forward(self, input_g, label_g):
transform_t = self._build2dTransformMatrix()
transform_t = transform_t.expand(input_g.shape[0], -1, -1)
transform_t = transform_t.to(input_g.device, torch.float32)
affine_t = F.affine_grid(transform_t[:,:2],
input_g.size(), align_corners=False)
augmented_input_g = F.grid_sample(input_g,
affine_t, padding_mode='border',
align_corners=False)
augmented_label_g = F.grid_sample(label_g.to(torch.float32),
affine_t, padding_mode='border',
align_corners=False)
if self.noise:
noise_t = torch.randn_like(augmented_input_g)
noise_t *= self.noise
augmented_input_g += noise_t
return augmented_input_g, augmented_label_g > 0.5
def _build2dTransformMatrix(self):
transform_t = torch.eye(3)
for i in range(2):
if self.flip:
if random.random() > 0.5:
transform_t[i,i] *= -1
if self.offset:
offset_float = self.offset
random_float = (random.random() * 2 - 1)
transform_t[2,i] = offset_float * random_float
if self.scale:
scale_float = self.scale
random_float = (random.random() * 2 - 1)
transform_t[i,i] *= 1.0 + scale_float * random_float
if self.rotate:
angle_rad = random.random() * math.pi * 2
s = math.sin(angle_rad)
c = math.cos(angle_rad)
rotation_t = torch.tensor([
[c, -s, 0],
[s, c, 0],
[0, 0, 1]])
transform_t @= rotation_t
return transform_t
# MaskTuple = namedtuple('MaskTuple', 'raw_dense_mask, dense_mask, body_mask, air_mask, raw_candidate_mask, candidate_mask, lung_mask, neg_mask, pos_mask')
#
# class SegmentationMask(nn.Module):
# def __init__(self):
# super().__init__()
#
# self.conv_list = nn.ModuleList([
# self._make_circle_conv(radius) for radius in range(1, 8)
# ])
#
# def _make_circle_conv(self, radius):
# diameter = 1 + radius * 2
#
# a = torch.linspace(-1, 1, steps=diameter)**2
# b = (a[None] + a[:, None])**0.5
#
# circle_weights = (b <= 1.0).to(torch.float32)
#
# conv = nn.Conv2d(1, 1, kernel_size=diameter, padding=radius, bias=False)
# conv.weight.data.fill_(1)
# conv.weight.data *= circle_weights / circle_weights.sum()
#
# return conv
#
#
# def erode(self, input_mask, radius, threshold=1):
# conv = self.conv_list[radius - 1]
# input_float = input_mask.to(torch.float32)
# result = conv(input_float)
#
# # log.debug(['erode in ', radius, threshold, input_float.min().item(), input_float.mean().item(), input_float.max().item()])
# # log.debug(['erode out', radius, threshold, result.min().item(), result.mean().item(), result.max().item()])
#
# return result >= threshold
#
# def deposit(self, input_mask, radius, threshold=0):
# conv = self.conv_list[radius - 1]
# input_float = input_mask.to(torch.float32)
# result = conv(input_float)
#
# # log.debug(['deposit in ', radius, threshold, input_float.min().item(), input_float.mean().item(), input_float.max().item()])
# # log.debug(['deposit out', radius, threshold, result.min().item(), result.mean().item(), result.max().item()])
#
# return result > threshold
#
# def fill_cavity(self, input_mask):
# cumsum = input_mask.cumsum(-1)
# filled_mask = (cumsum > 0)
# filled_mask &= (cumsum < cumsum[..., -1:])
# cumsum = input_mask.cumsum(-2)
# filled_mask &= (cumsum > 0)
# filled_mask &= (cumsum < cumsum[..., -1:, :])
#
# return filled_mask
#
#
# def forward(self, input_g, raw_pos_g):
# gcc_g = input_g + 1
#
# with torch.no_grad():
# # log.info(['gcc_g', gcc_g.min(), gcc_g.mean(), gcc_g.max()])
#
# raw_dense_mask = gcc_g > 0.7
# dense_mask = self.deposit(raw_dense_mask, 2)
# dense_mask = self.erode(dense_mask, 6)
# dense_mask = self.deposit(dense_mask, 4)
#
# body_mask = self.fill_cavity(dense_mask)
# air_mask = self.deposit(body_mask & ~dense_mask, 5)
# air_mask = self.erode(air_mask, 6)
#
# lung_mask = self.deposit(air_mask, 5)
#
# raw_candidate_mask = gcc_g > 0.4
# raw_candidate_mask &= air_mask
# candidate_mask = self.erode(raw_candidate_mask, 1)
# candidate_mask = self.deposit(candidate_mask, 1)
#
# pos_mask = self.deposit((raw_pos_g > 0.5) & lung_mask, 2)
#
# neg_mask = self.deposit(candidate_mask, 1)
# neg_mask &= ~pos_mask
# neg_mask &= lung_mask
#
# # label_g = (neg_mask | pos_mask).to(torch.float32)
# label_g = (pos_mask).to(torch.float32)
# neg_g = neg_mask.to(torch.float32)
# pos_g = pos_mask.to(torch.float32)
#
# mask_dict = {
# 'raw_dense_mask': raw_dense_mask,
# 'dense_mask': dense_mask,
# 'body_mask': body_mask,
# 'air_mask': air_mask,
# 'raw_candidate_mask': raw_candidate_mask,
# 'candidate_mask': candidate_mask,
# 'lung_mask': lung_mask,
# 'neg_mask': neg_mask,
# 'pos_mask': pos_mask,
# }
#
# return label_g, neg_g, pos_g, lung_mask, mask_dict

View File

@ -1,69 +0,0 @@
import timing
import argparse
import sys
import numpy as np
import torch.nn as nn
from torch.autograd import Variable
from torch.optim import SGD
from torch.utils.data import DataLoader
from util.util import enumerateWithEstimate
from .dsets import PrepcacheLunaDataset, getCtSampleSize
from util.logconf import logging
# from .model import LunaModel
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
log.setLevel(logging.INFO)
# log.setLevel(logging.DEBUG)
class LunaPrepCacheApp:
@classmethod
def __init__(self, sys_argv=None):
if sys_argv is None:
sys_argv = sys.argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument('--batch-size',
help='Batch size to use for training',
default=1024,
type=int,
)
parser.add_argument('--num-workers',
help='Number of worker processes for background data loading',
default=8,
type=int,
)
# parser.add_argument('--scaled',
# help="Scale the CT chunks to square voxels.",
# default=False,
# action='store_true',
# )
self.cli_args = parser.parse_args(sys_argv)
def main(self):
log.info("Starting {}, {}".format(type(self).__name__, self.cli_args))
self.prep_dl = DataLoader(
PrepcacheLunaDataset(
# sortby_str='series_uid',
),
batch_size=self.cli_args.batch_size,
num_workers=self.cli_args.num_workers,
)
batch_iter = enumerateWithEstimate(
self.prep_dl,
"Stuffing cache",
start_ndx=self.prep_dl.num_workers,
)
for batch_ndx, batch_tup in batch_iter:
pass
if __name__ == '__main__':
LunaPrepCacheApp().main()

View File

@ -1,331 +0,0 @@
import math
import random
import warnings
import numpy as np
import scipy.ndimage
import torch
from torch.autograd import Function
from torch.autograd.function import once_differentiable
import torch.backends.cudnn as cudnn
from util.logconf import logging
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
# log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)
def cropToShape(image, new_shape, center_list=None, fill=0.0):
# log.debug([image.shape, new_shape, center_list])
# assert len(image.shape) == 3, repr(image.shape)
if center_list is None:
center_list = [int(image.shape[i] / 2) for i in range(3)]
crop_list = []
for i in range(0, 3):
crop_int = center_list[i]
if image.shape[i] > new_shape[i] and crop_int is not None:
# We can't just do crop_int +/- shape/2 since shape might be odd
# and ints round down.
start_int = crop_int - int(new_shape[i]/2)
end_int = start_int + new_shape[i]
crop_list.append(slice(max(0, start_int), end_int))
else:
crop_list.append(slice(0, image.shape[i]))
# log.debug([image.shape, crop_list])
image = image[crop_list]
crop_list = []
for i in range(0, 3):
if image.shape[i] < new_shape[i]:
crop_int = int((new_shape[i] - image.shape[i]) / 2)
crop_list.append(slice(crop_int, crop_int + image.shape[i]))
else:
crop_list.append(slice(0, image.shape[i]))
# log.debug([image.shape, crop_list])
new_image = np.zeros(new_shape, dtype=image.dtype)
new_image[:] = fill
new_image[crop_list] = image
return new_image
def zoomToShape(image, new_shape, square=True):
# assert image.shape[-1] in {1, 3, 4}, repr(image.shape)
if square and image.shape[0] != image.shape[1]:
crop_int = min(image.shape[0], image.shape[1])
new_shape = [crop_int, crop_int, image.shape[2]]
image = cropToShape(image, new_shape)
zoom_shape = [new_shape[i] / image.shape[i] for i in range(3)]
with warnings.catch_warnings():
warnings.simplefilter("ignore")
image = scipy.ndimage.interpolation.zoom(
image, zoom_shape,
output=None, order=0, mode='nearest', cval=0.0, prefilter=True)
return image
def randomOffset(image_list, offset_rows=0.125, offset_cols=0.125):
center_list = [int(image_list[0].shape[i] / 2) for i in range(3)]
center_list[0] += int(offset_rows * (random.random() - 0.5) * 2)
center_list[1] += int(offset_cols * (random.random() - 0.5) * 2)
center_list[2] = None
new_list = []
for image in image_list:
new_image = cropToShape(image, image.shape, center_list)
new_list.append(new_image)
return new_list
def randomZoom(image_list, scale=None, scale_min=0.8, scale_max=1.3):
if scale is None:
scale = scale_min + (scale_max - scale_min) * random.random()
new_list = []
for image in image_list:
# assert image.shape[-1] in {1, 3, 4}, repr(image.shape)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
# log.info([image.shape])
zimage = scipy.ndimage.interpolation.zoom(
image, [scale, scale, 1.0],
output=None, order=0, mode='nearest', cval=0.0, prefilter=True)
image = cropToShape(zimage, image.shape)
new_list.append(image)
return new_list
_randomFlip_transform_list = [
# lambda a: np.rot90(a, axes=(0, 1)),
# lambda a: np.flip(a, 0),
lambda a: np.flip(a, 1),
]
def randomFlip(image_list, transform_bits=None):
if transform_bits is None:
transform_bits = random.randrange(0, 2 ** len(_randomFlip_transform_list))
new_list = []
for image in image_list:
# assert image.shape[-1] in {1, 3, 4}, repr(image.shape)
for n in range(len(_randomFlip_transform_list)):
if transform_bits & 2**n:
# prhist(image, 'before')
image = _randomFlip_transform_list[n](image)
# prhist(image, 'after ')
new_list.append(image)
return new_list
def randomSpin(image_list, angle=None, range_tup=None, axes=(0, 1)):
if range_tup is None:
range_tup = (0, 360)
if angle is None:
angle = range_tup[0] + (range_tup[1] - range_tup[0]) * random.random()
new_list = []
for image in image_list:
# assert image.shape[-1] in {1, 3, 4}, repr(image.shape)
image = scipy.ndimage.interpolation.rotate(
image, angle, axes=axes, reshape=False,
output=None, order=0, mode='nearest', cval=0.0, prefilter=True)
new_list.append(image)
return new_list
def randomNoise(image_list, noise_min=-0.1, noise_max=0.1):
noise = np.zeros_like(image_list[0])
noise += (noise_max - noise_min) * np.random.random_sample(image_list[0].shape) + noise_min
noise *= 5
noise = scipy.ndimage.filters.gaussian_filter(noise, 3)
# noise += (noise_max - noise_min) * np.random.random_sample(image_hsv.shape) + noise_min
new_list = []
for image_hsv in image_list:
image_hsv = image_hsv + noise
new_list.append(image_hsv)
return new_list
def randomHsvShift(image_list, h=None, s=None, v=None,
h_min=-0.1, h_max=0.1,
s_min=0.5, s_max=2.0,
v_min=0.5, v_max=2.0):
if h is None:
h = h_min + (h_max - h_min) * random.random()
if s is None:
s = s_min + (s_max - s_min) * random.random()
if v is None:
v = v_min + (v_max - v_min) * random.random()
new_list = []
for image_hsv in image_list:
# assert image_hsv.shape[-1] == 3, repr(image_hsv.shape)
image_hsv[:,:,0::3] += h
image_hsv[:,:,1::3] = image_hsv[:,:,1::3] ** s
image_hsv[:,:,2::3] = image_hsv[:,:,2::3] ** v
new_list.append(image_hsv)
return clampHsv(new_list)
def clampHsv(image_list):
new_list = []
for image_hsv in image_list:
image_hsv = image_hsv.clone()
# Hue wraps around
image_hsv[:,:,0][image_hsv[:,:,0] > 1] -= 1
image_hsv[:,:,0][image_hsv[:,:,0] < 0] += 1
# Everything else clamps between 0 and 1
image_hsv[image_hsv > 1] = 1
image_hsv[image_hsv < 0] = 0
new_list.append(image_hsv)
return new_list
# def torch_augment(input):
# theta = random.random() * math.pi * 2
# s = math.sin(theta)
# c = math.cos(theta)
# c1 = 1 - c
# axis_vector = torch.rand(3, device='cpu', dtype=torch.float64)
# axis_vector -= 0.5
# axis_vector /= axis_vector.abs().sum()
# l, m, n = axis_vector
#
# matrix = torch.tensor([
# [l*l*c1 + c, m*l*c1 - n*s, n*l*c1 + m*s, 0],
# [l*m*c1 + n*s, m*m*c1 + c, n*m*c1 - l*s, 0],
# [l*n*c1 - m*s, m*n*c1 + l*s, n*n*c1 + c, 0],
# [0, 0, 0, 1],
# ], device=input.device, dtype=torch.float32)
#
# return th_affine3d(input, matrix)
# following from https://github.com/ncullen93/torchsample/blob/master/torchsample/utils.py
# MIT licensed
# def th_affine3d(input, matrix):
# """
# 3D Affine image transform on torch.Tensor
# """
# A = matrix[:3,:3]
# b = matrix[:3,3]
#
# # make a meshgrid of normal coordinates
# coords = th_iterproduct(input.size(-3), input.size(-2), input.size(-1), dtype=torch.float32)
#
# # shift the coordinates so center is the origin
# coords[:,0] = coords[:,0] - (input.size(-3) / 2. - 0.5)
# coords[:,1] = coords[:,1] - (input.size(-2) / 2. - 0.5)
# coords[:,2] = coords[:,2] - (input.size(-1) / 2. - 0.5)
#
# # apply the coordinate transformation
# new_coords = coords.mm(A.t().contiguous()) + b.expand_as(coords)
#
# # shift the coordinates back so origin is origin
# new_coords[:,0] = new_coords[:,0] + (input.size(-3) / 2. - 0.5)
# new_coords[:,1] = new_coords[:,1] + (input.size(-2) / 2. - 0.5)
# new_coords[:,2] = new_coords[:,2] + (input.size(-1) / 2. - 0.5)
#
# # map new coordinates using bilinear interpolation
# input_transformed = th_trilinear_interp3d(input, new_coords)
#
# return input_transformed
#
#
# def th_trilinear_interp3d(input, coords):
# """
# trilinear interpolation of 3D torch.Tensor image
# """
# # take clamp then floor/ceil of x coords
# x = torch.clamp(coords[:,0], 0, input.size(-3)-2)
# x0 = x.floor()
# x1 = x0 + 1
# # take clamp then floor/ceil of y coords
# y = torch.clamp(coords[:,1], 0, input.size(-2)-2)
# y0 = y.floor()
# y1 = y0 + 1
# # take clamp then floor/ceil of z coords
# z = torch.clamp(coords[:,2], 0, input.size(-1)-2)
# z0 = z.floor()
# z1 = z0 + 1
#
# stride = torch.tensor(input.stride()[-3:], dtype=torch.int64, device=input.device)
# x0_ix = x0.mul(stride[0]).long()
# x1_ix = x1.mul(stride[0]).long()
# y0_ix = y0.mul(stride[1]).long()
# y1_ix = y1.mul(stride[1]).long()
# z0_ix = z0.mul(stride[2]).long()
# z1_ix = z1.mul(stride[2]).long()
#
# # input_flat = th_flatten(input)
# input_flat = x.contiguous().view(x[0], x[1], -1)
#
# vals_000 = input_flat[:, :, x0_ix+y0_ix+z0_ix]
# vals_001 = input_flat[:, :, x0_ix+y0_ix+z1_ix]
# vals_010 = input_flat[:, :, x0_ix+y1_ix+z0_ix]
# vals_011 = input_flat[:, :, x0_ix+y1_ix+z1_ix]
# vals_100 = input_flat[:, :, x1_ix+y0_ix+z0_ix]
# vals_101 = input_flat[:, :, x1_ix+y0_ix+z1_ix]
# vals_110 = input_flat[:, :, x1_ix+y1_ix+z0_ix]
# vals_111 = input_flat[:, :, x1_ix+y1_ix+z1_ix]
#
# xd = x - x0
# yd = y - y0
# zd = z - z0
# xm1 = 1 - xd
# ym1 = 1 - yd
# zm1 = 1 - zd
#
# x_mapped = (
# vals_000.mul(xm1).mul(ym1).mul(zm1) +
# vals_001.mul(xm1).mul(ym1).mul(zd) +
# vals_010.mul(xm1).mul(yd).mul(zm1) +
# vals_011.mul(xm1).mul(yd).mul(zd) +
# vals_100.mul(xd).mul(ym1).mul(zm1) +
# vals_101.mul(xd).mul(ym1).mul(zd) +
# vals_110.mul(xd).mul(yd).mul(zm1) +
# vals_111.mul(xd).mul(yd).mul(zd)
# )
#
# return x_mapped.view_as(input)
#
# def th_iterproduct(*args, dtype=None):
# return torch.from_numpy(np.indices(args).reshape((len(args),-1)).T)
#
# def th_flatten(x):
# """Flatten tensor"""
# return x.contiguous().view(x[0], x[1], -1)

View File

@ -1,136 +0,0 @@
import gzip
from diskcache import FanoutCache, Disk
from diskcache.core import BytesType, MODE_BINARY, BytesIO
from util.logconf import logging
log = logging.getLogger(__name__)
# log.setLevel(logging.WARN)
log.setLevel(logging.INFO)
# log.setLevel(logging.DEBUG)
class GzipDisk(Disk):
def store(self, value, read, key=None):
"""
Override from base class diskcache.Disk.
Chunking is due to needing to work on pythons < 2.7.13:
- Issue #27130: In the "zlib" module, fix handling of large buffers
(typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and
compression and decompression operations did not properly handle results of
2 or 4 GiB.
:param value: value to convert
:param bool read: True when value is file-like object
:return: (size, mode, filename, value) tuple for Cache table
"""
# pylint: disable=unidiomatic-typecheck
if type(value) is BytesType:
if read:
value = value.read()
read = False
str_io = BytesIO()
gz_file = gzip.GzipFile(mode='wb', compresslevel=1, fileobj=str_io)
for offset in range(0, len(value), 2**30):
gz_file.write(value[offset:offset+2**30])
gz_file.close()
value = str_io.getvalue()
return super(GzipDisk, self).store(value, read)
def fetch(self, mode, filename, value, read):
"""
Override from base class diskcache.Disk.
Chunking is due to needing to work on pythons < 2.7.13:
- Issue #27130: In the "zlib" module, fix handling of large buffers
(typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and
compression and decompression operations did not properly handle results of
2 or 4 GiB.
:param int mode: value mode raw, binary, text, or pickle
:param str filename: filename of corresponding value
:param value: database value
:param bool read: when True, return an open file handle
:return: corresponding Python value
"""
value = super(GzipDisk, self).fetch(mode, filename, value, read)
if mode == MODE_BINARY:
str_io = BytesIO(value)
gz_file = gzip.GzipFile(mode='rb', fileobj=str_io)
read_csio = BytesIO()
while True:
uncompressed_data = gz_file.read(2**30)
if uncompressed_data:
read_csio.write(uncompressed_data)
else:
break
value = read_csio.getvalue()
return value
def getCache(scope_str):
return FanoutCache('data-unversioned/cache/' + scope_str,
disk=GzipDisk,
shards=64,
timeout=1,
size_limit=3e11,
# disk_min_file_size=2**20,
)
# def disk_cache(base_path, memsize=2):
# def disk_cache_decorator(f):
# @functools.wraps(f)
# def wrapper(*args, **kwargs):
# args_str = repr(args) + repr(sorted(kwargs.items()))
# file_str = hashlib.md5(args_str.encode('utf8')).hexdigest()
#
# cache_path = os.path.join(base_path, f.__name__, file_str + '.pkl.gz')
#
# if not os.path.exists(os.path.dirname(cache_path)):
# os.makedirs(os.path.dirname(cache_path), exist_ok=True)
#
# if os.path.exists(cache_path):
# return pickle_loadgz(cache_path)
# else:
# ret = f(*args, **kwargs)
# pickle_dumpgz(cache_path, ret)
# return ret
#
# return wrapper
#
# return disk_cache_decorator
#
#
# def pickle_dumpgz(file_path, obj):
# log.debug("Writing {}".format(file_path))
# with open(file_path, 'wb') as file_obj:
# with gzip.GzipFile(mode='wb', compresslevel=1, fileobj=file_obj) as gz_file:
# pickle.dump(obj, gz_file, pickle.HIGHEST_PROTOCOL)
#
#
# def pickle_loadgz(file_path):
# log.debug("Reading {}".format(file_path))
# with open(file_path, 'rb') as file_obj:
# with gzip.GzipFile(mode='rb', fileobj=file_obj) as gz_file:
# return pickle.load(gz_file)
#
#
# def dtpath(dt=None):
# if dt is None:
# dt = datetime.datetime.now()
#
# return str(dt).rsplit('.', 1)[0].replace(' ', '--').replace(':', '.')
#
#
# def safepath(s):
# s = s.replace(' ', '_')
# return re.sub('[^A-Za-z0-9_.-]', '', s)

View File

@ -1,19 +0,0 @@
import logging
import logging.handlers
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
# Some libraries attempt to add their own root logger handlers. This is
# annoying and so we get rid of them.
for handler in list(root_logger.handlers):
root_logger.removeHandler(handler)
logfmt_str = "%(asctime)s %(levelname)-8s pid:%(process)d %(name)s:%(lineno)03d:%(funcName)s %(message)s"
formatter = logging.Formatter(logfmt_str)
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)
streamHandler.setLevel(logging.DEBUG)
root_logger.addHandler(streamHandler)

View File

@ -1,143 +0,0 @@
# From https://github.com/jvanvugt/pytorch-unet
# https://raw.githubusercontent.com/jvanvugt/pytorch-unet/master/unet.py
# MIT License
#
# Copyright (c) 2018 Joris
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Adapted from https://discuss.pytorch.org/t/unet-implementation/426
import torch
from torch import nn
import torch.nn.functional as F
class UNet(nn.Module):
def __init__(self, in_channels=1, n_classes=2, depth=5, wf=6, padding=False,
batch_norm=False, up_mode='upconv'):
"""
Implementation of
U-Net: Convolutional Networks for Biomedical Image Segmentation
(Ronneberger et al., 2015)
https://arxiv.org/abs/1505.04597
Using the default arguments will yield the exact version used
in the original paper
Args:
in_channels (int): number of input channels
n_classes (int): number of output channels
depth (int): depth of the network
wf (int): number of filters in the first layer is 2**wf
padding (bool): if True, apply padding such that the input shape
is the same as the output.
This may introduce artifacts
batch_norm (bool): Use BatchNorm after layers with an
activation function
up_mode (str): one of 'upconv' or 'upsample'.
'upconv' will use transposed convolutions for
learned upsampling.
'upsample' will use bilinear upsampling.
"""
super(UNet, self).__init__()
assert up_mode in ('upconv', 'upsample')
self.padding = padding
self.depth = depth
prev_channels = in_channels
self.down_path = nn.ModuleList()
for i in range(depth):
self.down_path.append(UNetConvBlock(prev_channels, 2**(wf+i),
padding, batch_norm))
prev_channels = 2**(wf+i)
self.up_path = nn.ModuleList()
for i in reversed(range(depth - 1)):
self.up_path.append(UNetUpBlock(prev_channels, 2**(wf+i), up_mode,
padding, batch_norm))
prev_channels = 2**(wf+i)
self.last = nn.Conv2d(prev_channels, n_classes, kernel_size=1)
def forward(self, x):
blocks = []
for i, down in enumerate(self.down_path):
x = down(x)
if i != len(self.down_path)-1:
blocks.append(x)
x = F.avg_pool2d(x, 2)
for i, up in enumerate(self.up_path):
x = up(x, blocks[-i-1])
return self.last(x)
class UNetConvBlock(nn.Module):
def __init__(self, in_size, out_size, padding, batch_norm):
super(UNetConvBlock, self).__init__()
block = []
block.append(nn.Conv2d(in_size, out_size, kernel_size=3,
padding=int(padding)))
block.append(nn.ReLU())
# block.append(nn.LeakyReLU())
if batch_norm:
block.append(nn.BatchNorm2d(out_size))
block.append(nn.Conv2d(out_size, out_size, kernel_size=3,
padding=int(padding)))
block.append(nn.ReLU())
# block.append(nn.LeakyReLU())
if batch_norm:
block.append(nn.BatchNorm2d(out_size))
self.block = nn.Sequential(*block)
def forward(self, x):
out = self.block(x)
return out
class UNetUpBlock(nn.Module):
def __init__(self, in_size, out_size, up_mode, padding, batch_norm):
super(UNetUpBlock, self).__init__()
if up_mode == 'upconv':
self.up = nn.ConvTranspose2d(in_size, out_size, kernel_size=2,
stride=2)
elif up_mode == 'upsample':
self.up = nn.Sequential(nn.Upsample(mode='bilinear', scale_factor=2),
nn.Conv2d(in_size, out_size, kernel_size=1))
self.conv_block = UNetConvBlock(in_size, out_size, padding, batch_norm)
def center_crop(self, layer, target_size):
_, _, layer_height, layer_width = layer.size()
diff_y = (layer_height - target_size[0]) // 2
diff_x = (layer_width - target_size[1]) // 2
return layer[:, :, diff_y:(diff_y + target_size[0]), diff_x:(diff_x + target_size[1])]
def forward(self, x, bridge):
up = self.up(x)
crop1 = self.center_crop(bridge, up.shape[2:])
out = torch.cat([up, crop1], 1)
out = self.conv_block(out)
return out

View File

@ -1,105 +0,0 @@
import os
from datetime import datetime
import argparse
import torch.multiprocessing as mp
import torchvision
import torchvision.transforms as transforms
import torch
import torch.nn as nn
import torch.distributed as dist
from apex.parallel import DistributedDataParallel as DDP
from apex import amp
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--nodes', default=1, type=int, metavar='N',
help='number of data loading workers (default: 4)')
parser.add_argument('-g', '--gpus', default=1, type=int,
help='number of gpus per node')
parser.add_argument('-nr', '--nr', default=0, type=int,
help='ranking within the nodes')
parser.add_argument('--epochs', default=2, type=int, metavar='N',
help='number of total epochs to run')
args = parser.parse_args()
args.world_size = args.gpus * args.nodes
os.environ['MASTER_ADDR'] = '147.232.47.114'
os.environ['MASTER_PORT'] = '8888'
mp.spawn(train, nprocs=args.gpus, args=(args,))
class ConvNet(nn.Module):
def __init__(self, num_classes=10):
super(ConvNet, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2))
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
nn.BatchNorm2d(32),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2))
self.fc = nn.Linear(7*7*32, num_classes)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = out.reshape(out.size(0), -1)
out = self.fc(out)
return out
def train(gpu, args):
rank = args.nr * args.gpus + gpu
dist.init_process_group(backend='nccl', init_method='env://', world_size=args.world_size, rank=rank)
torch.manual_seed(0)
model = ConvNet()
torch.cuda.set_device(gpu)
model.cuda(gpu)
batch_size = 10
# define loss function (criterion) and optimizer
criterion = nn.CrossEntropyLoss().cuda(gpu)
optimizer = torch.optim.SGD(model.parameters(), 1e-4)
# Wrap the model
model = nn.parallel.DistributedDataParallel(model, device_ids=[gpu])
# Data loading code
train_dataset = torchvision.datasets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset,
num_replicas=args.world_size,
rank=rank)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=False,
num_workers=0,
pin_memory=True,
sampler=train_sampler)
start = datetime.now()
total_step = len(train_loader)
for epoch in range(args.epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.cuda(non_blocking=True)
labels = labels.cuda(non_blocking=True)
# Forward pass
outputs = model(images)
loss = criterion(outputs, labels)
# Backward and optimize
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0 and gpu == 0:
print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch + 1, args.epochs, i + 1, total_step,
loss.item()))
if gpu == 0:
print("Training complete in: " + str(datetime.now() - start))
if __name__ == '__main__':
torch.multiprocessing.set_start_method('spawn')
main()

View File

@ -1,92 +0,0 @@
import os
from datetime import datetime
import argparse
import torch.multiprocessing as mp
import torchvision
import torchvision.transforms as transforms
import torch
import torch.nn as nn
import torch.distributed as dist
from apex.parallel import DistributedDataParallel as DDP
from apex import amp
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--nodes', default=1, type=int, metavar='N',
help='number of data loading workers (default: 4)')
parser.add_argument('-g', '--gpus', default=1, type=int,
help='number of gpus per node')
parser.add_argument('-nr', '--nr', default=0, type =int,
help='ranking within the nodes')
parser.add_argument('--epochs', default=2, type=int, metavar='N',
help='number of total epochs to run')
args = parser.parse_args()
train(0, args)
class ConvNet(nn.Module):
def __init__(self, num_classes=10):
super(ConvNet, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2))
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
nn.BatchNorm2d(32),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2))
self.fc = nn.Linear(7*7*32, num_classes)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = out.reshape(out.size(0), -1)
out = self.fc(out)
return out
def train(gpu, args):
model = ConvNet()
torch.cuda.set_device(gpu)
model.cuda(gpu)
batch_size = 50
# define loss function (criterion) and optimizer
criterion = nn.CrossEntropyLoss().cuda(gpu)
optimizer = torch.optim.SGD(model.parameters(), 1e-4)
# Data loading code
train_dataset = torchvision.datasets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=0,
pin_memory=True)
start = datetime.now()
total_step = len(train_loader)
for epoch in range(args.epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.cuda(non_blocking=True)
labels = labels.cuda(non_blocking=True)
# Forward pass
outputs = model(images)
loss = criterion(outputs, labels)
# Backward and optimize
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0 and gpu == 0:
print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch + 1, args.epochs, i + 1, total_step,
loss.item()))
if gpu == 0:
print("Training complete in: " + str(datetime.now() - start))
if __name__ == '__main__':
main()

View File

@ -1,748 +0,0 @@
from argparse import Namespace
from collections import Counter
import json
import os
import re
import string
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from tqdm.notebook import tqdm
class Vocabulary(object):
"""Class to process text and extract vocabulary for mapping"""
def __init__(self, token_to_idx=None, add_unk=True, unk_token="<UNK>"):
"""
Args:
token_to_idx (dict): a pre-existing map of tokens to indices
add_unk (bool): a flag that indicates whether to add the UNK token
unk_token (str): the UNK token to add into the Vocabulary
"""
if token_to_idx is None:
token_to_idx = {}
self._token_to_idx = token_to_idx
self._idx_to_token = {idx: token
for token, idx in self._token_to_idx.items()}
self._add_unk = add_unk
self._unk_token = unk_token
self.unk_index = -1
if add_unk:
self.unk_index = self.add_token(unk_token)
def to_serializable(self):
""" returns a dictionary that can be serialized """
return {'token_to_idx': self._token_to_idx,
'add_unk': self._add_unk,
'unk_token': self._unk_token}
@classmethod
def from_serializable(cls, contents):
""" instantiates the Vocabulary from a serialized dictionary """
return cls(**contents)
def add_token(self, token):
"""Update mapping dicts based on the token.
Args:
token (str): the item to add into the Vocabulary
Returns:
index (int): the integer corresponding to the token
"""
if token in self._token_to_idx:
index = self._token_to_idx[token]
else:
index = len(self._token_to_idx)
self._token_to_idx[token] = index
self._idx_to_token[index] = token
return index
def add_many(self, tokens):
"""Add a list of tokens into the Vocabulary
Args:
tokens (list): a list of string tokens
Returns:
indices (list): a list of indices corresponding to the tokens
"""
return [self.add_token(token) for token in tokens]
def lookup_token(self, token):
"""Retrieve the index associated with the token
or the UNK index if token isn't present.
Args:
token (str): the token to look up
Returns:
index (int): the index corresponding to the token
Notes:
`unk_index` needs to be >=0 (having been added into the Vocabulary)
for the UNK functionality
"""
if self.unk_index >= 0:
return self._token_to_idx.get(token, self.unk_index)
else:
return self._token_to_idx[token]
def lookup_index(self, index):
"""Return the token associated with the index
Args:
index (int): the index to look up
Returns:
token (str): the token corresponding to the index
Raises:
KeyError: if the index is not in the Vocabulary
"""
if index not in self._idx_to_token:
raise KeyError("the index (%d) is not in the Vocabulary" % index)
return self._idx_to_token[index]
def __str__(self):
return "<Vocabulary(size=%d)>" % len(self)
def __len__(self):
return len(self._token_to_idx)
class ReviewVectorizer(object):
""" The Vectorizer which coordinates the Vocabularies and puts them to use"""
def __init__(self, review_vocab, rating_vocab):
"""
Args:
review_vocab (Vocabulary): maps words to integers
rating_vocab (Vocabulary): maps class labels to integers
"""
self.review_vocab = review_vocab
self.rating_vocab = rating_vocab
def vectorize(self, review):
"""Create a collapsed one-hit vector for the review
Args:
review (str): the review
Returns:
one_hot (np.ndarray): the collapsed one-hot encoding
"""
one_hot = np.zeros(len(self.review_vocab), dtype=np.float32)
for token in review.split(" "):
if token not in string.punctuation:
one_hot[self.review_vocab.lookup_token(token)] = 1
return one_hot
@classmethod
def from_dataframe(cls, review_df, cutoff=25):
"""Instantiate the vectorizer from the dataset dataframe
Args:
review_df (pandas.DataFrame): the review dataset
cutoff (int): the parameter for frequency-based filtering
Returns:
an instance of the ReviewVectorizer
"""
review_vocab = Vocabulary(add_unk=True)
rating_vocab = Vocabulary(add_unk=False)
# Add ratings
for rating in sorted(set(review_df.rating)):
rating_vocab.add_token(rating)
# Add top words if count > provided count
word_counts = Counter()
for review in review_df.review:
for word in review.split(" "):
if word not in string.punctuation:
word_counts[word] += 1
for word, count in word_counts.items():
if count > cutoff:
review_vocab.add_token(word)
return cls(review_vocab, rating_vocab)
@classmethod
def from_serializable(cls, contents):
"""Instantiate a ReviewVectorizer from a serializable dictionary
Args:
contents (dict): the serializable dictionary
Returns:
an instance of the ReviewVectorizer class
"""
review_vocab = Vocabulary.from_serializable(contents['review_vocab'])
rating_vocab = Vocabulary.from_serializable(contents['rating_vocab'])
return cls(review_vocab=review_vocab, rating_vocab=rating_vocab)
def to_serializable(self):
"""Create the serializable dictionary for caching
Returns:
contents (dict): the serializable dictionary
"""
return {'review_vocab': self.review_vocab.to_serializable(),
'rating_vocab': self.rating_vocab.to_serializable()}
class ReviewDataset(Dataset):
def __init__(self, review_df, vectorizer):
"""
Args:
review_df (pandas.DataFrame): the dataset
vectorizer (ReviewVectorizer): vectorizer instantiated from dataset
"""
self.review_df = review_df
self._vectorizer = vectorizer
self.train_df = self.review_df[self.review_df.split=='train']
self.train_size = len(self.train_df)
self.val_df = self.review_df[self.review_df.split=='val']
self.validation_size = len(self.val_df)
self.test_df = self.review_df[self.review_df.split=='test']
self.test_size = len(self.test_df)
self._lookup_dict = {'train': (self.train_df, self.train_size),
'val': (self.val_df, self.validation_size),
'test': (self.test_df, self.test_size)}
self.set_split('train')
@classmethod
def load_dataset_and_make_vectorizer(cls, review_csv):
"""Load dataset and make a new vectorizer from scratch
Args:
review_csv (str): location of the dataset
Returns:
an instance of ReviewDataset
"""
review_df = pd.read_csv(review_csv)
train_review_df = review_df[review_df.split=='train']
return cls(review_df, ReviewVectorizer.from_dataframe(train_review_df))
@classmethod
def load_dataset_and_load_vectorizer(cls, review_csv, vectorizer_filepath):
"""Load dataset and the corresponding vectorizer.
Used in the case in the vectorizer has been cached for re-use
Args:
review_csv (str): location of the dataset
vectorizer_filepath (str): location of the saved vectorizer
Returns:
an instance of ReviewDataset
"""
review_df = pd.read_csv(review_csv)
vectorizer = cls.load_vectorizer_only(vectorizer_filepath)
return cls(review_df, vectorizer)
@staticmethod
def load_vectorizer_only(vectorizer_filepath):
"""a static method for loading the vectorizer from file
Args:
vectorizer_filepath (str): the location of the serialized vectorizer
Returns:
an instance of ReviewVectorizer
"""
with open(vectorizer_filepath) as fp:
return ReviewVectorizer.from_serializable(json.load(fp))
def save_vectorizer(self, vectorizer_filepath):
"""saves the vectorizer to disk using json
Args:
vectorizer_filepath (str): the location to save the vectorizer
"""
with open(vectorizer_filepath, "w") as fp:
json.dump(self._vectorizer.to_serializable(), fp)
def get_vectorizer(self):
""" returns the vectorizer """
return self._vectorizer
def set_split(self, split="train"):
""" selects the splits in the dataset using a column in the dataframe
Args:
split (str): one of "train", "val", or "test"
"""
self._target_split = split
self._target_df, self._target_size = self._lookup_dict[split]
def __len__(self):
return self._target_size
def __getitem__(self, index):
"""the primary entry point method for PyTorch datasets
Args:
index (int): the index to the data point
Returns:
a dictionary holding the data point's features (x_data) and label (y_target)
"""
row = self._target_df.iloc[index]
review_vector = \
self._vectorizer.vectorize(row.review)
rating_index = \
self._vectorizer.rating_vocab.lookup_token(row.rating)
return {'x_data': review_vector,
'y_target': rating_index}
def get_num_batches(self, batch_size):
"""Given a batch size, return the number of batches in the dataset
Args:
batch_size (int)
Returns:
number of batches in the dataset
"""
return len(self) // batch_size
def generate_batches(dataset, batch_size, shuffle=True,
drop_last=True, device="cpu"):
"""
A generator function which wraps the PyTorch DataLoader. It will
ensure each tensor is on the write device location.
"""
dataloader = DataLoader(dataset=dataset, batch_size=batch_size,
shuffle=shuffle, drop_last=drop_last)
for data_dict in dataloader:
out_data_dict = {}
for name, tensor in data_dict.items():
out_data_dict[name] = data_dict[name].to(device)
yield out_data_dict
class ReviewClassifier(nn.Module):
""" a simple perceptron based classifier """
def __init__(self, num_features):
"""
Args:
num_features (int): the size of the input feature vector
"""
super(ReviewClassifier, self).__init__()
self.fc1 = nn.Linear(in_features=num_features,
out_features=1)
def forward(self, x_in, apply_sigmoid=False):
"""The forward pass of the classifier
Args:
x_in (torch.Tensor): an input data tensor.
x_in.shape should be (batch, num_features)
apply_sigmoid (bool): a flag for the sigmoid activation
should be false if used with the Cross Entropy losses
Returns:
the resulting tensor. tensor.shape should be (batch,)
"""
y_out = self.fc1(x_in).squeeze()
if apply_sigmoid:
y_out = torch.sigmoid(y_out)
return y_out
def make_train_state(args):
return {'stop_early': False,
'early_stopping_step': 0,
'early_stopping_best_val': 1e8,
'learning_rate': args.learning_rate,
'epoch_index': 0,
'train_loss': [],
'train_acc': [],
'val_loss': [],
'val_acc': [],
'test_loss': -1,
'test_acc': -1,
'model_filename': args.model_state_file}
def update_train_state(args, model, train_state):
"""Handle the training state updates.
Components:
- Early Stopping: Prevent overfitting.
- Model Checkpoint: Model is saved if the model is better
:param args: main arguments
:param model: model to train
:param train_state: a dictionary representing the training state values
:returns:
a new train_state
"""
# Save one model at least
if train_state['epoch_index'] == 0:
torch.save(model.state_dict(), train_state['model_filename'])
train_state['stop_early'] = False
# Save model if performance improved
elif train_state['epoch_index'] >= 1:
loss_tm1, loss_t = train_state['val_loss'][-2:]
# If loss worsened
if loss_t >= train_state['early_stopping_best_val']:
# Update step
train_state['early_stopping_step'] += 1
# Loss decreased
else:
# Save the best model
if loss_t < train_state['early_stopping_best_val']:
torch.save(model.state_dict(), train_state['model_filename'])
# Reset early stopping step
train_state['early_stopping_step'] = 0
# Stop early ?
train_state['stop_early'] = \
train_state['early_stopping_step'] >= args.early_stopping_criteria
return train_state
def compute_accuracy(y_pred, y_target):
y_target = y_target.cpu()
y_pred_indices = (torch.sigmoid(y_pred)>0.5).cpu().long()#.max(dim=1)[1]
n_correct = torch.eq(y_pred_indices, y_target).sum().item()
return n_correct / len(y_pred_indices) * 100
def set_seed_everywhere(seed, cuda):
np.random.seed(seed)
torch.manual_seed(seed)
if cuda:
torch.cuda.manual_seed_all(seed)
def handle_dirs(dirpath):
if not os.path.exists(dirpath):
os.makedirs(dirpath)
args = Namespace(
# Data and Path information
frequency_cutoff=25,
model_state_file='model.pth',
review_csv='data/yelp/reviews_with_splits_lite.csv',
# review_csv='data/yelp/reviews_with_splits_full.csv',
save_dir='model_storage/ch3/yelp/',
vectorizer_file='vectorizer.json',
# No Model hyper parameters
# Training hyper parameters
batch_size=128,
early_stopping_criteria=5,
learning_rate=0.001,
num_epochs=100,
seed=1337,
# Runtime options
catch_keyboard_interrupt=True,
cuda=True,
expand_filepaths_to_save_dir=True,
reload_from_files=False,
)
if args.expand_filepaths_to_save_dir:
args.vectorizer_file = os.path.join(args.save_dir,
args.vectorizer_file)
args.model_state_file = os.path.join(args.save_dir,
args.model_state_file)
print("Expanded filepaths: ")
print("\t{}".format(args.vectorizer_file))
print("\t{}".format(args.model_state_file))
# Check CUDA
if not torch.cuda.is_available():
args.cuda = False
if torch.cuda.device_count() > 1:
print("Pouzivam", torch.cuda.device_count(), "graficke karty!")
args.device = torch.device("cuda" if args.cuda else "cpu")
# Set seed for reproducibility
set_seed_everywhere(args.seed, args.cuda)
# handle dirs
handle_dirs(args.save_dir)
if args.reload_from_files:
# training from a checkpoint
print("Loading dataset and vectorizer")
dataset = ReviewDataset.load_dataset_and_load_vectorizer(args.review_csv,
args.vectorizer_file)
else:
print("Loading dataset and creating vectorizer")
# create dataset and vectorizer
dataset = ReviewDataset.load_dataset_and_make_vectorizer(args.review_csv)
dataset.save_vectorizer(args.vectorizer_file)
vectorizer = dataset.get_vectorizer()
classifier = ReviewClassifier(num_features=len(vectorizer.review_vocab))
classifier = nn.DataParallel(classifier)
classifier = classifier.to(args.device)
loss_func = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(classifier.parameters(), lr=args.learning_rate)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer=optimizer,
mode='min', factor=0.5,
patience=1)
train_state = make_train_state(args)
epoch_bar = tqdm(desc='training routine',
total=args.num_epochs,
position=0)
dataset.set_split('train')
train_bar = tqdm(desc='split=train',
total=dataset.get_num_batches(args.batch_size),
position=1,
leave=True)
dataset.set_split('val')
val_bar = tqdm(desc='split=val',
total=dataset.get_num_batches(args.batch_size),
position=1,
leave=True)
try:
for epoch_index in range(args.num_epochs):
train_state['epoch_index'] = epoch_index
# Iterate over training dataset
# setup: batch generator, set loss and acc to 0, set train mode on
dataset.set_split('train')
batch_generator = generate_batches(dataset,
batch_size=args.batch_size,
device=args.device)
running_loss = 0.0
running_acc = 0.0
classifier.train()
for batch_index, batch_dict in enumerate(batch_generator):
# the training routine is these 5 steps:
# --------------------------------------
# step 1. zero the gradients
optimizer.zero_grad()
# step 2. compute the output
y_pred = classifier(x_in=batch_dict['x_data'].float())
# step 3. compute the loss
loss = loss_func(y_pred, batch_dict['y_target'].float())
loss_t = loss.item()
running_loss += (loss_t - running_loss) / (batch_index + 1)
# step 4. use loss to produce gradients
loss.backward()
# step 5. use optimizer to take gradient step
optimizer.step()
# -----------------------------------------
# compute the accuracy
acc_t = compute_accuracy(y_pred, batch_dict['y_target'])
running_acc += (acc_t - running_acc) / (batch_index + 1)
# update bar
train_bar.set_postfix(loss=running_loss,
acc=running_acc,
epoch=epoch_index)
train_bar.update()
train_state['train_loss'].append(running_loss)
train_state['train_acc'].append(running_acc)
# Iterate over val dataset
# setup: batch generator, set loss and acc to 0; set eval mode on
dataset.set_split('val')
batch_generator = generate_batches(dataset,
batch_size=args.batch_size,
device=args.device)
running_loss = 0.
running_acc = 0.
classifier.eval()
for batch_index, batch_dict in enumerate(batch_generator):
# compute the output
y_pred = classifier(x_in=batch_dict['x_data'].float())
# step 3. compute the loss
loss = loss_func(y_pred, batch_dict['y_target'].float())
loss_t = loss.item()
running_loss += (loss_t - running_loss) / (batch_index + 1)
# compute the accuracy
acc_t = compute_accuracy(y_pred, batch_dict['y_target'])
running_acc += (acc_t - running_acc) / (batch_index + 1)
val_bar.set_postfix(loss=running_loss,
acc=running_acc,
epoch=epoch_index)
val_bar.update()
train_state['val_loss'].append(running_loss)
train_state['val_acc'].append(running_acc)
train_state = update_train_state(args=args, model=classifier,
train_state=train_state)
scheduler.step(train_state['val_loss'][-1])
train_bar.n = 0
val_bar.n = 0
epoch_bar.update()
if train_state['stop_early']:
break
train_bar.n = 0
val_bar.n = 0
epoch_bar.update()
except KeyboardInterrupt:
print("Exiting loop")
classifier.load_state_dict(torch.load(train_state['model_filename']))
classifier = classifier.to(args.device)
dataset.set_split('test')
batch_generator = generate_batches(dataset,
batch_size=args.batch_size,
device=args.device)
running_loss = 0.
running_acc = 0.
classifier.eval()
for batch_index, batch_dict in enumerate(batch_generator):
# compute the output
y_pred = classifier(x_in=batch_dict['x_data'].float())
# compute the loss
loss = loss_func(y_pred, batch_dict['y_target'].float())
loss_t = loss.item()
running_loss += (loss_t - running_loss) / (batch_index + 1)
# compute the accuracy
acc_t = compute_accuracy(y_pred, batch_dict['y_target'])
running_acc += (acc_t - running_acc) / (batch_index + 1)
train_state['test_loss'] = running_loss
train_state['test_acc'] = running_acc
print("Test loss: {:.3f}".format(train_state['test_loss']))
print("Test Accuracy: {:.2f}".format(train_state['test_acc']))
def preprocess_text(text):
text = text.lower()
text = re.sub(r"([.,!?])", r" \1 ", text)
text = re.sub(r"[^a-zA-Z.,!?]+", r" ", text)
return text
def predict_rating(review, classifier, vectorizer, decision_threshold=0.5):
"""Predict the rating of a review
Args:
review (str): the text of the review
classifier (ReviewClassifier): the trained model
vectorizer (ReviewVectorizer): the corresponding vectorizer
decision_threshold (float): The numerical boundary which separates the rating classes
"""
review = preprocess_text(review)
vectorized_review = torch.tensor(vectorizer.vectorize(review))
result = classifier(vectorized_review.view(1, -1))
probability_value = F.sigmoid(result).item()
index = 1
if probability_value < decision_threshold:
index = 0
return vectorizer.rating_vocab.lookup_index(index)
test_review = "this is a pretty awesome book"
classifier = classifier.cpu()
prediction = predict_rating(test_review, classifier, vectorizer, decision_threshold=0.5)
print("{} -> {}".format(test_review, prediction))
# Sort weights
fc1_weights = classifier.fc1.weight.detach()[0]
_, indices = torch.sort(fc1_weights, dim=0, descending=True)
indices = indices.numpy().tolist()
# Top 20 words
print("Influential words in Positive Reviews:")
print("--------------------------------------")
for i in range(20):
print(vectorizer.review_vocab.lookup_index(indices[i]))
print("====\n\n\n")
# Top 20 negative words
print("Influential words in Negative Reviews:")
print("--------------------------------------")
indices.reverse()
for i in range(20):
print(vectorizer.review_vocab.lookup_index(indices[i]))

View File

@ -1,12 +1,3 @@
---
title: Paralelné spracovanie
published: true
taxonomy:
category: [tp2020]
tag: [gpu,nlp]
author: Lukáš Pokrývka
---
**Paralelné spracovanie** **Paralelné spracovanie**
Systémy na spracovanie prirodzeného jazyka (_z angl. Natural Language Processing_ ďalej už len NLP), boli ešte v nedávnej minulosti založené na sériových algoritmoch, ktoré simulovali spôsob, ktorým ľudia čítajú text slovo za slovom, riadok po riadku [1]. Keďže týmto štýlom boli prezentované všetky gramatické teórie, programátori ich týmto štýlom aj implementovali. Systémy na spracovanie prirodzeného jazyka (_z angl. Natural Language Processing_ ďalej už len NLP), boli ešte v nedávnej minulosti založené na sériových algoritmoch, ktoré simulovali spôsob, ktorým ľudia čítajú text slovo za slovom, riadok po riadku [1]. Keďže týmto štýlom boli prezentované všetky gramatické teórie, programátori ich týmto štýlom aj implementovali.
@ -100,4 +91,4 @@ V porovnaní s Word2vec bol pridaný nový algoritmus. Tento algoritmus berie do
[11]. Joulin A. Grave E. Bojanowski P. et al. Bag of Tricks for Efficient Text Classification. [Online]. 15th Conference of the European Chapter of the Association for Computational Linguistic, EACL 2017 [cit. 11.11.2019] Dostupné na internete: \&lt;[https://arxiv.org/pdf/1607.01759.pdf](https://arxiv.org/pdf/1607.01759.pdf)\&gt; [11]. Joulin A. Grave E. Bojanowski P. et al. Bag of Tricks for Efficient Text Classification. [Online]. 15th Conference of the European Chapter of the Association for Computational Linguistic, EACL 2017 [cit. 11.11.2019] Dostupné na internete: \&lt;[https://arxiv.org/pdf/1607.01759.pdf](https://arxiv.org/pdf/1607.01759.pdf)\&gt;
[12]. Joulin A. Grave E. Bojanowski P. et al. FastText.zip: Compressing Text Classification Models. [Online]. ICLR, 2017. [cit. 11.11.2019] Dostupné na internete: \&lt;[https://arxiv.org/pdf/1612.03651.pdf](https://arxiv.org/pdf/1612.03651.pdf)\&gt; [12]. Joulin A. Grave E. Bojanowski P. et al. FastText.zip: Compressing Text Classification Models. [Online]. ICLR, 2017. [cit. 11.11.2019] Dostupné na internete: \&lt;[https://arxiv.org/pdf/1612.03651.pdf](https://arxiv.org/pdf/1612.03651.pdf)\&gt;

View File

@ -1,133 +0,0 @@
---
title: Márk Fehér
published: true
taxonomy:
category: [dp2022]
tag: [scikit,nlp,klasifikácia]
author: Daniel Hladek
---
# Diplomová práca 2022
Názov diplomovej práce: Klasifikácia textu metódami strojového učenia
- [GIT repozitár](https://git.kemt.fei.tuke.sk/mf425hk/dp2022)
## Návrh na zadanie DP
1. Vypracujte prehľad metód klasifikácie textu metódami strojového učenia.
2. Pripravte slovenské trénovacie dáta vo vhodnom formáte a natrénujte viacero modelov pre klasifikáciu textu do viacerých kategórií
3. Navrhnite, vykonajte a vyhodnoťte experimenty pre porovnanie presnosti klasifikácie textu.
4. Navrhnite zlepšenia presnosti klasifikácie textu.
18.3.
- Práca na texte pokračuje
- Podarilo sa spustiť finetning huggingface glue s scnc datasetom.
Úlohy:
- Pokračovať v texte.
- LSTM trénovanie urobené, výsledky sú v práci.
- Pokúsiť sa urobiť dataset interface na vlastné dáta.
4.3.2022
- Stretnutie bolo aj minulý týždeň.
- LSTM trénovanie beží (skoro ukončené).
- SlovakBert na colab prvé výsledky cca 65 percent na scnc (asi tam je chyba).
- Práca na texte pokračuje.
- Vedúcim dodaný skript na scnc datasets rozhranie
- Vedúcim dodaný skript na trénovanie run_glue.py
- Dodaný skript na inštaláciu pytorch a cuda 11.3
Úlohy:
- Práca na texte - sumarizácia experimentov do tabuľky
- Vyskúšať dotrénovanie na idoc pomocou dodaných skriptov.
- Na trénovanie na pozadí použiť `tmux a -t 0`.
## Diplomový projekt 2021
Stretnutie 3.12.
- Dopracované vyhodnotenie pomocou SCNC. Výsledkom je konfúzna matica a grafy presnosti so štatistickými modelmi.
- Rozpracovaná klasifikácia LSTM (Keras).
Úlohy:
- Pridať klasifikáciu pomocou Huggingface Transformers, model SlovakBert, multilingualBert, alebo aj iné multilinguálne modely.
- dokončiť LSTM.
- Pokračovať na textovej časti.
- Zobrazte aj F1
Stretnutie 5.11.2021
- Práca na texte, štúdium literatúry
- pridané kódy na GIT
Úlohy:
- Zopakujte experimenty na korpuse scnc. Slovak Categorized News Corpus.
- Pokračujte v otvorených úlohách
- Upravte skripty do opakovateľnej podoby, pripravte dokumentáciu k skriptom.
Stretnutie 15.10.
- trénovanie pomocou LSTM, zatiaľ nie je na gite
- písanie do šabóny práce (cca 35 strán).
Úlohy:
- Doplniť na GIT.
- Zabrániť overfittingu LSTM. Early stopping alebo dropout.
Stretnutie 1.10.
Stav:
- modifikácia trénovacích skriptov na vypisovanie pomocných štatistík.
- Vytvorený GIT repozitár
- Práca na text (cca 22 strán)
- Pridaná referenčná literatúra.
Úlohy:
- [x] Stiahnite si šablónu práce a vložte text čo máte pripravené, vrátane bibliografie.
- [x] Doplňte zdrojové kódy na GITe, tak aby boli opakovateľné.
- [x] Zoznam knižníc zapíšte do súboru requirements.txt.
- Alebo zapíšte zoznam conda balíčkov.
- Vyberte jednu úlohu zo zásobníka a vypracujte ju.
Zásobník úloh:
- Vyskúšajte klasifikáciu pomocou neurónových sietí.
- Vytvorte web demo pomocou Docker
- [x] Skúste klasifikáciu pomocou neurónovej siete.
Stretnutie 23.9.
Stav:
- vypracovaný draft diplomovej práce
- pripravené dáta z BeautifulSoup - z rôznych webov (sme.sk)
- vypracované experimenty pomocou scikit-learn na klasifikátoroch:
- multinomial Bayes
- random forest
- support vector machine
- Stochastic Gradient Descent Classifier
- k-neighbours
- decision tree
- vypracované vyhodnotenie pomocou konfúznej matice,
Ciele na ďalšie stretnutie:
- Vytvoríte si repozitár dp2022 na školskom gite, kde dáte dáta, zdrojové kódy aj texty.
- Vybrať jeden odborný článok alebo knihu o klasifikácii textu a vypracujte poznámky.

View File

@ -3,477 +3,13 @@ title: Maroš Harahus
published: true published: true
taxonomy: taxonomy:
category: [dp2021,bp2019] category: [dp2021,bp2019]
tag: [spelling,spacy,nlp] tag: [spacy,nlp]
author: Daniel Hladek author: Daniel Hladek
--- ---
# Maroš Harahus # Maroš Harahus
- [Git repozitár ai4steel](https://git.kemt.fei.tuke.sk/ai4steel/ai4steel) (pre členov skupiny)
- [GIT repozitár s poznámkami](https://git.kemt.fei.tuke.sk/mh496vd/Doktorandske) (súkromný)
## Dizertačná práca
v roku 2023/24
Automatické opravy textu a spracovanie prirodzeného jazyka
Ciele:
- Zverejniť a obhájiť minimovku
- Napísať dizertačnú prácu
- Publikovať 2 články triedy Q2-Q3
Súvisiaca BP [Vladyslav Krupko](/students/2020/vladyslav_krupko)
## Druhý rok doktorandského štúdia
Ciele:
- *Publikovanie článku Q2/Q3* - podmienka pre pokračovanie v štúdiu.
- *Obhájiť minimovku*. Minimovka by mala obsahovať definíciu riešenej úlohy, prehľad problematiky, tézy dizertačnej práce - vedecké prínosy.
- Poskytnite najnovší prehľad.
- Popísať vedecký prínos dizertačnej práce
- Zverejniť min. 1 príspevok na školskej konferencii.
- Publikovať min. 1 riadny konferenčný príspevok.
- Pripraviť demo.
- Pomáhať s výukou, projektami a výskumom.
### Návrh na tézy dizertačnej práce
Automatické opravy textu pri spracovaní prirodzeného jazyka
Hlavným cieľom dizertačnej práce je návrh, implementácia a overenie modelu pre automatickú opravu textov.
Na splnenie tohto cieľa je potrebné vykonať tieto úlohy:
1. Analyzovať súčasný stav modelov pre opravu gramatických chýb a preklepov.
2. Vybrať vhodné metódy a navrhnúť vlastný model pre automatickú opravu textov v slovenskom jazyku.
3. Navrhnúť a pripraviť metódu augumentácie dát generovaním chýb v texte.
4. Zozbierať dáta a pripraviť ich do podoby vhodnej na overenie modelu pre automatickú opravu slovenského textu.
5. Navrhnúť a vykonať viacero experimentov pre overenie a porovnanie navrhnutého modelu.
Plán činosti na semester:
1. Prediskutovať a vybrať definitívnu tému. Obidve témy sú komplikované.
- Trénovanie jazykových modelov. Cieľom by bolo zlepšenie jazykového modelovania.
- [x] Dá sa nadviazať na existujúce trénovacie skripty.
- [x] Dá sa využiť webový korpus.
- [x] Dá sa využiť naša GPU infraštruktúra. (Na trénovanie menších modelov)
- [x] Veľký praktický prínos.
- [ ] Teoretický prínos je otázny.
- [ ] Naša infraštruktúra je asi slabá na väčšie modely.
- Oprava gramatických chýb.
- [x] Dá sa nadviazať na "spelling correction" výskum a skripty.
- [x] Teoretický prínos je väčší.
- [x] Trénovanie by bolo jednoduchšie na našom HW.
- Posledné review je z [2020](https://scholar.google.sk/scholar?hl=en&as_sdt=0%2C5&q=grammatical+error+correction+survey&btnG=)
2. Napísať prehľadový článok.
- Prečítať existujúce prehľady na danú tému. Zistitť ako boli napísané, kde boli uverejnené, čo je ich prínos. Je dobré použiť metodiku https://www.prisma-statement.org//
- Identifikovať v čom by bol náš prehľad originálny a kde by bolo možné uverejniť.
- Prečítať a zotriediť aspoň 200 článkov na danú tému.
- Zistiť, aké metódy, datasety a spôsoby vyhodnotenia sa používajú.
- Rozšíriť prehľadový článok do formy minimovky.
3. Priebežne pracovať na experimentoch.
- Vybrať vhodnú dátovú množinu a metriku vyhodotenia.
- Vybrať základnú metódu a vyhodnotiť.
- Vyskúšať modifikáciu základnej metódy a vyhodotiť.
4. Napísať 2 konferenčné články.
- Písať si poznámky pri experimentoch.
- Predbežné experimenty zverejniť v krátkom článku.
- Prediskutovať spôsob financovania.
Stretnutie 27.10.
Stav:
- Prečítaných a spoznámkovaných cca 4O článkov na tému "Grammar Error Correction".
- Experimenty strojový preklad s Fairseq. Z toho vznikol článok SAMI.
- Poznámky o Transfer Leaarning. Preštudované GPT3.
- Sú rozpracované ďalšie modely pre strojový preklad. Česko-slovenský.
- https://github.com/KaushalBajaj11/GEC--Grammatical-Error-Correction
- https://github.com/LukasStankevicius/Towards-Lithuanian-Grammatical-Error-Correction
- https://github.com/yuantiku/fairseq-gec
Úlohy:
- Rozbehať fairseq GEC a porozmýšľať ako by a to dalo zlepšiť.
- Pozrieť si prehľad https://scholar.google.sk/scholar?hl=en&as_sdt=0%2C5&q=question+generation&btnG=&oq=question+ge a napísať niekoľko poznámok. Vedeli by sme nájsť prínos?
Nápady:
- Smerovať to na inú generatívnu úlohu podobnú strojovému prekladu. Napríklad "Question generation".
- question generation by sa dalo použiť na zlepšenie QA-IR systémov.
- Možno "multilingual question generation"?
Stretnutie 9.9.2022
Stav:
Počas prázdnin sa pracovalo na experimentoch s fairseq - strojový preklad a Spacy trénovanie, štúdium literatúry.
Úlohy:
- [x] Prečítať niekoľko prehľadov na tému Grammar Correction, zistiť ako sú napísané a čo je v nich napísané.
- [x] Prečítať niekoľko prehľadov (survey) na tému Neural Language Modelling - BERT Type models. Zistiť, kde je priestor na vedecký prínos.
- [x] Zistiť čo je to Transfer Learning. https://ieeexplore.ieee.org/abstract/document/9134370
- Na obe témy vyhľadať a prečítať niekoľko článkov. Uložiť záznam do databázy, napísať poznánky ku článku.
- [ ] Porozmýšľať nad témou práce.
- [x] Pokračovať v experimenotch fairseq so strojovým prekladom. Vieme pripraviť experiment na tému "spelling", "grammar" alebo training "roberta small", "bart small" na web korpuse? Toto by sa mohlo publikovať na konferenčnom článku do konca roka. treba vybrať dátovú množinu, metodiku vyhodnoteia, metódu trénovania.
- [-] Čítať knihy - Bishop-Patter Recognition. Yang: Transfer Learning.
## Prvý ročník PhD štúdia
29.6.
- Vyskúšané https://github.com/NicGian/text_VAE, podľa článku https://arxiv.org/pdf/1511.06349.pdf
Tento prístup je pôvodne na Question Generation. Využíva GLOVE embeding a VAE. Možno by sa to dalo využiť ako chybový model.
- So skriptami fairseq sú zatiaľ problémy.
Úlohy:
- Pokračovať v otvorených úlohách.
- Vyskúšať tutoriál https://fairseq.readthedocs.io/en/latest/getting_started.html#training-a-new-model.
- Prečítať knihu "Bishop: Pattern Recognition".
17.6.
- Končí financovanie USsteel , je potrebné zmeniť tému.
Úlohy:
- Do konca ďalšieho školského roka submitovať karent článok. To je podmienka pre ďalšie pokračovanie. Článok by mal nadviazať na predošlý výskum v oblasti "spelling correction".
- Preštudovať články:
* Survey of automatic spelling correction
* Learning string distance with smoothing for OCR spelling correction
* Sequence to Sequence Convolutional Neural Network for Automatic Spelling Correction
* Iné súvisiace články. Kľúčové slová: "automatic spelling correction."
- Naučiť sa pracovať s fairseq. Naučiť sa ako funguje strojový preklad.
- Zopakovať experiment OCR Trec-5 Confusion Track. Pridaný prístup do repozitára https://git.kemt.fei.tuke.sk/dano/correct
Zásobník úloh:
- Vymyslieť systém pre opravu gramatických chýb. Aka Grammarly.
- Využiť GAN-VAE sieť na generovanie chybového textu. To by mohlo pomôcť pri učení NS.
3.6.
Úlohy:
- Pripraviť experiment pri ktorom sa vyhodnotia rôzne spôsoby zhlukovania pre rôzne veľkosti priestoru (PCA, k-means, DBSCAN, KernelPCA - to mi padalo). Základ je v súbore embed.py
- Do tabuľky spísať najdôležitejšie a najmenej dôležité parametre pre rôzne konvertory a pre všetky konvertory naraz (furnace-linear.py).
- Vypočítanie presnosti pre každý konvertor zo spojeného modelu, pokračovať.
27.5.
- Našli sme medzné hodnoty pre dáta zo skriptov USS.
- Urobený skript, polynómová transformácia príznakov nepomáha.
- rozrobený skript na generovanie dát GAN.
Otvorené úlohy:
- Pokračovať v otvorených úlohách.
- (3) Urobiť zhlukovanie a pridať informáciu do dátovej množiny. Zistiť, či informácia o zhlukoch zlepšuje presnosť. Informácia o grade umožňuje predikciu.
Stretnutie 20.5.
Otvorené úlohy:
- [ ] (1) Vypočítanie presnosti pre každý konvertor zo spojeného modelu a porovnanie s osobitnými modelmi. Chceme potvrdiť či je spojený model lepší vo všetkých prípadoch.
- [ ] (2) Doplniť fyzické limity pre jednotlivé kolónky do anotácie. Ktoré kolónky nemôžu byť negatívne? Tieto fyzické limity by mali byť zapracované do testu robustnosti.
- [ ] (4) Overenie robustnosti modelu. Vymyslieť testy invariantnosti, ktoré overia ako sa model správa v extrémnej situácii. Urobiť funkciu, kotrá otestuje parametre lineárnej regresie a povie či je model validný. Urobiť funkciu, ktorá navrhne nejaké vstupy a otestuje, či je výstup validný.
Neprioritné úlohy:
- [o] Preskúmať možnosti zníženia rozmeru vstupného priestoru. PCA? alebo zhlukovanie? Zistiť, či vôbec má zmysel používať autoenóder (aj VAE). (Asi to nemá zmysel)
- [x] Vyradenie niektorých kolóniek, podľa koeficientu lineárnej regresie (daniel, funguje ale nezlepšuje presnosť).
- Generovať umelé "extrémne" dáta. Sledovať, ako sa model správa. Extrémne dáta by mali byť fyzicky možné.
Urobené úlohy:
- Hľadanie hyperparametrov pre neurónku a náhodný les.
Report 29.4.2022
- Práca na VE.
- Čítanie článkov.
Report 8.4.2022
- Študovanie teórie
- Práca na VAE kóde rozpracovaný
Report 1.4.2022
- práca na DH neurónovej sieťi
![DH](/uss.PNG)
- študovanie o Deep Belief Network
Stretnutie 28.3.
Úlohy:
- Dokončiť podrobnú anotáciu dát. Aké sú kazuálne súvisosti medzi atribútmi?
- Zopakovať a vylepšiť DH neurónovú sieť na predikciu síry
Zásobník úloh:
- Zvážiť použitie Deep Belief Network.
Report 25.3.2022
- Porovnávanie dát január, február (subor je na gite)
- Hodnotenie ešte nemám spisujem čo tým chcem dosiahnuť ci to ma vôbec zmysel na tom pracovať
Report 18.3.2022
- práca na dátach (príprava na TS, zisťovanie súvislosti, hľadanie hraničných hodnôt)
- študovanie timesesries (https://heartbeat.comet.ml/building-deep-learning-model-to-predict-stock-prices-part-1-2-58e62ad754dd,)
- študovanie o reinforcement learning (https://github.com/dennybritz/reinforcement-learning
https://github.com/ShangtongZhang/reinforcement-learning-an-introduction)
- študovanie o transfer learning
- študovanie feature selection (https://machinelearningmastery.com/feature-selection-machine-learning-python/
https://www.kdnuggets.com/2021/12/alternative-feature-selection-methods-machine-learning.html)
Report 11.3.2022
- Data Preprocessing (inspirácia- https://www.kaggle.com/tajuddinkh/drugs-prediction-data-preprocessing-json-to-csv)
- Analyzovanie dát (inspirácia- https://www.kaggle.com/rounakbanik/ted-data-analysis, https://www.kaggle.com/lostinworlds/analysing-pokemon-dataset
https://www.kaggle.com/kanncaa1/data-sciencetutorial-for-beginners)
- Pracovanie na scripte jsnol --> csv
- Študovanie time series (https://www.machinelearningplus.com/time-series/time-series-analysis-python/
Python Live - 1| Time Series Analysis in Python | Data Science with Python Training | Edureka
Complete Python Pandas Data Science Tutorial! (Reading CSV/Excel files, Sorting, Filtering, Groupby)
https://www.kaggle.com/kashnitsky/topic-9-part-1-time-series-analysis-in-python)
- Time series články (https://ieeexplore.ieee.org/abstract/document/8853246
https://ieeexplore.ieee.org/abstract/document/8931714
https://ieeexplore.ieee.org/abstract/document/8942842
https://arxiv.org/abs/2103.01904)
Working on:
- Neurónovej siete pre GAN time series (stále mam nejaké errory)
- klasickej neuronke
Stretnutie 1.3.2022
Úlohy:
- Zapracovať wandB pre reporting experimentov
- Textovo opísať dáta
Zásobník úloh:
- Vyskúšať predtrénovanie pomocou "historických dát".
Report 25.02.2022
- Prehlaď o jazykových modeloch (BERT, RoBERTa, BART, XLNet, GPT-3) (spracovane poznámky na gite)
- Prehlaď o time-series GAN
- Úprava skriptu z peci jsnol -- > csv
- Skúšanie programu GAN na generovanie obrázkov (na pochopenie ako to funguje)
- Hľadanie vhodnej implementácie na generovanie dát
- Rozpracovaná (veľmi malo) analýza datasetu peci
Stretnutie 2.2.2022
In progress:
- Práca na prehľade článkov VAE-GAN
- na (súkromný) git pridaný náhľad dát a tavný list
- práca na Pandas skripte
Úlohy:
- Dokončiť spacy článok
- Dokončiť prehľad článkov
- Pripraviť prezentáciu na spoločné stretnutie. Do prezentácie uveď čo si sa dozvedel o metódach VAE a GAN. Vysvetli, ako funguje "autoenkóder".
- Napísať krátky blog vrátane odkazov nal literatúru o tom ako funguje neurónový jazykový model (BERT, Roberta, BART, GPT-3, XLNet). Ako funguje? Na čo všetko sa používa?
Stretnutie 18.1.2022
Úlohy:
- [ ] Do git repozitára pridať súbor s podrobným popisom jednotlivých kolóniek v dátovej množine.
- [-] Do git repozitára pridať skript na načítanie dát do Pandas formátu.
- [ ] Vypracovať písomný prehľad metód modelovania procesov v oceliarni (kyslíkového konvertora BOS-basic oxygen steelmaking).
- [x] Nájsť oznam najnovších článkov k vyhľadávaciuemu heslu "gan time series", "vae time series", "sequence modeling,prediction" napísať ku nim komentár (abstrakt z abstraktu) a dať na git.
- [x] Preformulovať zadanie BP Stromp.
- [-] Dokončiť draft článok spacy.
Zásobník úloh:
- [-] Získať prehľad o najnovších metódach NLP - transformers,GAN, VAE a nájsť súvis s modelovaním BOS.
- [ ] nájsť vhodnú implementáciu gan-vae v pythone pre analýzu časových radov alebo postupnosti.
Stretnutie 17.1.2022
- Mame dáta z vysokej pece (500GB)
- Zlepšený konvolučný autoenkóder - dosahuje state-of-the-art.
- Prečítané niečo o transformers a word2vec.
Stretnutie 9.12.2021
- Natrénovaný autoenkóder (feed-forward) pre predikciu celkovej váhy Fe a obsahu S.
- dát je celkom dosť.
Úlohy:
- Vyskúšať iné neurónové siete (keras?).
- Pohľadať dátové množiny, ktoré sú podobné riešenej úlohe. Napr. Open Data.
Stretnutie 26.11.2021
Dáta z US Steel:
- Najprv sa do vysokej pece nasypú suroviny.
- Z tavby sa postupne odoberajú vzorky a meria sa množstvo jednotlivých vzoriek.
- Na konci tavby sa robí finálna analýza taveniny.
- Priebeh procesu závisí od vlastností konkrétnej pece. Sú vlastnosti pece stacionárne? Je možné , že vlastnosti pece sa v čase menia.
- Cieľom je predpovedať výsledky anaýzy finálnej tavby na základe predošlých vzoriek?
- Cieľom je predpovedať výsledky nasledujúceho odberu na základe predchádzajúcich?
- Čo znamená "dobrá tavba"?
- Čo znamená "dobrá predpoveď výsledkov"?
- Je dôležitý čas odbery vzorky?
Zásobník úloh:
- Formulovať problém ako "predikcia časových radov" - sequence prediction.
- Nápad: The analysis of time series : an introduction / Chris Chatfield. 5th ed. Boca Raton : Chapman and Hall, 1996. xii, 283 s. (Chapman & Hall texts in statistical science series). - ISBN 0-412-71640-2 (brož.).
- Prezrieť literatúru a zistiť najnovšie metódy na predikciu.
- Navrhnúť metódu konverzie dát na vektor príznakov. Sú potrebné binárne vektory?
- Navrhnúť metódu výpočtu chybovej funkcie - asi euklidovská vzdialenosť medzi výsledkov a očakávaním.
- Vyskúšať navrhnúť rekurentnú neurónovú sieť - RNN, GRU, LSTM.
- Nápad: Transformer network, Generative Adversarial Network.
- Nápad: Vyskúšať klasické štatistické modely (scikit-learn) - napr. aproximácia polynómom, alebo SVM.
Stretnutie 1.10.
Stav:
- Štúdium základov neurónových sietí
- Úvodné stretnutie s US Steel
Úlohy:
- Vypracovať prehľad aktuálnych metód grafových neurónových sietí
- Nájsť a vyskúšať toolkit na GNN.
- Vytvoriť pracovný repozitár na GITe.
- Naštudovať dáta z US Steel.
- Publikovať diplomovú prácu.
## Diplomová práca 2021
- [CRZP](https://opac.crzp.sk/?fn=detailBiblioForm&sid=ECC3D3F0B3159C4F3216E2027BE4)
- [Zdrojové kódy](https://git.kemt.fei.tuke.sk/mh496vd/diplomovka/)
Názov diplomovej práce: Neurónová morfologická anotácia slovenského jazyka
1. Vysvetlite, ako funguje neurónová morfologická anotácia v knižnici Spacy. Vysvetlite, ako funguje predtrénovanie v knižnici Spacy.
2. Pripravte slovenské trénovacie dáta vo vhodnom formáte a natrénujte základný model morfologickej anotácie pomocou knižnice Spacy.
3. Pripravte model pre morfologickú anotáciu s pomocou predtrénovania.
4. Vyhodnoťte presnosť značkovania modelov vo viacerých experimentoch a navrhnite možné zlepšenia.
## Diplomový projekt 2 2020 ## Diplomový projekt 2 2020
Zásobník úloh:
- skúsiť prezentovať na lokálnej konferencii, (Data, Znalosti and WIKT) alebo fakultný zborník (krátka verzia diplomovky).
- Využiť korpus Multext East pri trénovaní. Vytvoriť mapovanie Multext Tagov na SNK Tagy.
- vykonať a opísať viac experinentov s rôznymi nastaveniami.
Stretnutie 12.2.
Stav:
- Práca na texte
Do ďalšieho stretnutia:
- Opraviť text podľa ústnej spätnej väzby
- Vysvetlite čo je to morfologická anotácia.
- Vystvetlite ako sa robí? Ako funguje spacy neurónová sieť?
- atď. predošlé textové úlohy z 30.10. 2020
Stretnutie 25.1.2021
Stav:
- Urobená prezentácia, spracované experimenty do tabuľky.
Do ďalšieho stretnutia:
- Pracovať na súvislom texte.
Virtuálne stretnutie 6.11.2020
Stav:
- Prečítané (podrobne) 2 články a urobené poznámky. Poznánky sú na GITe.
- Dorobené ďalšie experimenty.
Úlohy do ďalšieho stretnutia:
- Pokračovať v otvorených úlohách.
Virtuálne stretnutie 30.10.2020
Stav:
- Súbory sú na GIte
- Vykonané experimenty, Výsledky experimentov sú v tabuľke
- Návod na spustenie
- Vyriešenie technických problémov. Je k dispozicíí Conda prostredie.
Úlohy na ďalšie stretnutie:
- Preštudovať literatúru na tému "pretrain" a "word embedding"
- [Healthcare NER Models Using Language Model Pretraining](http://ceur-ws.org/Vol-2551/paper-04.pdf)
- [Design and implementation of an open source Greek POS Tagger and Entity Recognizer using spaCy](https://ieeexplore.ieee.org/abstract/document/8909591)
- https://arxiv.org/abs/1909.00505
- https://arxiv.org/abs/1607.04606
- LSTM, recurrent neural network,
- Urobte si poznámky z viacerých čnánkov, poznačte si zdroj a čo ste sa dozvedeli.
- Vykonať viacero experimentov s pretrénovaním - rôzne modely, rôzne veľkosti adaptačných dát a zostaviť tabuľku
- Opísať pretrénovanie, zhrnúť vplyv pretrénovania na trénovanie v krátkom článku cca 10 strán.
Virtuálne stretnutie 8.10.2020
Stav:
- Podarilo sa vykonať pretrénovanie aj trénovanie, prvé výsledky experimentov.
- pretrénovanie funguje na GPU, použila sa verzia spacy 2.2, trénovanie na IDOC
- trénovanie ide lepšie na CPU
- vyskytol sa problém že nevie alokovať viac ako 2GB RAM
- 200 iterácií pretrénovania, 4000 riadkov viet
Úlohy do ďalšieho stretnutia:
- Dať zdrojáky na GIT
- Urobiť porovnanie voči presnosti bez pretrain
- Výsledky dajte do tabuľky - aké parametre ste použili pri trénovaní a pretrénovaí?
- experimenty si poznačte do skriptu aby sa dali zopakovať
- Do článku (do súboru README na GIte) presne opíšte nastavenie experimentu - parametre, dáta a spôsob overenia, aspoň rozpracovať.
- Začnite spisovať teoretickú časť článku, aspoň rozpracovať.
Stretnutie 25.9.2020 Stretnutie 25.9.2020
Stav: Stav:
@ -521,6 +57,18 @@ K zápočtu:
- Porovnajte s presnosťou bez pretrénovania. - Porovnajte s presnosťou bez pretrénovania.
Zásobník úloh:
- Preštudovať literatúru na tému "pretrain" a "word embedding"
- [Healthcare NERModelsUsing Language Model Pretraining](http://ceur-ws.org/Vol-2551/paper-04.pdf)
- [Design and implementation of an open source Greek POS Tagger and Entity Recognizer using spaCy](https://ieeexplore.ieee.org/abstract/document/8909591)
- https://arxiv.org/abs/1909.00505
- https://arxiv.org/abs/1607.04606
- LSTM, recurrent neural network,
- Vykonať viacero experimentov s pretrénovaním - rôzne modely, rôzne veľkosti adaptačných dát a zostaviť tabuľku
- Opísať pretrénovanie, zhrnúť vplyv pretrénovania na trénovanie v krátkom článku cca 10 strán.
- skúsiť prezentovať na lokálnej konferencii, (Data, Znalosti and WIKT) alebo fakultný zborník (krátka verzia diplomovky).
- Využiť korpus Multext East pri trénovaní. Vytvoriť mapovanie Multext Tagov na SNK Tagy.
Virtuálne stretnutie 15.5.2020: Virtuálne stretnutie 15.5.2020:
@ -582,6 +130,15 @@ Stretnutie: 20.2.2020:
## Návrh na zadanie DP
Názov diplomovej práce: Štatistická morfologická anotácia slovenského jazyka
1. Vypracujte prehľad spôsobov morfologickej anotácie slovenského jazyka.
2. Pripravte trénovacie dáta vo vhodnom formáte a natrénujte štatistický model morfologického značkovania
3. Vyhodnoťte presnosť značkovania a navrhnite možné zlepšenia.
## Tímový projekt 2019 ## Tímový projekt 2019
Projektové stránky: Projektové stránky:

View File

@ -1,11 +1,3 @@
---
title: Spracovanie prirodzeného jazyka
published: true
taxonomy:
category: [tp2020]
tag: [spacy,nlp]
author: Maroš Harahus
---
# NLP # NLP
Je založený na umelej inteligencii, ktorá sa zaoberá interakciami medzi počítačom a jazykmi. NLP uľahčuje proces analýzy a Je založený na umelej inteligencii, ktorá sa zaoberá interakciami medzi počítačom a jazykmi. NLP uľahčuje proces analýzy a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@ -2,246 +2,13 @@
title: Patrik Pavlišin title: Patrik Pavlišin
published: true published: true
taxonomy: taxonomy:
category: [dp2022,bp2020,tp2021] category: [dp2021,bp2019]
tag: [nmt,translation,nlp] tag: [translation,nlp]
author: Daniel Hladek author: Daniel Hladek
--- ---
# Patrik Pavlišin # Patrik Pavlišin
# Diplomová práca 2022 ## Bakalárksa práca 2019
Predbežný názov: Neurónový strojový preklad
Návrh na nástroje pre strojový preklad:
- OpenNMT-py
- Fairseq
- Hugging Face Transformers
## Návrh na zadanie diplomovej práce
1. Pripraviť prehľad aktuálnych metód strojového prekladu pomocou neurónových sietí.
2. Vybrať konkrétnu metódu strojového prekladu pomocou neurónových sietí a podrobne ju opísať.
3. Pripraviť vybraný paralelný korpus do vhodnej podoby a pomocou vybranej metódy natrénovať model pre strojový preklad.
4. Vyhodnotiť experimenty a navrhnúť možnosti na zlepšenie.
## Diplomový projekt 2
Ciele na semester:
1. Natrénovať "kvalitný model" na preklad z angličtiny do slovenčiny.
2. Napísať draft diplomovej práce.
Zásobník úloh:
- natrénovať aj iné preklady (z a do češtiny).
18.2.2022
- Beží trénovanie na idoc
Úlohy:
Zmeňte štruktúru práce podľa tohoto myšienkového postupu.
Pridajte nové časti a vyradte nerelevantné časti.
1. Vysvetlite čo je to neurónový strojovyý preklad.
2. Vysvetlite, čo je to neurónová sieť.
3. Povedze aké typy neurónových sietí sa používajú na strojový preklad.
4. Vyberte konkrétnu neurónovú sieť (tú ktorá sa používa v OPennmt) a podrobne opíšte ako funguje.
5. Predstavte Open NMT.
6. Povedzte o dátach ktoré ste použili (dorobiť).
7. Vysvetlite, ako ste pripravili experimenty, ako ste ich spustili a aké výlsekdy ste dosiahli (dorobiť).
8. Sumarizujte experimenty a určite miesto na zlepšenie (dorobiť).
27.1.2022
- Hotovy model na CZ-EN
Úlohy:
- Aktualizujte trénovacie skripty na gite.
- Rozbehajte GPU trénovnaie na idoc. Vyriešte technické problémy.
- Natrénujte viacero modelov s viacerými nastaveniami a výsledkyž dajte do tabuľky. Ku každému modelu si poznačte výsledné BLEU. Výsledky skontrolujte aj osobne.
- Pokračujte na texte práce. Odstrániť nezmyselné časti. Pri ďalšom stretnutí prezentujte stav textovej časti.
17.12.2021
- Vylepšený draft práce.
- Nové vyhodnotenie a výsledky modelu.
- Trénovanie na česko-anglickom korpuse.
Úlohy:
- natrénujte na tomto EN-SK korpuse: https://lindat.mff.cuni.cz/repository/xmlui/handle/11858/00-097C-0000-0006-AAE0-A
- Pokračujte v otvorených úlohách z minulého stretnutia.
- Výsledky experiemntov zhrňte do tabuľky. Poznačte architektúru neurónovej siete, parametre trénovania.
- Skúste rozbehať trénovanie na GPU.
1. Vytvorte nové conda prostredie. Spustite:
conda install pytorch=1.8.1cudatoolkit=10.1 -c pytorch
2. Nainštalujte OpenNMT.
26.11.2021
Natrénovaný prvý model OpenNMT na korpuse europarlament.
Výslekdy vyzerajú OK, ale sú chaotické. Pravdepodobne bolo trénovanie prerušené predčasne. Zatiaľ nefunguje trénovanie na GPU.
Úlohy:
- Pokračujte v trénovaní Europarl. Modelu, skúste vylepšiť výsledky.
- Trénovanie robte opakovateľným spôsobom - dajte na git nastavenia a trénovacie skripty, ale nie textové dáta. Len poznačte odkiaľ ste ich stiahli.
- Pokračujte v práci na texte - myšlienky by mali logicky nasledovať za sebou.
12.11.2021
Práca na texte
Úlohy:
- Zlepšiť štruktúru práce
- Dotrénovať a vyhodnotiť model slovenčina-angličtina.
28.10.
Stav:
- Vypracovaný draft článoku o transformeroch, treba vylepšiť. Článok je na ZP Wiki
- Problém pri príprave trénovacích dát.
Úlohy:
- Naučte sa pripravovať textové dáta. Prejdite si knihu https://diveintopython3.net aspoň do 4 kapitoly. Vypracujte všetky príklady z nej.
- Pokračujte v práci na článku. Treba doplniť odkazy do textu. Treba zlepšiť štruktúru a logickú náväznosť viet. Vysvetlite neznáme pojmy.
- Zmente článok na draft diplomovej práce. Vypracujte osnovu diplomovej práce - napíšte názvy kapitol a ich obsah. Zaraďte tam text o transformeroch ktorý ste vypracovali.
- Pripravte textové dáta do vhodnej podoby a spustite trénovanie.
Stretnutie 30.9.
Stav:
- Len začaté štúdium článkov, ostatné úlohy zostávajú otvorené.
Úlohy:
- Pokračovať v úlohách zo 17.6.
- Na trénovanie použite OpenNMT.
- Vytvorte si repozitár dp2022 a do neho dajte skripty na natrénovanie modelov. Nedávajte tam veľké dáta, ale dajte tam skript na ich stiahnutie, napr. pomocou wget.
- prepare-env.sh : ako ste vyttvorili Vaše prostredie - nainštalovali programy.
- download-data.sh: ako ste získali dáta
- prepare-data.sh: ako ste pripravili dáta
- train1.sh: ako ste natrénovali model
- evaluate1.sh: ako ste vyhodnotili model.
## Diplomový projekt 1
Stretnutie 17.6.
- Splnené podmienky na zápočet.
- Napísaný tutoriál a úvod do NMT
Úlohy:
- Skúste zlepšiť presnosť strojového prekladu. Modifikujte setup tak, aby sa výsledky zlepšili.
- Preštudujte si architektúru neurónovej siete typu Transformer. Prečítajte si blogy a urobte poznámky,
Prečítajte si článok s názvom "Attention is all you need.". Urobte si poznámky čo ste sa dozvedeli.
- Preštudujte si architektúru typu enkóder-dekóder. Urobte si poznámky čo ste sa dozvedeli a z akých zdrojov.
Využívajte vyhľadávač Scholar.
Stretnutie 9.4.
Stav:
- Problém pri OpenNMT-py Quickstart - Nvidia driver nefunguje v prostredí WSL1. riešenie - vypnúť GPU training alebo trénovať na IDOC.
- Napísané poznámky o NMT na cca 3 strany, na zpwiki
Úlohy:
- Vysvetlite vlastnými slovami čo to je neurónová sieť. Ak sa niečo dozviete z článku, povedzte vlastnými slovami čo ste sa dozvedeli a z akého článku ste sa to dozvedeli.
- Vysvetlite vlastnými slovami ako prebieha neurónový preklad. Vysvetlite, ako sa text premení do formy ktorá je zrozumiteľná pre neurónovú sieť. Vysvetlite čo je výstupom neurónovej siete a ako sa ten výstup premení na text.
- Napíšte to do markdown súboru na zpwiki.
- Dokončite tutoriál OpenNMT-py.
Stretnutie 12.3.
Stav:
- poznámky k článku "Googles neural machine translation system .
- Śtúdium ostatných článkov pokračuje.
- Problém - aktuálna verzia OpenNMT-py nefunguje s pythonom 3.5. Je potrebné využit Anacondu.
Úlohy:
- Vypracujte poznámky k článkom
- Pokračujte v tutoriáli OpenNMT-py cez prostredie Anaconda.
- Poznámky pridajte na zpWiki vo formáte Markdown
Stretnutie 18.2.
Stav:
- Vypracovaný článok z minulého semestra
Úlohy:
- V linuxovom prostredí (napr. idoc) si vytvorte python virtuálne prostredie:
- vytvorte si adresár s projektom
- mkdir ./venv
- python3 -m virtualenv ./venv
- source ./venv/bin/activate
- Keď skončíte: deactivate
- Prejdite si tutoriál https://github.com/OpenNMT/OpenNMT-py
- Prečítjte si články z https://opennmt.net/OpenNMT-py/ref.html
- Vypracujte poznámky k článku "Googles neural machine translation system: bridging the gap between human and machine translation. arXiv preprint arXiv:1609.08144, 2016". Čo ste sa z čánku dozvedeli?
## Tímový projekt 2021
Ciel:
- vytvoriť článok s témou "Štatistický preklad".
- vytvoriť článok, publikovateľný na konferencii
Virtuálne stretnutie 4.12.2020
Stav:
- Vypracovaný prehľad na tri strany, prečítané 3 články.
- Prístup treba zlepšiť.
Úlohy na ďalšie stretnutie:
- Pokračujte v písaní. Prečítajte si min. 10 článok na tému strojový preklad a ku každému napíšte čo ste sa dozvedeli.
- Zamerajte sa na články o neurónovom strojovom preklade. Zistite a napíšte čo je to archtektúra encoder-decoder. Napíšte aké neurónové siete sa najviac používajú.
- Pozrite [Ondrej Megela](/students/2018/ondrej_megela), [Martin Jancura](/students/2017/martin_jancura), [Dominik Nagy](/students/2016/dominik_nagy)
- Navrhnite zadanie diplomovej práce.
Virtuálne stretnutie 2.10.2020
Prečítajte si a vypracujte poznámky:
- https://apps.dtic.mil/sti/pdfs/ADA466330.pdf
- https://arxiv.org/abs/1409.1259
Pozrite si aj niektoré články ktoré sú v bibliografii.
Zistitie, aké najnovšie voľne šíriteľné systémy na strojový preklad sú dostupné a napíšte ku nim krátku charakteristiku. Na akej metóde sú založené? V ktorom článku je táto metóda opísaná? Používajte scopus alebo scholar.
Zapíšte si zaujímavé bibliografické odkazy a poznačte si, čo zaujímavé sa v nich nachádza.
## Bakalárska práca 2020
https://opac.crzp.sk/?fn=detailBiblioForm&sid=AFB64E0160B4F4E92146D39F9648
Názov bakalárskej práce: Metódy automatického prekladu Názov bakalárskej práce: Metódy automatického prekladu

View File

@ -1 +0,0 @@
data downloaded from " https://lindat.mff.cuni.cz/repository/xmlui/discover "

View File

@ -1 +0,0 @@
nohup perl tools/multi-bleu.perl dp2022/sk-en/europarl-v7.clean.sk-en.sk < dp2022/sk-en/pred_10000.txt2 > prekladsk&

View File

@ -1,11 +0,0 @@
import sys
for l in sys.stdin:
line = l.rstrip()
tokens = line.split()
result = []
for token in tokens:
items = token.split("|")
print(items)
result.append(items[0])
print(" ".join(result))

View File

@ -1,6 +0,0 @@
onmt_build_vocab -config dp2022/sk-en/trainsk.yaml -n_sample 10000
onmt_train -config dp2022/sk-en/trainsk.yaml
onmt_translate -model dp2022/sk-en/run/model_step_1000.pt -src dp2022/sk-en/src-test.txt -output dp2022/sk-en/pred_1000.txt -verbose

View File

@ -1,33 +0,0 @@
# train.yaml
## Where the samples will be written
save_data: dp2022/run2/example
## Where the vocab(s) will be written
src_vocab: dp2022/run2/example.vocab.src
tgt_vocab: dp2022/run2/example.vocab.tgt
# Prevent overwriting existing files in the folder
overwrite: False
# Corpus opts
data:
corpus_1:
path_src: dp2022/europarl-v7.sk-en.en
path_tgt: dp2022/europarl-v7.sk-en.sk
valid:
path_src: dp2022/europarl-v7.clean.sk-en.en
path_tgt: dp2022/europarl-v7.clean.sk-en.sk
# Vocabulary files that were just created
src_vocab: dp2022/run2/example.vocab.src
tgt_vocab: dp2022/run2/example.vocab.tgt
# Train on a single GPU
world_size: 1
gpu_ranks: [0]
# Where to save the checkpoints
save_model: dp2022/run2/model
save_checkpoint_steps: 1000
train_steps: 20000
valid_steps: 10000

View File

@ -1,173 +0,0 @@
## Úvod
Neurónový strojový preklad (NMT) je prístup k strojovému prekladu, ktorý využíva umelú neurónovú sieť na predpovedanie pravdepodobnosti postupnosti slov, typicky modelovaním celých viet v jednom integrovanom modeli. NMT nie je drastickým krokom nad rámec toho, čo sa tradične robí v štatistickom strojovom preklade (SMT). Štruktúra modelov je jednoduchšia ako frázové modely. Neexistuje žiadny samostatný jazykový model, prekladový model a model zmeny poradia, ale iba jeden sekvenčný model, ktorý predpovedá jedno slovo po druhom. Táto predikcia postupnosti je však podmienená celou zdrojovou vetou a celou už vyprodukovanou cieľovou sekvenciou.
## Neurónová sieť
Neurónovú sieť tvoria neuróny, ktoré sú medzi sebou poprepájané. Všeobecne môžeme poprepájať ľubovoľný počet neurónov, pričom okrem pôvodných vstupov môžu byť za vstupy brané aj výstupy iných neurónov. Počet neurónov a ich vzájomné poprepájanie v sieti určuje tzv. architektúru (topológiu) neurónovej siete. Neurónová sieť sa v čase vyvíja, preto je potrebné celkovú dynamiku neurónovej siete rozdeliť do troch dynamík a potom uvažovať tri režimy práce siete: organizačná (zmena topológie), aktívna (zmena stavu) a adaptívna (zmena konfigurácie). Jednotlivé dynamiky neurónovej siete sú obvykle zadané počiatočným stavom a matematickou rovnicou, resp. pravidlom, ktoré určuje vývoj príslušnej charakteristiky sieti v čase.
Synaptické váhy patria medzi dôležité časti Neurónovej siete. Tieto váhy ovplyvňujú celú sieť tým, že ovplyvňujú vstupy do neurónov a tým aj ich stavy. Synaptické váhy medzi neurónmi i, j označujeme wi,j. Najdôležitejším momentom pri činnosti Neurónovej siete je práve zmena váh delta wi,j. Vo všeobecnosti ich rozdeľujeme na kladné (excitačné) a záporné (inhibičné).
Neurón je základným prvkom Neurónovej siete. Rozdiel medzi umelým a ľudským je v tom, že v súčasnosti je možné vytvoriť oveľa rýchlejší neurón, ako ľudský. Avšak čo sa týka počtu neurónov, ľudský mozog sa skladá z 10 na 11 až 10 na 14 neurónov a každý neurón má 10 na 3 až 10 na 4 neurónových spojení. V súčasnej dobe nie je možné nasimulovať v rámci jednej Neurónovej siete také množstvo neurónov. V tomto ohľade je ľudský mozog podstatne silnejší oproti nasimulovanej Neurónovej siete. [3]
|![](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/patrik_pavlisin/tp20/neuronova%20siet.png)|
|:--:|
|Obr 1. základné zobrazenie Neurónovej siete|
Činnosť Neurónových sieti rozdeľujeme na :
- Fáza učenia v tejto fáze sa znalosti ukladajú do synaptických váh neurónovej siete, ktoré sa menia podľa stanovených pravidiel počas procesu učenia. V prípade neurónových sieti môžeme pojem učenie chápať ako adaptáciu neurónových sieti, teda zbieranie a uchovávanie poznatkov.
- Fáza života dochádza ku kontrole a využitiu nadobudnutých poznatkov na riešenie určitého problému (napr. transformáciu signálov, problémy riadenia procesov, aproximáciu funkcií, klasifikácia do tried a podobne). V tejto fáze sa už nemenia synaptické váhy.
Neurónová sieť by vo všeobecnosti mala mať pravidelnú štruktúru pre ľahší popis a analýzu. Viacvrstvová štruktúra patrí k pomerne dobre preskúmaným štruktúram Neurónovej siete a skladá sa z :
- Vstupná vrstva (angl. Input layer) na vstup prichádzajú len vzorky z vonkajšieho sveta a výstupy posiela k ďalším neurónom
- Skrytá vrstva (angl. Hidden layer) vstupom sú neuróny z ostatných neurónov z vonkajšieho sveta (pomocou prahového prepojenia) a výstupy posiela opäť ďalším neurónom
- Výstupná vrstva (angl. Output layer) prijíma vstupy z iných neurónov a výstupy posiela do vonkajšieho prostredia
Reprezentatívna vzorka je jedným zo základných pojmov Neurónových sieti. Jedná sa o usporiadanú množinu usporiadaných dvojíc, pričom ku každému vstupu je priradený vyhovujúci výstup. Poznáme dva typy reprezentatívnych vzoriek :
- Trénovaciu vzorku využíva sa pri fáze učenia (pri tejto vzorke je dôležité vybrať tú najvhodnejšiu a najkvalitnejšiu, pretože získané poznatky sa ukladajú učením do synaptických váh neurónovej siete)
- Testovacia vzorka používa sa vo fáze života
Topológiu Neurónových sieti rozdeľujeme na :
- Dopredné Neurónové siete (angl. feed-forward neural network), ktoré sa ďalej delia na kontrolované a nekontrolované učenie, v tejto topológií je signál šírený iba jedným smerom. U dopredných sietí neexistujú spojenia medzi neurónmi tej istej vrstvy, ani medzi neurónmi vzdialených vrstiev.
|![](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/patrik_pavlisin/tp20/dopredn%c3%bd%20nn.png)|
|:--:|
|Obr 2. Dopredná Neurónová sieť|
- Rekurentné Neurónové siete (angl. recurrent neural network), ktoré sa ďalej delia na kontrolované a nekontrolované učenie, signál sa šíry obojsmerne (neuróny sa môžu správať ako vstupné aj výstupné). [3]
|![](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/patrik_pavlisin/tp20/recurrent%20neural%20network.png)|
|:--:|
|Obr 3. Rekurentná Neurónová sieť|
**Exploding and vanishing gradient problems**
V strojovom učení sa s problémom miznúceho gradientu stretávame pri trénovaní umelých neurónových sietí metódami učenia založenými na gradiente a spätnou propagáciou. V takýchto metódach dostáva každá z váh neurónovej siete aktualizáciu úmernú čiastočnej derivácii chybovej funkcie vzhľadom na aktuálnu váhu v každej iterácii trénovania. Problém je v tom, že v niektorých prípadoch bude gradient zbytočne malý, čo účinne zabráni tomu, aby váha zmenila svoju hodnotu. V najhoršom prípade to môže úplne zabrániť neurónovej sieti v ďalšom trénovaní. Ako jeden príklad príčiny problému majú tradičné aktivačné funkcie, ako je hyperbolická tangenciálna funkcia, gradienty v rozsahu (0, 1) a spätné šírenie počíta gradienty podľa pravidla reťazca. To má za následok znásobenie n týchto malých čísel na výpočet gradientov prvých vrstiev v sieti n-vrstiev, čo znamená, že gradient (chybový signál) exponenciálne klesá s n, zatiaľ čo prvé vrstvy trénujú veľmi pomaly.
Ak sa použijú aktivačné funkcie, ktorých deriváty môžu nadobúdať väčšie hodnoty, riskujeme, že narazíme na súvisiaci problém s explodujúcim gradientom. Problém s explodujúcim gradientom je problém, ktorý sa môže vyskytnúť pri trénovaní umelých neurónových sietí pomocou gradientného klesania spätným šírením. Problém s explodujúcim gradientom je možné vyriešiť prepracovaním sieťového modelu, použitím usmernenej lineárnej aktivácie, využitím sietí s LSTM, orezaním gradientu a regularizáciou váh. Ďalším riešením problému s explodujúcim gradientom je zabrániť tomu, aby sa gradienty zmenili na 0, a to pomocou procesu známeho ako orezávanie gradientov, ktorý kladie na každý gradient vopred definovanú hranicu. Orezávanie prechodov zaisťuje, že prechody budú smerovať rovnakým smerom, ale s kratšími dĺžkami. [2]
**Neurónový preklad**
Neurónový strojový preklad vo všeobecnosti zahŕňa všetky typy strojového prekladu, kde sa na predpovedanie postupnosti čísel používa umelá neurónová sieť. V prípade prekladu je každé slovo vo vstupnej vete zakódované na číslo, ktoré neurónová sieť prepošle do výslednej postupnosti čísel predstavujúcich preloženú cieľovú vetu. Prekladový model následne funguje prostredníctvom zložitého matematického vzorca (reprezentovaného ako neurónová sieť). Tento vzorec prijíma reťazec čísel ako vstupy a výstupy výsledného reťazca čísel. Parametre tejto neurónovej siete sú vytvárané a vylepšované trénovaním siete s miliónmi vetných párov. Každý takýto pár viet tak mierne upravuje a vylepšuje neurónovú sieť, keď prechádza každým vetným párom pomocou algoritmu nazývaným spätné šírenie. [3]
**Systém neurónového strojového prekladu spoločnosti Google**
Neurónový strojový preklad (angl. NMT - neural machine translation) používa end-to-end učenie pre strojový preklad, ktorého cieľom je prekonať slabé stránky konvenčných frázových systémov. End-to-end učenie je typ Deep Learningu, v ktorom sú všetky parametre trénované spoločne, a nie krok za krokom. Bohužiaľ systémy NMT výpočtovo náročné počas trénovania ako aj pri samotnom preklade (je to kvôli ochrane napr. pri vysokom množstve veľkých súborov a veľkých modelov). Niekoľko autorov tiež uviedlo (odkaz na [1]), že systémom NMT chýba robustnosť, najmä keď vstupné vety obsahujú zriedkavé, alebo zastaralé slová. Tieto problémy bránili používaniu NMT v praktických nasadeniach a službách, kde je nevyhnutná presnosť aj rýchlosť.
Spoločnosť Google preto predstavila GNMT (google´s neural machine translation) systém , ktorý sa pokúša vyriešiť mnohé z týchto problémov. Tento model sa skladá z hlbokej siete Long Short-Term Memory (LSTM) s 8 kódovacími a 8 dekódovacími vrstvami, ktoré využívajú zvyškové spojenia, ako aj pozorovacie spojenia zo siete dekodéra ku kódovaciemu zariadeniu. Aby sa zlepšila paralelnosť a tým pádom skrátil čas potrebný na trénovanie, tento mechanizmus pozornosti spája spodnú vrstvu dekodéra s hornou vrstvou kódovacieho zariadenia. Na urýchlenie konečnej rýchlosti prekladu používame pri odvodzovacích výpočtoch aritmetiku s nízkou presnosťou. Aby sa vylepšila práca so zriedkavými slovami, slová sa delia na vstup aj výstup na obmedzenú množinu bežných podslovných jednotiek („wordpieces“). Táto metóda poskytuje dobrú rovnováhu medzi flexibilitou modelov oddelených znakom a účinnosťou modelov oddelených slovom, prirodzene zvláda preklady zriedkavých slov a v konečnom dôsledku zvyšuje celkovú presnosť systému.
Štatistický strojový preklad (SMT - statistical machine translation) je po celé desaťročia dominantnou paradigmou strojového prekladu. Implementáciami SMT sú vo všeobecnosti systémy založené na frázach (PBMT - phrase-based machine translation), ktoré prekladajú postupnosti slov alebo frázy, kde sa môžu dĺžky líšiť. Ešte pred príchodom priameho neurónového strojového prekladu sa neurónové siete s určitým úspechom používali ako súčasť systémov SMT. Možno jeden z najpozoruhodnejších pokusov spočíval v použití spoločného jazykového modelu na osvojenie frázových reprezentácií, čo prinieslo pozoruhodné zlepšenie v kombinácii s prekladom založeným na frázach. Tento prístup však vo svojej podstate stále využíva frázové prekladové systémy, a preto dedí ich nedostatky.
O koncepciu end-to-end učenia pre strojový preklad sa v minulosti pokúšali s obmedzeným úspechom. Po mnohých seminárnych prácach v tejto oblasti sa kvalita prekladu NMT priblížila k úrovni frázových prekladových systémov pre bežné výskumné kritériá. V anglickom a francúzskom jazyku WMT14 dosiahol tento systém zlepšenie o 0,5 BLEU (je algoritmus na hodnotenie kvality textu) v porovnaní s najmodernejším frázovým systémom. Odvtedy bolo navrhnutých veľa nových techník na ďalšie vylepšenie NMT ako napríklad použitie mechanizmu pozornosti na riešenie zriedkavých slov, mechanizmu na modelovanie pokrytia prekladu, rôznymi druhmi mechanizmov pozornosti, minimalizáciou strát na úrovni vety.
LSTM sú špeciálny typ Rekurentných neurónových sietí (RNN), ktorý slúži na dosiahnutie dlhodobého kontextu (napr. Pri doplnení chýbajúcej interpunkcie alebo veľkých písmen). Najväčšie využitie LSTM je v oblasti strojového učenia a hlbokého učenia.
Vlastnosti LSTM:
- pripravený spracovať nielen jednoduché dáta, ale aj celé sekvenčné dáta (napr. reč alebo video),
- sú vhodné na klasifikáciu, spracovanie a vytváranie predikcií na základe časových údajov
- LSTM boli definované tak, aby si na rozdiel od RNN vedeli pomôcť s problémom, ktorý sa nazýva „Exploding and vanishing gradient problems“. [1]
**Wordpiece Model**
Tento prístup je založený výlučne na dátach a je zaručené, že pre každú možnú postupnosť znakov vygeneruje deterministickú segmentáciu (segmenty používateľov založené na nejakej hypotéze následne sa dáta analyzujú, aby sa zistilo, či sú segmenty zaujímavé a užitočné). Je to podobné ako metóda použitá pri riešení zriedkavých slov v strojovom preklade neurónov. Na spracovanie ľubovoľných slov najskôr rozdelíme slová na slovné druhy, ktoré sú dané trénovaným modelom slovných spojení. Pred cvičením modelu sú pridané špeciálne symboly hraníc slov, aby bolo možné pôvodnú sekvenciu slov získať z postupnosti slovných spojení bez nejasností. V čase dekódovania model najskôr vytvorí sekvenciu slovných spojení, ktorá sa potom prevedie na zodpovedajúcu sekvenciu slov.
|![one](https://git.kemt.fei.tuke.sk/KEMT/zpwiki/raw/branch/master/pages/students/2016/patrik_pavlisin/tp20/Bez%20n%c3%a1zvu.png)|
|:--:|
|Obr 4. Príklad postupnosti slov a príslušná postupnosť slovných spojení|
Vo vyššie uvedenom príklade je slovo „Jet“ rozdelené na dve slovné spojenia „_J“ a „et“ a slovo „feud“ je rozdelené na dve slovné spojenia „_fe“ a „ud“. Ostatné slová zostávajú ako jednotlivé slová. „_“ Je špeciálny znak pridaný na označenie začiatku slova.
Wordpiece model sa generuje pomocou prístupu založeného na údajoch, aby sa maximalizovala pravdepodobnosť jazykových modelov cvičných údajov, vzhľadom na vyvíjajúcu sa definíciu slova. Vzhľadom na cvičný korpus a množstvo požadovaných tokenov D je problémom optimalizácie výber wordpieces D tak, aby výsledný korpus bol minimálny v počte wordpieces, ak sú segmentované podľa zvoleného wordpiece modelu. V tejto implementácii používame špeciálny symbol iba na začiatku slov, a nie na oboch koncoch. Počet základných znakov tiež znížime na zvládnuteľný počet v závislosti na údajoch (zhruba 500 pre západné jazyky, viac pre ázijské jazyky). Zistili sme, že použitím celkovej slovnej zásoby medzi 8 000 a 32 000 slovnými jednotkami sa dosahuje dobrá presnosť (BLEU skóre) aj rýchlosť dekódovania pre dané jazykové páry.
V preklade má často zmysel kopírovať zriedkavé názvy entít alebo čísla priamo zo zdroja do cieľa. Na uľahčenie tohto typu priameho kopírovania vždy používame wordpiece model pre zdrojový aj cieľový jazyk. Použitím tohto prístupu je zaručené, že rovnaký reťazec vo zdrojovej a cieľovej vete bude segmentovaný presne rovnakým spôsobom, čo uľahčí systému naučiť sa kopírovať tieto tokeny. Wordpieces dosahujú rovnováhu medzi flexibilitou znakov a efektívnosťou slov. Zistili sme tiež, že naše modely dosahujú lepšie celkové skóre BLEU pri používaní wordpieces - pravdepodobne kvôli tomu, že naše modely teraz efektívne pracujú v podstate s nekonečnou slovnou zásobou bez toho, aby sa uchýlili iba k znakom. [1]
## OpenNMT-py tutoriál
Pri práci na tomto tutoriáli som použil školský server idoc, rovnako ako aj voľne dostupné linuxové prostredie Ubuntu.
Predtým než začneme so samotným tutoriálom je nutné si nainštalovať PyTorch (rámec pre preklad neurónových strojov s otvoreným zdrojom) verziu projektu OpenNMT rovnako ako inštaláciu najnovšej dostupnej verzie knižnice pip. To vykonáme zadaním nasledujúcich príkazov:
- pip install --upgrade pip
- pip install OpenNMT-py
Prvým krokom v tutoriáli je príprava dát, na to nám poslúži predpripravená vzorka dát v anglicko-nemeckom jazyku voľne dostupná na internete obsahujúca 10 000 tokenizovaných viet (tokenizovanie je rozdelenie frázy, vety, odseku alebo celého textu na menšie jednotky teda tokeny,). Údaje pozostávajú z paralelných zdrojových (src) a cieľových (tgt) údajov obsahujúcich jednu vetu na riadok s tokenmi oddelenými medzerou.
- wget https://s3.amazonaws.com/opennmt-trainingdata/toy-ende.tar.gz
- tar xf toy-ende.tar.gz
- cd toy-ende
Pre pokračovanie si musíme pripraviť konfiguračný súbor YAML, aby sme určili údaje, ktoré sa použijú:
- -# toy_en_de.yaml
- -## Where the samples will be written
- save_data: toy-ende/run/example
- -## Where the vocab(s) will be written
- src_vocab: toy-ende/run/example.vocab.src
- tgt_vocab: toy-ende/run/example.vocab.tgt
- -# Prevent overwriting existing files in the folder
- overwrite: False
- -# Corpus opts:
- data:
- corpus_1:
- path_src: toy-ende/src-train.txt
- path_tgt: toy-ende/tgt-train.txt
- valid:
- path_src: toy-ende/src-val.txt
- path_tgt: toy-ende/tgt-val.txt
...
Z tejto konfigurácie môžeme zostaviť slovnú zásobu, ktorá bude potrebná na trénovanie modelu:
- onmt_build_vocab -config toy-ende/toy_en_de.yaml -n_sample 10000
Aby sme mohli model trénovať, musíme do konfiguračného súboru YAML pridať:
-- cesty slovnej zásoby, ktoré sa budú používať (v tomto prípade cesty vygenerované programom onmt_build_vocab)
-- tréning špecifických parametrov.
Pridáme do YAML konfiguračného súboru nasledujúce riadky:
- -# Vocabulary files that were just created
- src_vocab: toy-ende/run/example.vocab.src
- tgt_vocab: toy-ende/run/example.vocab.tgt
- -# Where to save the checkpoints
- save_model: toy-ende/run/model
- save_checkpoint_steps: 500
- train_steps: 1000
- valid_steps: 500
Potom už len stačí spustiť proces trénovania:
- onmt_train -config toy-ende/toy_en_de.yaml
V tejto konfigurácii bude bežať predvolený model, ktorý sa skladá z dvojvrstvového modulu LSTM s 500 skrytými jednotkami v kodéri aj v dekodéri.
Posledným krokom je samotný preklad, ktorý vykonáme zadaním nasledujúceho príkazu:
- onmt_translate -model toy-ende/run/model_step_1000.pt -src toy-ende/src-test.txt -output toy-ende/pred_1000.txt -verbose
Výsledkom je model, ktorý môžeme použiť na predpovedanie nových údajov. To prebieha spustením tzv. Beam search. Beam search sa využíva za účelom udržania ľahšieho ovládania vo veľkých systémoch s nedostatkom pamäte na uloženie celého vyhľadávacieho stromu. To vygeneruje predpovede do výstupného súboru toy-ende/pred_1000.txt . V mojom prípade proces prekladu trval na školskom serveri idoc približne 5 hodín zatiaľ čo v Linuxovom prostredí Ubuntu 1 hodinu. V obidvoch prípadoch boli výsledky podpriemerné, pretože demo súbor údajov bol dosť malý.
## Zoznam použitej literatúry
[1]. WU Y., SCHUSTER M., CHEN Z., LE V. Q., NOROUZI M.: _Googles Neural Machine Translation System: Bridging the Gapbetween Human and Machine Translation._ [online]. [citované 08-09-2016].
[2]. PYKES K.: _The Vanishing/Exploding Gradient Problem in Deep Neural Networks._ [online]. [citované 17-05-2020].
[3]. ŠÍMA J., NERUDA R.: Teoretické otázky neurónových sítí [online]. [1996].

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Some files were not shown because too many files have changed in this diff Show More