diff --git a/.gitignore b/.gitignore index 7dd29ef86..2c6667640 100644 --- a/.gitignore +++ b/.gitignore @@ -82,4 +82,4 @@ docs/_build/doctrees/api/ docs/_build/html/ -docs/_build/doctrees/ +docs/_build/doctrees/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d344703c4..7bc977447 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,10 +15,9 @@ script: coverage run --source=pythainlp setup.py test after_success: coveralls deploy: provider: pypi - distributions: sdist bdist_wheel + distributions: bdist_wheel user: wannaphong password: - secure: zX35+8niw5W9H8XbFwacrDAhqyIibdUdC/cARnHlmxLN/2H9IynK0NW04UZwkBlrwrIZrU/g+cqYXFQXu6jE1ozlBKBxUd3xG8d1kixuntI0j9e+erPTs8Ju/KazUZtlknJPvnDMP+/1Dq+RMnMCP3RRlBrH6lvG70OgZ1aBpgx8FxRfs0xHfBIZvo5CVtR/QlDzhDJM1cgEyWkSgnlAhPxpv8qIQbh4/Rw89jXIZqv0bGCVJorrrcTA1oCzkr/4E4u/WZaARnvPjUr2a9U1w7C2IysDHiBfqQWlovdMmpoSLFE56YlG3smbmXfldWjmiMRQoWL+Ifu+smisvOLmR0ja78UMrrhHWP4mdzIeBVVRnT6eHUv0ChmLT2uCkOLE0newhtEJIYToot2TSoLFavXXIQB1fIHt6e74KRTV6WGnm0nFfHuGP+b5SgSPQFgqx8tBpn0rBOeqZ1y3pRISc/drF0F4reWMnlqoQfZZFmLmU1UmDZbvWNvXPu6MWyyuZ1F6fE9jyb3mG+kDuJf1PZ4ejC/sdIvpLlwUGLFGzRMa2TtxXqGq5CWsywPxo8Sx+bpMPCOImuW60PB9K/xKgfLhAtb7gZwndzUGqDbtSJCd5PmTkfEH8fawv/XnydvsssYUpipBCmFDZlNREyAkgOcLlL099Y5fAO8l2gOLyKs= + secure: Tj3VA05qopp0mkzWu6EFTlvijAoisd0BN/gD2c/vaaDCUy6fTXBkYk+dTkjbmYkEBl/WrsrW1T/QxCt2uc6bv7QTz+qL243Edv4FFQbBKvMSNlUO+hh1jI9zv3/QzwOaNHXOsI4JGeUaN5cULfxBjsBEFN+v6E0mkgBwJ0Qdb0/yuMybLWZ9dJI8iUKiaWNIr+NQoa9a+Sxw6Ltl/mdCKPppgOYPpVMCsDDdLqZdjkgXmzsjH9+Nfe6R+mYbdmeigy3ePNsIKbPkzZrY+E/I0lPZOVUgrs6gvZwlD3gESJgTROrUH6E2lBP9yYvFUE3KB0O+rdT5GyFq3MH1uD2ocrPCTQku6577wK31FzGoex6vtT4y2b39fLbhRmZDOJW8IFO7MLybazuRsNhaXn9hQU4HBRM2GQZc41bLkiEhsUX9/b2ujcn4PJKDZy91LnBw/93bgZJ7KweDzKywmcZSNeuBsGWgXdPqYiizzcf8DdvJAYytydhf8RxqdemTiS7GE7XBoXhj1/9Vfrt3lZXZbfYpTjNZeyxu7FrUJpm/I23wCw46qaRWzKXv2sRRUleNqQ1jIKEVupIa9sruHvG7DZecErhO9rMkGdsf4CIjolZ0A2BE+eAPEEY6/H1WFUWHxzxuELbUJwxnl1By677hBkLJaVs1YMGc2enGWzOnUYI= on: - tags: true - repo: pythainlp/pythainlp \ No newline at end of file + tags: true \ No newline at end of file diff --git a/README-pypi.md b/README-pypi.md index 51ad0707b..b39e99b59 100644 --- a/README-pypi.md +++ b/README-pypi.md @@ -8,20 +8,15 @@ PyThaiNLP includes Thai word tokenizers, transliterators, soundex converters, pa 📫 follow us on Facebook [PyThaiNLP](https://www.facebook.com/pythainlp/) -## What's new in 2.0 ? +## What's new in 2.1 ? -- Terminate Python 2 support. Remove all Python 2 compatibility code. - Improved `word_tokenize` ("newmm" and "mm" engine), a `custom_dict` dictionary can be provided -- Improved `pos_tag` Part-Of-Speech tagging -- New `NorvigSpellChecker` spell checker class, which can be initialized with custom dictionary. -- New `thai2fit` (replacing `thai2vec`, upgrade ULMFiT-related code to fastai 1.0) -- Updated ThaiNER to 1.0 - - You may need to [update your existing ThaiNER models from PyThaiNLP 1.7](https://github.com/PyThaiNLP/pythainlp/wiki/Upgrade-ThaiNER-from-PyThaiNLP-1.7-to-PyThaiNLP-2.0) -- Remove old, obsolated, deprecated, duplicated, and experimental code. - - Sentiment analysis is no longer part of the library, but rather [a text classification example](https://github.com/PyThaiNLP/pythainlp/blob/dev/notebooks/sentiment_analysis.ipynb). +- Add AttaCut to be options for `word_tokenize` engine. +- New Thai2rom (PyTorch) +- New Command Line +- Add word tokenization benchmark to PyThaiNLP - See more examples in [Get Started notebook](https://github.com/PyThaiNLP/pythainlp/blob/dev/notebooks/pythainlp-get-started.ipynb) -- [Full change log](https://github.com/PyThaiNLP/pythainlp/issues/118) -- [Upgrading from 1.7](https://thainlp.org/pythainlp/docs/2.0/notes/pythainlp-1_7-2_0.html) +- [Full change log](https://github.com/PyThaiNLP/pythainlp/issues/181) ## Install @@ -40,6 +35,7 @@ pip install pythainlp[extra1,extra2,...] where extras can be - `artagger` (to support artagger part-of-speech tagger)* +- `attacut` - Wrapper for AttaCut (https://github.com/PyThaiNLP/attacut) - `deepcut` (to support deepcut machine-learnt tokenizer) - `icu` (for ICU support in transliteration and tokenization) - `ipa` (for International Phonetic Alphabet support in transliteration) @@ -54,8 +50,15 @@ Install it with pip, for example: `pip install marisa_trie‑0.7.5‑cp36‑cp36 ## Links -- User guide: [English](https://github.com/PyThaiNLP/pythainlp/blob/dev/notebooks/pythainlp-get-started.ipynb), [ภาษาไทย](https://colab.research.google.com/drive/1rEkB2Dcr1UAKPqz4bCghZV7pXx2qxf89) -- Docs: https://thainlp.org/pythainlp/docs/2.0/ +- User guide: [English](https://github.com/PyThaiNLP/pythainlp/blob/dev/notebooks/pythainlp-get-started.ipynb) +- Docs: https://thainlp.org/pythainlp/docs/2.1/ - GitHub: https://github.com/PyThaiNLP/pythainlp - Issues: https://github.com/PyThaiNLP/pythainlp/issues - Facebook: [PyThaiNLP](https://www.facebook.com/pythainlp/) + + +Made with ❤️ + +We build Thai NLP. + +PyThaiNLP Team. \ No newline at end of file diff --git a/README.md b/README.md index 9a814a5ea..fab714986 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Made with ❤️ We build Thai NLP. -PyThaiNLP team. +PyThaiNLP Team. # ภาษาไทย diff --git a/appveyor.docs.yml b/appveyor.docs.yml new file mode 100644 index 000000000..12f512c06 --- /dev/null +++ b/appveyor.docs.yml @@ -0,0 +1,62 @@ +image: ubuntu1604 + +branches: + only: + - /2.*/ + - dev + +skip_commits: + message: /(skip ci docs)/ # Skip a new build if message contains '(skip ci docs)' + +install: + - sudo add-apt-repository ppa:jonathonf/python-3.6 -y + - sudo apt-get update + - sudo apt install -y python3.6 + - sudo apt install -y python3.6-dev + - sudo apt install -y python3.6-venv + - wget https://bootstrap.pypa.io/get-pip.py + - sudo python3.6 get-pip.py + - sudo ln -s /usr/bin/python3.6 /usr/local/bin/python + - sudo apt-get install -y pandoc libicu-dev + - python -V + - python3 -V + - pip -V + - sudo pip install -r requirements.txt + - export LD_LIBRARY_PATH=/usr/local/lib + - sudo pip install torch==1.2.0+cpu -f https://download.pytorch.org/whl/torch_stable.html + - sudo pip install sphinx sphinx-rtd-theme typing artagger deepcut epitran keras numpy pyicu sklearn-crfsuite tensorflow ssg emoji pandas + - sudo pip install --upgrade gensim smart_open boto + +# configuration for deploy mode, commit message with /(build and deloy docs)/ +# 1. build documents and upload HTML files to Appveyor's storage +# 2. upload to thainlp.org/pythainlp/docs/ + +only_commits: + message: /(build and deploy docs)/ + +build_script: + - cd ./docs + - export CURRENT_BRANCH=$APPVEYOR_REPO_BRANCH + - export RELEASE=$(git describe --tags --always) + - export RELEASE=$(echo $RELEASE | cut -d'-' -f1) + - export TODAY=$(date +'%Y-%m-%d') + - make html + - echo "Done building HTML files for the branch -- $APPVEYOR_REPO_BRANCH" + - echo "Start cleaning the directory /docs/$APPVEYOR_REPO_BRANCH" + - sudo bash ./clean_directory.sh $FTP_USER $FTP_PASSWORD $FTP_HOST $APPVEYOR_REPO_BRANCH + - echo "Start Uploading files to thainlp.org/pythainlp/docs/$APPVEYOR_REPO_BRANCH" + - cd ./_build/html + - echo "cd to ./build/html" + - find . -type f -name "*" -print -exec curl --ftp-create-dir --ipv4 -T {} ftp://${FTP_USER}:${FTP_PASSWORD}@${FTP_HOST}/public_html/pythainlp/docs/$APPVEYOR_REPO_BRANCH/{} \; + - echo "Done uploading" + - echo "Done uploading files to -- thainlp.org/pythainlp/docs/$APPVEYOR_REPO_BRANCH" + +artifacts: + - path: ./docs/_build/html + name: document + +after_build: + - echo "Done build and deploy" + - appveyor exit + +test: off diff --git a/bin/word-tokenization-benchmark b/bin/word-tokenization-benchmark index 0193926d7..a692d3db2 100644 --- a/bin/word-tokenization-benchmark +++ b/bin/word-tokenization-benchmark @@ -1,121 +1,115 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import argparse import json import os -import argparse -import yaml -from pythainlp.benchmarks import word_tokenisation +import yaml +from pythainlp.benchmarks import word_tokenization parser = argparse.ArgumentParser( description="Script for benchmarking tokenizaiton results" ) parser.add_argument( - "--input", + "--input-file", action="store", - help="path to file that you want to compare against the test file" + help="Path to input file to compare against the test file", ) parser.add_argument( "--test-file", action="store", - help="path to test file" + help="Path to test file i.e. ground truth", ) parser.add_argument( "--save-details", default=False, - action='store_true', - help="specify whether to save the details of comparisons" + action="store_true", + help="Save comparison details to files (eval-XXX.json and eval-details-XXX.json)", ) args = parser.parse_args() + def _read_file(path): with open(path, "r", encoding="utf-8") as f: lines = map(lambda r: r.strip(), f.readlines()) return list(lines) -print(args.input) -actual = _read_file(args.input) +print(args.input_file) +actual = _read_file(args.input_file) expected = _read_file(args.test_file) -assert len(actual) == len(expected), \ - 'Input and test files do not have the same number of samples' -print('Benchmarking %s against %s with %d samples in total' % ( - args.input, args.test_file, len(actual) -)) - -df_raw = word_tokenisation.benchmark(expected, actual) - -df_res = df_raw\ - .describe() -df_res = df_res[[ - 'char_level:tp', - 'char_level:tn', - 'char_level:fp', - 'char_level:fn', - 'char_level:precision', - 'char_level:recall', - 'char_level:f1', - 'word_level:precision', - 'word_level:recall', - 'word_level:f1', -]] +assert len(actual) == len( + expected +), "Input and test files do not have the same number of samples" +print( + "Benchmarking %s against %s with %d samples in total" + % (args.input_file, args.test_file, len(actual)) +) + +df_raw = word_tokenization.benchmark(expected, actual) + +df_res = df_raw.describe() +df_res = df_res[ + [ + "char_level:tp", + "char_level:tn", + "char_level:fp", + "char_level:fn", + "char_level:precision", + "char_level:recall", + "char_level:f1", + "word_level:precision", + "word_level:recall", + "word_level:f1", + ] +] df_res = df_res.T.reset_index(0) -df_res['mean±std'] = df_res.apply( - lambda r: '%2.2f±%2.2f' % (r['mean'], r['std']), - axis=1 +df_res["mean±std"] = df_res.apply( + lambda r: "%2.2f±%2.2f" % (r["mean"], r["std"]), axis=1 ) -df_res['metric'] = df_res['index'] +df_res["metric"] = df_res["index"] print("============== Benchmark Result ==============") -print(df_res[['metric', 'mean±std', 'min', 'max']].to_string(index=False)) - +print(df_res[["metric", "mean±std", "min", "max"]].to_string(index=False)) if args.save_details: data = {} - for r in df_res.to_dict('records'): - metric = r['index'] - del r['index'] + for r in df_res.to_dict("records"): + metric = r["index"] + del r["index"] data[metric] = r - dir_name = os.path.dirname(args.input) - file_name = args.input.split("/")[-1].split(".")[0] + dir_name = os.path.dirname(args.input_file) + file_name = args.input_file.split("/")[-1].split(".")[0] res_path = "%s/eval-%s.yml" % (dir_name, file_name) print("Evaluation result is saved to %s" % res_path) - with open(res_path, 'w') as outfile: + with open(res_path, "w", encoding="utf-8") as outfile: yaml.dump(data, outfile, default_flow_style=False) res_path = "%s/eval-details-%s.json" % (dir_name, file_name) print("Details of comparisons is saved to %s" % res_path) - with open(res_path, "w") as f: + with open(res_path, "w", encoding="utf-8") as f: samples = [] for i, r in enumerate(df_raw.to_dict("records")): expected, actual = r["expected"], r["actual"] del r["expected"] del r["actual"] - samples.append(dict( - metrics=r, - expected=expected, - actual=actual, - id=i - )) - - details = dict( - metrics=data, - samples=samples - ) + samples.append(dict(metrics=r, expected=expected, actual=actual, id=i)) + + details = dict(metrics=data, samples=samples) json.dump(details, f, ensure_ascii=False) diff --git a/bld.bat b/bld.bat deleted file mode 100644 index f1f6e67a7..000000000 --- a/bld.bat +++ /dev/null @@ -1,2 +0,0 @@ -cd %RECIPE_DIR%\.. -%PYTHON% setup.py install --single-version-externally-managed --record=record.txt diff --git a/build.sh b/build.sh deleted file mode 100644 index 838a79040..000000000 --- a/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd "$RECIPE_DIR"/.. || exit -$PYTHON setup.py install --single-version-externally-managed --record=record.txt diff --git a/buildall.sh b/buildall.sh deleted file mode 100755 index 104591b14..000000000 --- a/buildall.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# change the package name to the existing PyPi package you would like to build and adjust the Python versions -pkg='pythainlp' -array=( 3.5 3.6 3.7 ) - -echo "Building conda package ..." -cd ~ -conda skeleton pypi $pkg -cd $pkg -wget https://raw.githubusercontent.com/Anaconda-Platform/anaconda-client/master/conda.recipe/build.sh -wget https://raw.githubusercontent.com/Anaconda-Platform/anaconda-client/master/conda.recipe/bld.bat -cd ~ - -# building conda packages -for i in "${array[@]}" -do - conda-build --python $i $pkg -done - -# convert package to other platforms -cd ~ -platforms=( osx-64 linux-32 linux-64 win-32 win-64 ) -find $HOME/conda-bld/linux-64/ -name *.tar.bz2 | while read file -do - echo $file - #conda convert --platform all $file -o $HOME/conda-bld/ - for platform in "${platforms[@]}" - do - conda convert --platform $platform $file -o $HOME/conda-bld/ - done - -done - -# upload packages to conda -find $HOME/conda-bld/ -name *.tar.bz2 | while read file -do - echo $file - anaconda upload $file -done - -echo "Building conda package done!" diff --git a/docs/api/benchmarks.rst b/docs/api/benchmarks.rst index e5167ee96..26ee1a1b5 100644 --- a/docs/api/benchmarks.rst +++ b/docs/api/benchmarks.rst @@ -19,6 +19,6 @@ Quality Qualitative evaluation of word tokenization. -.. autofunction:: pythainlp.benchmarks.word_tokenisation.compute_stats -.. autofunction:: pythainlp.benchmarks.word_tokenisation.benchmark -.. autofunction:: pythainlp.benchmarks.word_tokenisation.preprocessing +.. autofunction:: pythainlp.benchmarks.word_tokenization.compute_stats +.. autofunction:: pythainlp.benchmarks.word_tokenization.benchmark +.. autofunction:: pythainlp.benchmarks.word_tokenization.preprocessing diff --git a/docs/api/ulmfit.rst b/docs/api/ulmfit.rst index 527336c64..9b7bdba28 100644 --- a/docs/api/ulmfit.rst +++ b/docs/api/ulmfit.rst @@ -6,13 +6,21 @@ The :class:`ulmfit.utils` is utils for ULMFit model. Modules ------- - -.. autofunction:: replace_rep_after +.. autoclass:: ThaiTokenizer +.. autofunction:: document_vector +.. autofunction:: process_thai +.. autofunction:: fix_html +.. autofunction:: spec_add_spaces +.. autofunction:: rm_useless_spaces .. autofunction:: rm_useless_newlines .. autofunction:: rm_brackets +.. autofunction:: replace_rep_nonum .. autofunction:: ungroup_emoji .. autofunction:: lowercase_all +.. autofunction:: replace_wrep_post +.. autofunction:: replace_wrep_post_nonum +.. autofunction:: replace_rep_after +.. autofunction:: remove_space .. autofunction:: merge_wgts -.. autofunction:: document_vector -.. autoclass:: ThaiTokenizer - :members: tokenizer + +:members: tokenizer diff --git a/docs/clean_directory.sh b/docs/clean_directory.sh new file mode 100644 index 000000000..126ee4774 --- /dev/null +++ b/docs/clean_directory.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Delete all files and folders in the directory: /pythainlp/docs/ + +# $1 : FTP_USER +# $2 : FTP_PASSWORD +# $3 : FTP_HOST +# $4 : Brnach name + +FTP_USER=$1 +FTP_PASSWORD=$2 +FTP_HOST=$3 +BRANCH_NAME=$4 + +remove_all_files() +{ + # DIRECTORY=$1 + echo "delete files in: $1" + for f in `curl --list-only --ftp-create-dirs --ipv4 ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST/$1/`; do + if [[ -d "$f" ]] || [[ "$f" = _* ]] || [[ "$f" = .doctree ]] || [[ "$f" != *"."* ]]; then + echo "--- deleting files in folder: $1/$f"; + remove_all_files $1/$f + else + echo "delete a file: $f" + curl --ipv4 ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST -Q "DELE $1/$f" + fi + done +} + +remove_empty_folders() +{ + + echo "delete empty folders in: $1" + for f in `curl --list-only --ftp-create-dirs --ipv4 ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST/$1/`; do + if [[ -d "$f" ]] || [[ "$f" = _* ]] || [[ "$f" = fonts ]] || [[ "$f" = pythainlp ]] || [[ "$f" = .doctree ]] || [[ "$f" != *"."* ]]; then + echo "--- deleting folders in: $1/$f"; + remove_empty_folders $1/$f + curl --ipv4 ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST -Q "RMD $1/$f" + else + echo "delete a folder: $f" + curl --ipv4 ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST -Q "RMD $1/$f" + fi + done +} + +echo "Start removing all files within 'public_html/pythainlp/docs/$BRANCH_NAME/'"; + +remove_all_files public_html/pythainlp/docs/$BRANCH_NAME; + +echo "Start removing all empty folders within 'public_html/pythainlp/docs/$BRANCH_NAME/'"; + +remove_empty_folders public_html/pythainlp/docs/$BRANCH_NAME; + +echo "Done"; \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 9a9e47343..a43b593a0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,7 @@ # import os import sys +import traceback sys.path.insert(0, os.path.abspath('..')) from datetime import datetime @@ -23,10 +24,24 @@ curyear = datetime.today().year copyright = u'2017-%s, %s (Apache Software License 2.0)' % (curyear, project) +# -- Get version information and date from Git ---------------------------- + +try: + from subprocess import check_output, STDOUT + current_branch = os.environ["CURRENT_BRANCH"] if "CURRENT_BRANCH" in os.environ else check_output(['git', 'symbolic-ref', 'HEAD'], shell=False, stderr=STDOUT).decode().strip().split('/')[-1] + release = os.environ["RELEASE"] if "RELEASE" in os.environ else check_output(['git', 'describe', '--tags', '--always'], shell=False, stderr=STDOUT).decode().strip().split('-')[0] + today = os.environ["TODAY"] if "TODAY" in os.environ else check_output(['git', 'show', '-s', '--format=%ad', '--date=short'], shell=False, stderr=STDOUT).decode().strip() +except Exception as e: + traceback.print_exc() + release = '' + today = '' + current_branch = '' + # The short X.Y version -version = '2.0' +version = '{} ({})
Published date: {}'.format(current_branch, release, today) + # The full version, including alpha/beta/rc tags -release = '2.0.3' +release = release # -- General configuration --------------------------------------------------- @@ -88,7 +103,9 @@ # further. For a list of options available for each theme, see the # documentation. # -# html_theme_options = {} +html_theme_options = { + 'display_version': True, +} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/images/evaluation.png b/docs/images/evaluation.png new file mode 100644 index 000000000..3ac1cd13e Binary files /dev/null and b/docs/images/evaluation.png differ diff --git a/docs/notes/command_line.rst b/docs/notes/command_line.rst index 90211ccc6..329ba6c78 100644 --- a/docs/notes/command_line.rst +++ b/docs/notes/command_line.rst @@ -7,27 +7,45 @@ Run Command Line and type the commands::: pythainlp -**Word segment**:: +**Word tokenization**:: - pythainlp -t TEXT -seg + pythainlp tokenization word --text TEXT *Example*:: - $ pythainlp -t แมวกินปลา -seg - แมว|กิน|ปลา + $ pythainlp tokenization word --text "ผมร<0e31>กประเทศไทย? สามารถ" --engine newmm + ผม|รัก|ประเทศไทย|?| |สามารถ -**Postag**:: - pythainlp -t TEXT -pos +**Syllable tokenization**:: + + pythainlp tokenization syllable --text TEXT + +*Example*:: + + $ pythainlp tokenization syllable --text "ผมร<0e31>กประเทศไทย? สามารถ" + ผม~รัก~ประ~เทศ~ไทย~? ~สา~มารถ + +**Part-Of-Speech tagging**:: + + pythainlp tagging pos --text TEXT + +*Example*:: + + $ pythainlp tagging pos --text "ผม|ไม่|กิน|เผ็ด" + +**Soundex**:: + + pythainlp soundex --text TEXT *Example*:: - $ pythainlp -t แมวกินปลา -pos - แมว/NCMN กิน/VACT ปลา/NCMN + $ pythainlp soundex --text "บ<0e39>รณการ" --engine lk82 + บE419 **Mange corpus**:: - pythainlp -c + pythainlp corpus **Help**:: diff --git a/notebooks/sentiment_analysis.ipynb b/notebooks/sentiment_analysis.ipynb index c1af928cb..74c9d4f9e 100644 --- a/notebooks/sentiment_analysis.ipynb +++ b/notebooks/sentiment_analysis.ipynb @@ -1,1805 +1,1838 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.3" - }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8AF08ssF6z5K" + }, + "source": [ + "# Sentiment Analysis" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "o-tHtMyc6z5L" + }, + "source": [ + "This notebook details the steps taken to create a sentiment analyzer using data from [WISESIGHT Sentiment Analysis](https://www.kaggle.com/c/wisesight-sentiment/) competition. Competition metric is overall accuracy across `neg`ative, `pos`itive, `neu`tral and `q`uestion classes. We give examples using logistic regression and ULMFit.\n", + "\n", + "The results for logistic regression, FastText, ULMFit, ULMFit with semi-supervised data are as follows:\n", + "\n", + "| Model | Public Accuracy | Private Accuracy |\n", + "|---------------------|-----------------|------------------|\n", + "| Logistic Regression | 0.72781 | 0.7499 |\n", + "| FastText | 0.63144 | 0.6131 |\n", + "| ULMFit | 0.71259 | 0.74194 |\n", + "| ULMFit Semi-supervised | 0.73119 | 0.75859 |\n", + "| ULMFit Semi-supervised Repeated One Time | **0.73372** | **0.75968** |\n", + "\n", + "For more information about the competition, see [1st Place Solution](https://www.kaggle.com/c/wisesight-sentiment/discussion/83564)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { "colab": { - "name": "sentiment_analysis.ipynb", - "version": "0.3.2", - "provenance": [] + "base_uri": "https://localhost:8080/", + "height": 1000 }, - "accelerator": "GPU" + "colab_type": "code", + "id": "bNjkuQK46z5M", + "outputId": "e04e1073-d8ca-4bd2-ac1c-2240826a75dc" + }, + "outputs": [], + "source": [ + "# #uncomment if you are running from google colab\n", + "# !pip install sklearn_crfsuite\n", + "# !pip install emoji\n", + "# !pip install https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", + "# !pip install fastai\n", + "# !wget https://github.com/PyThaiNLP/wisesight-sentiment/archive/master.zip\n", + "# !unzip master.zip\n", + "# !mkdir wisesight_data; ls\n", + "# !cd wisesight-sentiment-master/kaggle-competition; ls" + ] }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "8AF08ssF6z5K", - "colab_type": "text" - }, - "source": [ - "# Sentiment Analysis" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "o-tHtMyc6z5L", - "colab_type": "text" - }, - "source": [ - "This notebook details the steps taken to create a sentiment analyzer using data from [WISESIGHT Sentiment Analysis](https://www.kaggle.com/c/wisesight-sentiment/) competition. Competition metric is overall accuracy across `neg`ative, `pos`itive, `neu`tral and `q`uestion classes. We give examples using logistic regression and ULMFit.\n", - "\n", - "The results for logistic regression, FastText, ULMFit, ULMFit with semi-supervised data are as follows:\n", - "\n", - "| Model | Public Accuracy | Private Accuracy |\n", - "|---------------------|-----------------|------------------|\n", - "| Logistic Regression | 0.72781 | 0.7499 |\n", - "| FastText | 0.63144 | 0.6131 |\n", - "| ULMFit | 0.71259 | 0.74194 |\n", - "| ULMFit Semi-supervised | 0.73119 | 0.75859 |\n", - "| ULMFit Semi-supervised Repeated One Time | **0.73372** | **0.75968** |\n", - "\n", - "For more information about the competition, see [1st Place Solution](https://www.kaggle.com/c/wisesight-sentiment/discussion/83564)." - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "bNjkuQK46z5M", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "outputId": "e04e1073-d8ca-4bd2-ac1c-2240826a75dc" - }, - "source": [ - "#uncomment if you are running from google colab\n", - "!pip install sklearn_crfsuite\n", - "!pip install emoji\n", - "!pip install https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "!pip install fastai\n", - "!wget https://github.com/PyThaiNLP/wisesight-sentiment/archive/master.zip\n", - "!unzip master.zip\n", - "!mkdir wisesight_data; ls" - ], - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "text": [ - "Collecting sklearn_crfsuite\n", - " Downloading https://files.pythonhosted.org/packages/25/74/5b7befa513482e6dee1f3dd68171a6c9dfc14c0eaa00f885ffeba54fe9b0/sklearn_crfsuite-0.3.6-py2.py3-none-any.whl\n", - "Requirement already satisfied: tabulate in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (0.8.3)\n", - "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (1.12.0)\n", - "Requirement already satisfied: tqdm>=2.0 in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (4.28.1)\n", - "Collecting python-crfsuite>=0.8.3 (from sklearn_crfsuite)\n", - "\u001b[?25l Downloading https://files.pythonhosted.org/packages/2f/86/cfcd71edca9d25d3d331209a20f6314b6f3f134c29478f90559cee9ce091/python_crfsuite-0.9.6-cp36-cp36m-manylinux1_x86_64.whl (754kB)\n", - "\u001b[K |████████████████████████████████| 757kB 3.8MB/s \n", - "\u001b[?25hInstalling collected packages: python-crfsuite, sklearn-crfsuite\n", - "Successfully installed python-crfsuite-0.9.6 sklearn-crfsuite-0.3.6\n", - "Collecting emoji\n", - "\u001b[?25l Downloading https://files.pythonhosted.org/packages/1b/d7/2746b4dd67375ce253e777ba54869545d24d2b0249ebcf83735c99df68d5/emoji-0.5.3.tar.gz (43kB)\n", - "\u001b[K |████████████████████████████████| 51kB 2.0MB/s \n", - "\u001b[?25hBuilding wheels for collected packages: emoji\n", - " Building wheel for emoji (setup.py) ... \u001b[?25l\u001b[?25hdone\n", - " Created wheel for emoji: filename=emoji-0.5.3-cp36-none-any.whl size=42175 sha256=208a827318503334b8daef569a30c9a2bf390eb8da0c6e8326ada209ae4708cf\n", - " Stored in directory: /root/.cache/pip/wheels/86/09/26/f944015841423cd516e8a97f30e29be59e53461aea8b7d3458\n", - "Successfully built emoji\n", - "Installing collected packages: emoji\n", - "Successfully installed emoji-0.5.3\n", - "Collecting https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "\u001b[?25l Downloading https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "\u001b[K | 15.7MB 322kB/s\n", - "\u001b[?25hRequirement already satisfied: dill in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (0.3.0)\n", - "Collecting marisa-trie==0.7.4 (from pythainlp==2.1.dev2)\n", - "\u001b[?25l Downloading https://files.pythonhosted.org/packages/1b/5f/21295ebb1feb1abde1e7652c0a4c182b4c25bdd5dda5a0f5b34d4e88bcc3/marisa_trie-0.7.4-cp36-cp36m-manylinux1_x86_64.whl (870kB)\n", - "\u001b[K |████████████████████████████████| 880kB 2.7MB/s \n", - "\u001b[?25hRequirement already satisfied: nltk>=3.2.2 in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (3.2.5)\n", - "Requirement already satisfied: pytz in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (2018.9)\n", - "Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (2.21.0)\n", - "Collecting tinydb (from pythainlp==2.1.dev2)\n", - " Downloading https://files.pythonhosted.org/packages/d7/f9/0e871cbf0da678cf1780609dc6aef26a5ed544c86733fc1ceaf134fce52c/tinydb-3.13.0-py2.py3-none-any.whl\n", - "Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (4.28.1)\n", - "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from nltk>=3.2.2->pythainlp==2.1.dev2) (1.12.0)\n", - "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (1.24.3)\n", - "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (2.8)\n", - "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (3.0.4)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (2019.6.16)\n", - "Building wheels for collected packages: pythainlp\n", - " Building wheel for pythainlp (setup.py) ... \u001b[?25l\u001b[?25hdone\n", - " Created wheel for pythainlp: filename=pythainlp-2.1.dev2-cp36-none-any.whl size=11014043 sha256=edfa71c88f221b4c0428a99429b522cdd69c512db0dbe00ed8910da6114e2c44\n", - " Stored in directory: /tmp/pip-ephem-wheel-cache-foefq95n/wheels/79/4e/1e/26f3198c6712ecfbee92928ed1dde923a078da3d222401cc78\n", - "Successfully built pythainlp\n", - "Installing collected packages: marisa-trie, tinydb, pythainlp\n", - "Successfully installed marisa-trie-0.7.4 pythainlp-2.1.dev2 tinydb-3.13.0\n", - "Collecting fastai==1.0.45\n", - "\u001b[31m ERROR: Could not find a version that satisfies the requirement fastai==1.0.45 (from versions: 0.6, 0.7.0, 1.0.0b7, 1.0.0b8, 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.9, 1.0.10, 1.0.11, 1.0.12, 1.0.13, 1.0.14, 1.0.15, 1.0.16, 1.0.17, 1.0.18, 1.0.19, 1.0.20, 1.0.21, 1.0.22, 1.0.24, 1.0.25, 1.0.26, 1.0.27, 1.0.28, 1.0.29, 1.0.30, 1.0.31, 1.0.32, 1.0.33, 1.0.34, 1.0.35, 1.0.36, 1.0.36.post1, 1.0.37, 1.0.38, 1.0.39, 1.0.40, 1.0.41, 1.0.42, 1.0.43.post1, 1.0.44, 1.0.46, 1.0.47, 1.0.47.post1, 1.0.48, 1.0.49, 1.0.50, 1.0.50.post1, 1.0.51, 1.0.52, 1.0.53, 1.0.53.post1, 1.0.53.post2, 1.0.53.post3, 1.0.54, 1.0.55, 1.0.57)\u001b[0m\n", - "\u001b[31mERROR: No matching distribution found for fastai==1.0.45\u001b[0m\n", - "--2019-08-20 07:49:28-- https://github.com/PyThaiNLP/wisesight-sentiment/archive/master.zip\n", - "Resolving github.com (github.com)... 192.30.253.112\n", - "Connecting to github.com (github.com)|192.30.253.112|:443... connected.\n", - "HTTP request sent, awaiting response... 302 Found\n", - "Location: https://codeload.github.com/PyThaiNLP/wisesight-sentiment/zip/master [following]\n", - "--2019-08-20 07:49:29-- https://codeload.github.com/PyThaiNLP/wisesight-sentiment/zip/master\n", - "Resolving codeload.github.com (codeload.github.com)... 140.82.113.9\n", - "Connecting to codeload.github.com (codeload.github.com)|140.82.113.9|:443... connected.\n", - "HTTP request sent, awaiting response... 200 OK\n", - "Length: unspecified [application/zip]\n", - "Saving to: ‘master.zip’\n", - "\n", - "master.zip [ <=> ] 3.95M 2.65MB/s in 1.5s \n", - "\n", - "2019-08-20 07:49:31 (2.65 MB/s) - ‘master.zip’ saved [4137118]\n", - "\n", - "Archive: master.zip\n", - "a2b5c41957bc799fe61cd407e7dc191ca6122dcb\n", - " creating: wisesight-sentiment-master/\n", - " inflating: wisesight-sentiment-master/.gitignore \n", - " inflating: wisesight-sentiment-master/README.md \n", - " inflating: wisesight-sentiment-master/exploration.ipynb \n", - " creating: wisesight-sentiment-master/kaggle-competition/\n", - " inflating: wisesight-sentiment-master/kaggle-competition/README.md \n", - " inflating: wisesight-sentiment-master/kaggle-competition/competition.ipynb \n", - " inflating: wisesight-sentiment-master/kaggle-competition/test.txt \n", - " inflating: wisesight-sentiment-master/kaggle-competition/test_label.txt \n", - " inflating: wisesight-sentiment-master/kaggle-competition/test_majority.csv \n", - " inflating: wisesight-sentiment-master/kaggle-competition/test_solution.csv \n", - " inflating: wisesight-sentiment-master/kaggle-competition/text_generation.ipynb \n", - " inflating: wisesight-sentiment-master/kaggle-competition/train.txt \n", - " inflating: wisesight-sentiment-master/kaggle-competition/train_label.txt \n", - " inflating: wisesight-sentiment-master/kaggle-competition/train_model.py \n", - " inflating: wisesight-sentiment-master/neg.txt \n", - " inflating: wisesight-sentiment-master/neu.txt \n", - " inflating: wisesight-sentiment-master/pos.txt \n", - " inflating: wisesight-sentiment-master/q.txt \n", - " creating: wisesight-sentiment-master/word-tokenization/\n", - " inflating: wisesight-sentiment-master/word-tokenization/README.md \n", - " inflating: wisesight-sentiment-master/word-tokenization/data-preparation-and-post-processing.ipynb \n", - " inflating: wisesight-sentiment-master/word-tokenization/wisesight-160-samples-tokenised.label \n", - " inflating: wisesight-sentiment-master/word-tokenization/wisesight-160-samples-tokenised.txt \n", - "master.zip sample_data wisesight_data wisesight-sentiment-master\n" - ], - "name": "stdout" - } - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "O-eB6ovn_UgH", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 68 - }, - "outputId": "6a6b59e2-e0ed-4184-a0fe-ee55cd66f3b2" - }, - "source": [ - "!cd wisesight-sentiment-master/kaggle-competition; ls" - ], - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "text": [ - "competition.ipynb test_majority.csv text_generation.ipynb train.txt\n", - "README.md\t test_solution.csv train_label.txt\n", - "test_label.txt\t test.txt\t train_model.py\n" - ], - "name": "stdout" - } - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "Zs8wtP0m6z5O", - "colab_type": "code", - "colab": {} - }, - "source": [ - "import re\n", - "\n", - "import emoji\n", - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "from pythainlp import word_tokenize\n", - "from tqdm import tqdm_notebook\n", - "\n", - "#viz\n", - "import matplotlib.pyplot as plt\n", - "import seaborn as sns" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "cRXpcJp16z5R", - "colab_type": "text" - }, - "source": [ - "## Text Processor for Logistic Regression" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "exvcf5XV6z5R", - "colab_type": "code", - "colab": {} - }, - "source": [ - "def replace_url(text):\n", - " URL_PATTERN = r\"\"\"(?i)\\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\\s()<>{}\\[\\]]+|\\([^\\s()]*?\\([^\\s()]+\\)[^\\s()]*?\\)|\\([^\\s]+?\\))+(?:\\([^\\s()]*?\\([^\\s()]+\\)[^\\s()]*?\\)|\\([^\\s]+?\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’])|(?:(?\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
categorytextsprocessedwcuwc
0neuเห็นคนลบแอพ viu ก็เห็นใจและเข้าใจเขานะคะ แผลมั...เห็น|คน|ลบ|แอพ|viu|ก็|เห็นใจ|และ|เข้าใจ|เขา|นะ...4641
1neuไปชมไม้คิวของแชมป์ และรองแชมป์ กันจ้า! ..........ไป|ชม|ไม้คิว|ของ|แชมป์|และ|รอง|แชมป์|กัน|จ้า|!...4139
2negกลุ่มรถซีวิคเป็นกลุ่มที่น่ารำคานมากกกกกกกกก อว...กลุ่ม|รถ|ซีวิค|เป็น|กลุ่ม|ที่|น่า|รำ|คาน|มาก|x...4635
3neuอยากสวยเหมือนเจ้าของแบรนด์สิคะ เนย โชติกา ใบหน...อยาก|สวย|เหมือน|เจ้าของ|แบรนด์|สิ|คะ|เนย|โชติ|...7256
4negข้าวโถละร้อย แพง เพราะตักเป็นจานๆละ15 เต็มที่ก...ข้าว|โถ|ละ|ร้อย|แพง|เพราะ|ตัก|เป็น|จาน|ๆ|ละ|15...379218
\n", - "" - ], - "text/plain": [ - " category texts ... wc uwc\n", - "0 neu เห็นคนลบแอพ viu ก็เห็นใจและเข้าใจเขานะคะ แผลมั... ... 46 41\n", - "1 neu ไปชมไม้คิวของแชมป์ และรองแชมป์ กันจ้า! .......... ... 41 39\n", - "2 neg กลุ่มรถซีวิคเป็นกลุ่มที่น่ารำคานมากกกกกกกกก อว... ... 46 35\n", - "3 neu อยากสวยเหมือนเจ้าของแบรนด์สิคะ เนย โชติกา ใบหน... ... 72 56\n", - "4 neg ข้าวโถละร้อย แพง เพราะตักเป็นจานๆละ15 เต็มที่ก... ... 379 218\n", - "\n", - "[5 rows x 5 columns]" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 13 - } + "data": { + "text/plain": [ + "(2674, 2)" ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with open(\"wisesight-sentiment-master/kaggle-competition/test.txt\") as f:\n", + " texts = [line.strip() for line in f.readlines()]\n", + "\n", + "test_df = pd.DataFrame({\"category\":\"test\", \"texts\":texts})\n", + "test_df.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "E5rbH6aJ6z5a" + }, + "source": [ + "## Load Data" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "yhQ6MX7U6z5a" + }, + "outputs": [], + "source": [ + "all_df[\"processed\"] = all_df.texts.map(lambda x: \"|\".join(process_thai(x)))\n", + "all_df[\"wc\"] = all_df.processed.map(lambda x: len(x.split(\"|\")))\n", + "all_df[\"uwc\"] = all_df.processed.map(lambda x: len(set(x.split(\"|\"))))\n", + "\n", + "test_df[\"processed\"] = test_df.texts.map(lambda x: \"|\".join(process_thai(x)))\n", + "test_df[\"wc\"] = test_df.processed.map(lambda x: len(x.split(\"|\")))\n", + "test_df[\"uwc\"] = test_df.processed.map(lambda x: len(set(x.split(\"|\"))))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 102 }, + "colab_type": "code", + "id": "iEDdQ9hH6z5c", + "outputId": "d27939a6-ee4f-4892-bcc1-40623aca567b" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "GojEjj2k6z5m", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 102 - }, - "outputId": "1596bac3-8a47-49bf-ed6c-59745c422145" - }, - "source": [ - "#prevalence\n", - "print(train_df[\"category\"].value_counts() / train_df.shape[0])" - ], - "execution_count": 14, - "outputs": [ - { - "output_type": "stream", - "text": [ - "neu 0.544957\n", - "neg 0.253557\n", - "pos 0.180071\n", - "q 0.021415\n", - "Name: category, dtype: float64\n" - ], - "name": "stdout" - } + "data": { + "text/plain": [ + "neu 0.544612\n", + "neg 0.255164\n", + "pos 0.178698\n", + "q 0.021527\n", + "Name: category, dtype: float64" ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#prevalence\n", + "all_df.category.value_counts() / all_df.shape[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "-jPw7Rbu6z5f" + }, + "source": [ + "## Train-validation Split" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "K9b0gp626z5g" + }, + "source": [ + "We perform 85/15 random train-validation split. We also perform under/oversampling to balance out the classes a little." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ioXCNzVX6z5h" + }, + "outputs": [], + "source": [ + "#when finding hyperparameters\n", + "from sklearn.model_selection import train_test_split\n", + "train_df, valid_df = train_test_split(all_df, test_size=0.15, random_state=1412)\n", + "train_df = train_df.reset_index(drop=True)\n", + "valid_df = valid_df.reset_index(drop=True)\n", + "\n", + "#when actually doing it\n", + "# train_df = all_df.copy()\n", + "# valid_df = pd.read_csv('valid_df.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 204 }, + "colab_type": "code", + "id": "J5sCacbM6z5j", + "outputId": "03df103a-e045-4dfa-d544-2d51cb374346" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "sH1t3bal6z5o", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 102 - }, - "outputId": "0c50fe48-3671-4940-d4fa-294161e84fa0" - }, - "source": [ - "#prevalence\n", - "print(valid_df[\"category\"].value_counts() / valid_df.shape[0])" + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
categorytextsprocessedwcuwc
0neuเห็นคนลบแอพ viu ก็เห็นใจและเข้าใจเขานะคะ แผลมั...เห็น|คน|ลบ|แอ|พ|viu|ก็|เห็นใจ|และ|เข้าใจ|เขา|น...4843
1neuไปชมไม้คิวของแชมป์ และรองแชมป์ กันจ้า! ..........ไป|ชม|ไม้|คิว|ของ|แชมป์|และ|รอง|แชมป์|กัน|จ้า|...4341
2negกลุ่มรถซีวิคเป็นกลุ่มที่น่ารำคานมากกกกกกกกก อว...กลุ่ม|รถ|ซีวิค|เป็น|กลุ่ม|ที่|น่า|รำ|คาน|มาก|x...4736
3neuอยากสวยเหมือนเจ้าของแบรนด์สิคะ เนย โชติกา ใบหน...อยาก|สวย|เหมือน|เจ้าของ|แบรนด์|สิ|คะ|เนย|โชติ|...7256
4negข้าวโถละร้อย แพง เพราะตักเป็นจานๆละ15 เต็มที่ก...ข้าว|โถ|ละ|ร้อย|แพง|เพราะ|ตัก|เป็น|จาน|ๆ|ละ|15...381218
\n", + "
" ], - "execution_count": 15, - "outputs": [ - { - "output_type": "stream", - "text": [ - "neu 0.542659\n", - "neg 0.264266\n", - "pos 0.170914\n", - "q 0.022161\n", - "Name: category, dtype: float64\n" - ], - "name": "stdout" - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fhsWvG9c6z5q", - "colab_type": "text" - }, - "source": [ - "## Logistic Regression" + "text/plain": [ + " category texts \\\n", + "0 neu เห็นคนลบแอพ viu ก็เห็นใจและเข้าใจเขานะคะ แผลมั... \n", + "1 neu ไปชมไม้คิวของแชมป์ และรองแชมป์ กันจ้า! .......... \n", + "2 neg กลุ่มรถซีวิคเป็นกลุ่มที่น่ารำคานมากกกกกกกกก อว... \n", + "3 neu อยากสวยเหมือนเจ้าของแบรนด์สิคะ เนย โชติกา ใบหน... \n", + "4 neg ข้าวโถละร้อย แพง เพราะตักเป็นจานๆละ15 เต็มที่ก... \n", + "\n", + " processed wc uwc \n", + "0 เห็น|คน|ลบ|แอ|พ|viu|ก็|เห็นใจ|และ|เข้าใจ|เขา|น... 48 43 \n", + "1 ไป|ชม|ไม้|คิว|ของ|แชมป์|และ|รอง|แชมป์|กัน|จ้า|... 43 41 \n", + "2 กลุ่ม|รถ|ซีวิค|เป็น|กลุ่ม|ที่|น่า|รำ|คาน|มาก|x... 47 36 \n", + "3 อยาก|สวย|เหมือน|เจ้าของ|แบรนด์|สิ|คะ|เนย|โชติ|... 72 56 \n", + "4 ข้าว|โถ|ละ|ร้อย|แพง|เพราะ|ตัก|เป็น|จาน|ๆ|ละ|15... 381 218 " ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "valid_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 102 }, + "colab_type": "code", + "id": "GojEjj2k6z5m", + "outputId": "1596bac3-8a47-49bf-ed6c-59745c422145" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "oUAqMvNe6z5q", - "colab_type": "text" - }, - "source": [ - "### Create Features" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "neu 0.544957\n", + "neg 0.253557\n", + "pos 0.180071\n", + "q 0.021415\n", + "Name: category, dtype: float64\n" + ] + } + ], + "source": [ + "#prevalence\n", + "print(train_df[\"category\"].value_counts() / train_df.shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 102 }, + "colab_type": "code", + "id": "sH1t3bal6z5o", + "outputId": "0c50fe48-3671-4940-d4fa-294161e84fa0" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "5eI-DEzW6z5r", - "colab_type": "code", - "colab": {} - }, - "source": [ - "#dependent variables\n", - "y_train = train_df[\"category\"]\n", - "y_valid = valid_df[\"category\"]" - ], - "execution_count": 0, - "outputs": [] + "name": "stdout", + "output_type": "stream", + "text": [ + "neu 0.542659\n", + "neg 0.264266\n", + "pos 0.170914\n", + "q 0.022161\n", + "Name: category, dtype: float64\n" + ] + } + ], + "source": [ + "#prevalence\n", + "print(valid_df[\"category\"].value_counts() / valid_df.shape[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fhsWvG9c6z5q" + }, + "source": [ + "## Logistic Regression" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "oUAqMvNe6z5q" + }, + "source": [ + "### Create Features" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "5eI-DEzW6z5r" + }, + "outputs": [], + "source": [ + "#dependent variables\n", + "y_train = train_df[\"category\"]\n", + "y_valid = valid_df[\"category\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "Ry4GTGaC6z5t", + "outputId": "30ae3a5e-b10b-4ec6-d907-5323714b1017" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "Ry4GTGaC6z5t", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "30ae3a5e-b10b-4ec6-d907-5323714b1017" - }, - "source": [ - "#text faetures\n", - "from sklearn.feature_extraction.text import TfidfVectorizer\n", - "from sklearn.linear_model import LogisticRegression\n", - "\n", - "tfidf = TfidfVectorizer(tokenizer=process_text, ngram_range=(1,2), min_df=20, sublinear_tf=True)\n", - "tfidf_fit = tfidf.fit(all_df[\"texts\"])\n", - "text_train = tfidf_fit.transform(train_df[\"texts\"])\n", - "text_valid = tfidf_fit.transform(valid_df[\"texts\"])\n", - "text_test = tfidf_fit.transform(test_df[\"texts\"])\n", - "text_train.shape, text_valid.shape" - ], - "execution_count": 17, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "((20453, 4563), (3610, 4563))" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 17 - } + "data": { + "text/plain": [ + "((20453, 4614), (3610, 4614))" ] - }, + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#text faetures\n", + "from sklearn.feature_extraction.text import TfidfVectorizer\n", + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "tfidf = TfidfVectorizer(tokenizer=process_thai, ngram_range=(1,2), min_df=20, sublinear_tf=True)\n", + "tfidf_fit = tfidf.fit(all_df[\"texts\"])\n", + "text_train = tfidf_fit.transform(train_df[\"texts\"])\n", + "text_valid = tfidf_fit.transform(valid_df[\"texts\"])\n", + "text_test = tfidf_fit.transform(test_df[\"texts\"])\n", + "text_train.shape, text_valid.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "7MnvOFdC6z5v", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 51 - }, - "outputId": "a80b5dc6-7973-4be4-8ab6-1be4945f5f03" - }, - "source": [ - "#word count and unique word counts; actually might not be so useful\n", - "from sklearn.preprocessing import StandardScaler\n", - "\n", - "scaler = StandardScaler()\n", - "scaler_fit = scaler.fit(all_df[[\"wc\",\"uwc\"]].astype(float))\n", - "print(scaler_fit.mean_, scaler_fit.var_)\n", - "num_train = scaler_fit.transform(train_df[[\"wc\",\"uwc\"]].astype(float))\n", - "num_valid = scaler_fit.transform(valid_df[[\"wc\",\"uwc\"]].astype(float))\n", - "num_test = scaler_fit.transform(test_df[[\"wc\",\"uwc\"]].astype(float))\n", - "num_train.shape, num_valid.shape" - ], - "execution_count": 20, - "outputs": [ - { - "output_type": "stream", - "text": [ - "[21.55059635 17.94551802] [1081.91655857 490.1667113 ]\n" - ], - "name": "stdout" - }, - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "((20453, 2), (3610, 2))" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 20 - } - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 448 ms, sys: 492 ms, total: 940 ms\n", + "Wall time: 938 ms\n", + "(4614, 5)\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "bj5PA95S6z5w", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "925ecd72-0444-48d0-baa9-1e724d0242f5" - }, - "source": [ - "#concatenate text and word count features\n", - "X_train = np.concatenate([num_train,text_train.toarray()],axis=1)\n", - "X_valid = np.concatenate([num_valid,text_valid.toarray()],axis=1)\n", - "X_test = np.concatenate([num_test,text_test.toarray()],axis=1)\n", - "X_train.shape, X_valid.shape" + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
rankfeaturescorengramlabel
00ไม่0.0299901neg
11กิน0.0228521neg
22xxrep0.0202521neg
33เลย0.0194931neg
44แต่0.0181531neg
\n", + "
" ], - "execution_count": 21, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "((20453, 4565), (3610, 4565))" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 21 - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "W4prkGZr6z5y", - "colab_type": "text" - }, - "source": [ - "### Fit Model" + "text/plain": [ + " rank feature score ngram label\n", + "0 0 ไม่ 0.029990 1 neg\n", + "1 1 กิน 0.022852 1 neg\n", + "2 2 xxrep 0.020252 1 neg\n", + "3 3 เลย 0.019493 1 neg\n", + "4 4 แต่ 0.018153 1 neg" ] - }, + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#visualize texts\n", + "from visualize import top_feats_all, plot_top_feats\n", + "features = tfidf_fit.get_feature_names()\n", + "%time ts = top_feats_all(text_train.toarray(), y_train, features)\n", + "print(ts[0].shape)\n", + "ts[0].head()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "_2IKPcUL6z5z", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "b8e58817-b2ad-440c-9eee-d20e5468a557" - }, - "source": [ - "#fit logistic regression models\n", - "model = LogisticRegression(C=2., penalty=\"l2\", solver=\"liblinear\", dual=False, multi_class=\"ovr\")\n", - "model.fit(X_train,y_train)\n", - "model.score(X_valid,y_valid)" - ], - "execution_count": 22, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "0.7257617728531855" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 22 - } + "data": { + "image/png": "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ZdKkSXh4eODh4UFdXR0zZ87k8OHDzJw5kzZt2pCZmUldXR2PP/44oaGhWCwWgoKCSElJobi4mJycHNq0acMPP/zA0KFD6du372Vfzx7rQNes2Jrm+MuVaBK9iIhcc3PmzKm3rV27dvz1r3+1/uzu7s4LL7xQ77ioqKgrLuwgIiKNZ1d37m3saL+IiIiIiFwdu2r8RURERESkadjVHH8REREREWkaGvEXEREREXEBavxFRERERFyAGn8RERERERfg8Mt52uPazVdL6+HKteDINXA1VCdyNeytDnTdihG0jr9ciUb8RURERERcgF00/rt27WLbtm1GxxARERERcVp2MdXnxIkTVFRUGB1DRERExOZKSkrYtGkT+/fv56677qJ3795GRxInZReNf1xcnNERRERERAwRERFBeno6ERERnDx50ug44sTsovEXERERcWWjRo3C09NTMyCkSdnFHH8RERERV/a73/3O6AjiAjTiL2KgM2fOMH36dPz9/SkrK+P222+nurqaAwcOMHXqVLZs2ULz5s3p0qWL0VFFROQ/UF1dzYwZM/D19aW6upro6Giuv/563nrrLSZNmoSfnx+rV69mxIgRF523ceNG3njjDYKDg6mtrWXkyJF06tTJoHchzsLQxn/z5s2sWrWKwMBAqqqqSExMJDc3l+DgYNzd3Zk6daqR8USa3Nq1axk/fjwdOnQAIDk5GU9PT0pLSykvL2ft2rVMnjzZ4JQi5y1YsICYmBj69u1LQUEB5eXl7Nixw9qQ5OXl0alTJ95++21yc3MBuO2223j99ddp164d//znPzl9+jSbNm3Cw8ODW265hdtuu425c+cSGBhIaWkpI0aMoHv37iQlJREeHk5dXR1lZWWMGjWKzp07G/wvINJ4K1euZNSoUURFRQEwYcIEDh06REhICJ9//jmnTp0iPDy83nlHjx6lRYsW+Pn58eCDD9K2bVtbRxcnZOhUn9LSUnJycpg6dSoxMTG8+uqrZGVlMW3aNCorK6murm7wvLy8PGJjY4mNjaV03xc2Ti1y7SQkJPDee++xbNkyAEwmE8OGDaNFixbMmzeP++67j4CAgHrnqQbECE8++SQrV67kgw8+YMeOHQwfPpwZM2aQk5PD22+/jbu7O/369aOyshKLxcLXX3/Nww8/zJo1awBYt24dv//979mzZw/p6en84Q9/4C9/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\n", + "text/plain": [ + "
" ] + }, + "metadata": {}, + "output_type": "display_data" }, { - "cell_type": "markdown", - "metadata": { - "id": "jFGtgFHF6z51", - "colab_type": "text" - }, - "source": [ - "### See Results" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.36 s, sys: 852 ms, total: 2.21 s\n", + "Wall time: 862 ms\n" + ] + } + ], + "source": [ + "%time plot_top_feats(ts)" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 }, + "colab_type": "code", + "id": "7MnvOFdC6z5v", + "outputId": "a80b5dc6-7973-4be4-8ab6-1be4945f5f03" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "7cub1c5S6z51", - "colab_type": "code", - "colab": {} - }, - "source": [ - "probs = model.predict_proba(X_valid)\n", - "probs_df = pd.DataFrame(probs)\n", - "probs_df.columns = model.classes_\n", - "probs_df[\"preds\"] = model.predict(X_valid)\n", - "probs_df[\"category\"] = valid_df.category\n", - "probs_df[\"texts\"] = valid_df.texts\n", - "probs_df[\"processed\"] = valid_df.processed\n", - "probs_df[\"wc\"] = valid_df.wc\n", - "probs_df[\"uwc\"] = valid_df.uwc\n", - "probs_df[\"hit\"] = (probs_df.preds==probs_df.category)\n", - "probs_df.to_csv(\"probs_df_linear.csv\", index=False)" - ], - "execution_count": 0, - "outputs": [] + "name": "stdout", + "output_type": "stream", + "text": [ + "[21.96529942 18.22744462] [1151.47512883 513.46009207]\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "pa4Q0nPS6z54", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 300 - }, - "outputId": "3e392b32-54c6-4fda-e819-af43e9ba0fd7" - }, - "source": [ - "from sklearn.metrics import confusion_matrix\n", - "\n", - "conf_mat = confusion_matrix(probs_df.category,probs_df.preds)\n", - "print(model.score(X_valid,y_valid))\n", - "sns.heatmap(conf_mat, annot=True, fmt=\"d\",\n", - " xticklabels=model.classes_, yticklabels=model.classes_)\n", - "plt.ylabel(\"Actual\")\n", - "plt.xlabel(\"Predicted\")\n", - "plt.show()" - ], - "execution_count": 24, - "outputs": [ - { - "output_type": "stream", - "text": [ - "0.7257617728531855\n" - ], - "name": "stdout" - }, - { - "output_type": "display_data", - "data": { - "image/png": "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\nAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [] - } - } + "data": { + "text/plain": [ + "((20453, 2), (3610, 2))" ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#word count and unique word counts; actually might not be so useful\n", + "from sklearn.preprocessing import StandardScaler\n", + "\n", + "scaler = StandardScaler()\n", + "scaler_fit = scaler.fit(all_df[[\"wc\",\"uwc\"]].astype(float))\n", + "print(scaler_fit.mean_, scaler_fit.var_)\n", + "num_train = scaler_fit.transform(train_df[[\"wc\",\"uwc\"]].astype(float))\n", + "num_valid = scaler_fit.transform(valid_df[[\"wc\",\"uwc\"]].astype(float))\n", + "num_test = scaler_fit.transform(test_df[[\"wc\",\"uwc\"]].astype(float))\n", + "num_train.shape, num_valid.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "bj5PA95S6z5w", + "outputId": "925ecd72-0444-48d0-baa9-1e724d0242f5" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "KIfXHEVn6z58", - "colab_type": "text" - }, - "source": [ - "## [ULMFit](https://github.com/cstorm125/thai2fit) Model" + "data": { + "text/plain": [ + "((20453, 4616), (3610, 4616))" ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#concatenate text and word count features\n", + "X_train = np.concatenate([num_train,text_train.toarray()],axis=1)\n", + "X_valid = np.concatenate([num_valid,text_valid.toarray()],axis=1)\n", + "X_test = np.concatenate([num_test,text_test.toarray()],axis=1)\n", + "X_train.shape, X_valid.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "W4prkGZr6z5y" + }, + "source": [ + "### Fit Model" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "_2IKPcUL6z5z", + "outputId": "b8e58817-b2ad-440c-9eee-d20e5468a557" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "xPQoEbfC6z58", - "colab_type": "code", - "colab": {} - }, - "source": [ - "from fastai.text import *\n", - "from fastai.callbacks import CSVLogger, SaveModelCallback\n", - "from pythainlp.ulmfit import *\n", - "\n", - "model_path = \"wisesight_data/\"\n", - "all_df = pd.read_csv(\"all_df.csv\")\n", - "train_df, valid_df = train_test_split(all_df, test_size=0.15, random_state=1412)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "RIUQEyb96z5-", - "colab_type": "text" - }, - "source": [ - "### Finetune Language Model" + "data": { + "text/plain": [ + "0.7324099722991689" ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#fit logistic regression models\n", + "model = LogisticRegression(C=2., penalty=\"l2\", solver=\"liblinear\", dual=False, multi_class=\"ovr\")\n", + "model.fit(X_train,y_train)\n", + "model.score(X_valid,y_valid)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "jFGtgFHF6z51" + }, + "source": [ + "### See Results" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "7cub1c5S6z51" + }, + "outputs": [], + "source": [ + "probs = model.predict_proba(X_valid)\n", + "probs_df = pd.DataFrame(probs)\n", + "probs_df.columns = model.classes_\n", + "probs_df[\"preds\"] = model.predict(X_valid)\n", + "probs_df[\"category\"] = valid_df.category\n", + "probs_df[\"texts\"] = valid_df.texts\n", + "probs_df[\"processed\"] = valid_df.processed\n", + "probs_df[\"wc\"] = valid_df.wc\n", + "probs_df[\"uwc\"] = valid_df.uwc\n", + "probs_df[\"hit\"] = (probs_df.preds==probs_df.category)\n", + "probs_df.to_csv(\"probs_df_linear.csv\", index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 }, + "colab_type": "code", + "id": "pa4Q0nPS6z54", + "outputId": "3e392b32-54c6-4fda-e819-af43e9ba0fd7" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "XGpprjbp6z5_", - "colab_type": "code", - "colab": {} - }, - "source": [ - "tt = Tokenizer(tok_func=ThaiTokenizer, lang=\"th\", pre_rules=pre_rules_th, post_rules=post_rules_th)\n", - "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", - " NumericalizeProcessor(vocab=None, max_vocab=60000, min_freq=2)]\n", - "\n", - "data_lm = (TextList.from_df(all_df, model_path, cols=\"texts\", processor=processor)\n", - " .split_by_rand_pct(valid_pct = 0.01, seed = 1412)\n", - " .label_for_lm()\n", - " .databunch(bs=48))\n", - "data_lm.sanity_check()\n", - "data_lm.save('wisesight_lm.pkl')" - ], - "execution_count": 0, - "outputs": [] + "name": "stdout", + "output_type": "stream", + "text": [ + "0.7324099722991689\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "8GiTvaHX6z6A", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "4ca15151-7db8-4bc8-d035-ddcbfc3383e1" - }, - "source": [ - "data_lm.sanity_check()\n", - "len(data_lm.train_ds), len(data_lm.valid_ds)" - ], - "execution_count": 32, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "(23823, 240)" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 32 - } + "data": { + "image/png": "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\n", + "text/plain": [ + "
" ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "\n", + "conf_mat = confusion_matrix(probs_df.category,probs_df.preds)\n", + "print(model.score(X_valid,y_valid))\n", + "sns.heatmap(conf_mat, annot=True, fmt=\"d\",\n", + " xticklabels=model.classes_, yticklabels=model.classes_)\n", + "plt.ylabel(\"Actual\")\n", + "plt.xlabel(\"Predicted\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "KIfXHEVn6z58" + }, + "source": [ + "## [ULMFit](https://github.com/cstorm125/thai2fit) Model" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "xPQoEbfC6z58" + }, + "outputs": [], + "source": [ + "from fastai.text import *\n", + "from fastai.callbacks import CSVLogger, SaveModelCallback\n", + "from pythainlp.ulmfit import *\n", + "\n", + "model_path = \"wisesight_data/\"\n", + "all_df = pd.read_csv(\"all_df.csv\")\n", + "train_df, valid_df = train_test_split(all_df, test_size=0.15, random_state=1412)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RIUQEyb96z5-" + }, + "source": [ + "### Finetune Language Model" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "XGpprjbp6z5_" + }, + "outputs": [], + "source": [ + "tt = Tokenizer(tok_func=ThaiTokenizer, lang=\"th\", pre_rules=pre_rules_th, post_rules=post_rules_th)\n", + "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", + " NumericalizeProcessor(vocab=None, max_vocab=60000, min_freq=2)]\n", + "\n", + "data_lm = (TextList.from_df(all_df, model_path, cols=\"texts\", processor=processor)\n", + " .split_by_rand_pct(valid_pct = 0.01, seed = 1412)\n", + " .label_for_lm()\n", + " .databunch(bs=48))\n", + "data_lm.sanity_check()\n", + "data_lm.save('wisesight_lm.pkl')" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "8GiTvaHX6z6A", + "outputId": "4ca15151-7db8-4bc8-d035-ddcbfc3383e1" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "Bm7PYDIC6z6E", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "outputId": "f768001e-09ee-4572-ea48-ac9e38e7296a" - }, - "source": [ - "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False, tie_weights=True, out_bias=True,\n", - " output_p=0.25, hidden_p=0.1, input_p=0.2, embed_p=0.02, weight_p=0.15)\n", - "trn_args = dict(drop_mult=1., clip=0.12, alpha=2, beta=1)\n", - "\n", - "learn = language_model_learner(data_lm, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", - "\n", - "#load pretrained models\n", - "learn.load_pretrained(**_THWIKI_LSTM)" - ], - "execution_count": 33, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "LanguageLearner(data=TextLMDataBunch;\n", - "\n", - "Train: LabelList (23823 items)\n", - "x: LMTextList\n", - "xxbos ประเทศ เรา ผลิต และ ส่งออก ยาสูบ เยอะ สุด ใน โลก จิง ป่าว คับ,xxbos คะ,xxbos อิ เหี้ย ออม ทำ กู อยาก กิน เอ็ม เค,xxbos xxwrep 2 😅,xxbos สวัสดี วัน พุธ แนน อะไร นะ\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: wisesight_data;\n", - "\n", - "Valid: LabelList (240 items)\n", - "x: LMTextList\n", - "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: wisesight_data;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): AWD_LSTM(\n", - " (encoder): Embedding(15000, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " (1): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[RNNTrainer\n", - "learn: LanguageLearner(data=TextLMDataBunch;\n", - "\n", - "Train: LabelList (23823 items)\n", - "x: LMTextList\n", - "xxbos ประเทศ เรา ผลิต และ ส่งออก ยาสูบ เยอะ สุด ใน โลก จิง ป่าว คับ,xxbos คะ,xxbos อิ เหี้ย ออม ทำ กู อยาก กิน เอ็ม เค,xxbos xxwrep 2 😅,xxbos สวัสดี วัน พุธ แนน อะไร นะ\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: wisesight_data;\n", - "\n", - "Valid: LabelList (240 items)\n", - "x: LMTextList\n", - "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: wisesight_data;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): AWD_LSTM(\n", - " (encoder): Embedding(15000, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " (1): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[...], layer_groups=[Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): Embedding(15000, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (2): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)\n", - "alpha: 2\n", - "beta: 1], layer_groups=[Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): Embedding(15000, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (2): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 33 - } + "data": { + "text/plain": [ + "(23823, 240)" ] + }, + "execution_count": 32, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "data_lm.sanity_check()\n", + "len(data_lm.train_ds), len(data_lm.valid_ds)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 }, + "colab_type": "code", + "id": "Bm7PYDIC6z6E", + "outputId": "f768001e-09ee-4572-ea48-ac9e38e7296a" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "uJK68vJT6z6G", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 97 - }, - "outputId": "9bde3724-568f-4630-afb7-df40b3aff0d4" - }, - "source": [ - "#train frozen\n", - "print(\"training frozen\")\n", - "learn.freeze_to(-1)\n", - "learn.fit_one_cycle(1, 1e-2, moms=(0.8, 0.7))" - ], - "execution_count": 34, - "outputs": [ - { - "output_type": "stream", - "text": [ - "training frozen\n" - ], - "name": "stdout" - }, - { - "output_type": "display_data", - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
epochtrain_lossvalid_lossaccuracytime
04.8411874.4627140.31974202:47
" - ], - "text/plain": [ - "" - ] - }, - "metadata": { - "tags": [] - } - } + "data": { + "text/plain": [ + "LanguageLearner(data=TextLMDataBunch;\n", + "\n", + "Train: LabelList (23823 items)\n", + "x: LMTextList\n", + "xxbos ประเทศ เรา ผลิต และ ส่งออก ยาสูบ เยอะ สุด ใน โลก จิง ป่าว คับ,xxbos คะ,xxbos อิ เหี้ย ออม ทำ กู อยาก กิน เอ็ม เค,xxbos xxwrep 2 😅,xxbos สวัสดี วัน พุธ แนน อะไร นะ\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: wisesight_data;\n", + "\n", + "Valid: LabelList (240 items)\n", + "x: LMTextList\n", + "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: wisesight_data;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): AWD_LSTM(\n", + " (encoder): Embedding(15000, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " (1): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[RNNTrainer\n", + "learn: LanguageLearner(data=TextLMDataBunch;\n", + "\n", + "Train: LabelList (23823 items)\n", + "x: LMTextList\n", + "xxbos ประเทศ เรา ผลิต และ ส่งออก ยาสูบ เยอะ สุด ใน โลก จิง ป่าว คับ,xxbos คะ,xxbos อิ เหี้ย ออม ทำ กู อยาก กิน เอ็ม เค,xxbos xxwrep 2 😅,xxbos สวัสดี วัน พุธ แนน อะไร นะ\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: wisesight_data;\n", + "\n", + "Valid: LabelList (240 items)\n", + "x: LMTextList\n", + "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: wisesight_data;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): AWD_LSTM(\n", + " (encoder): Embedding(15000, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " (1): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[...], layer_groups=[Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): Embedding(15000, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (2): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)\n", + "alpha: 2\n", + "beta: 1], layer_groups=[Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): Embedding(15000, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (2): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=15000, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)" ] + }, + "execution_count": 33, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False, tie_weights=True, out_bias=True,\n", + " output_p=0.25, hidden_p=0.1, input_p=0.2, embed_p=0.02, weight_p=0.15)\n", + "trn_args = dict(drop_mult=1., clip=0.12, alpha=2, beta=1)\n", + "\n", + "learn = language_model_learner(data_lm, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", + "\n", + "#load pretrained models\n", + "learn.load_pretrained(**_THWIKI_LSTM)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 97 }, + "colab_type": "code", + "id": "uJK68vJT6z6G", + "outputId": "9bde3724-568f-4630-afb7-df40b3aff0d4" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "axooWmsg6z6I", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 221 - }, - "outputId": "819107f9-5d37-49ef-dac6-7cde4204656b" - }, - "source": [ - "#train unfrozen\n", - "print(\"training unfrozen\")\n", - "learn.unfreeze()\n", - "learn.fit_one_cycle(5, 1e-3, moms=(0.8, 0.7))" - ], - "execution_count": 35, - "outputs": [ - { - "output_type": "stream", - "text": [ - "training unfrozen\n" - ], - "name": "stdout" - }, - { - "output_type": "display_data", - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
epochtrain_lossvalid_lossaccuracytime
04.4118344.2055520.34176603:31
14.1780304.0370950.36150803:31
23.9703883.9309190.37013903:31
33.7561903.8903980.37619103:31
43.6717043.8902320.37559503:31
" - ], - "text/plain": [ - "" - ] - }, - "metadata": { - "tags": [] - } - } - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "training frozen\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "OZC4BGnB6z6L", - "colab_type": "code", - "colab": {} - }, - "source": [ - "# learn.save('wisesight_lm')\n", - "learn.save_encoder(\"wisesight_enc\")" + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochtrain_lossvalid_lossaccuracytime
04.8411874.4627140.31974202:47
" ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "hTTQ76Ls6z6N", - "colab_type": "text" - }, - "source": [ - "### Train Text Classifier" + "text/plain": [ + "" ] + }, + "metadata": { + "tags": [] + }, + "output_type": "display_data" + } + ], + "source": [ + "#train frozen\n", + "print(\"training frozen\")\n", + "learn.freeze_to(-1)\n", + "learn.fit_one_cycle(1, 1e-2, moms=(0.8, 0.7))" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 221 }, + "colab_type": "code", + "id": "axooWmsg6z6I", + "outputId": "819107f9-5d37-49ef-dac6-7cde4204656b" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "A2Z09Mf26z6N", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "27cfec82-23e3-4e0b-dd0d-7b4ba855e646" - }, - "source": [ - "#lm data\n", - "data_lm = load_data(model_path, \"wisesight_lm.pkl\")\n", - "data_lm.sanity_check()\n", - "\n", - "#classification data\n", - "tt = Tokenizer(tok_func=ThaiTokenizer, lang=\"th\", pre_rules=pre_rules_th, post_rules=post_rules_th)\n", - "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", - " NumericalizeProcessor(vocab=data_lm.vocab, max_vocab=60000, min_freq=20)]\n", - "\n", - "data_cls = (ItemLists(model_path,train=TextList.from_df(train_df, model_path, cols=[\"texts\"], processor=processor),\n", - " valid=TextList.from_df(valid_df, model_path, cols=[\"texts\"], processor=processor))\n", - " .label_from_df(\"category\")\n", - " .databunch(bs=50)\n", - " )\n", - "data_cls.sanity_check()\n", - "print(len(data_cls.vocab.itos))" - ], - "execution_count": 39, - "outputs": [ - { - "output_type": "stream", - "text": [ - "15000\n" - ], - "name": "stdout" - } - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "training unfrozen\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "RjRFWx8-6z6P", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "outputId": "76a4bb55-a3cd-4d51-d5fc-6c2fec878573" - }, - "source": [ - "#model\n", - "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False,\n", - " output_p=0.4, hidden_p=0.2, input_p=0.6, embed_p=0.1, weight_p=0.5)\n", - "trn_args = dict(bptt=70, drop_mult=0.7, alpha=2, beta=1, max_len=500)\n", - "\n", - "learn = text_classifier_learner(data_cls, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", - "#load pretrained finetuned model\n", - "learn.load_encoder(\"wisesight_enc\")" + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochtrain_lossvalid_lossaccuracytime
04.4118344.2055520.34176603:31
14.1780304.0370950.36150803:31
23.9703883.9309190.37013903:31
33.7561903.8903980.37619103:31
43.6717043.8902320.37559503:31
" ], - "execution_count": 40, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "RNNLearner(data=TextClasDataBunch;\n", - "\n", - "Train: LabelList (20453 items)\n", - "x: TextList\n", - "xxbos กันแดด คิว เพลส ตัวใหม่ นี่ คุม มัน ดีจริง อ่ะ นี่ หน้า มัน ยิ่ง ที โซน ยิ่ง มัน เยอะ นีเวีย หลอด ยาว ๆ ฝา เขียว ก็ เอา ไม่อยู่ อ่ะ แล้ว xxunk,xxbos พบ กับ การ ร่วม ตัว ของ ศิลปิน soul pop สาม ยุค สาม สไตล์ ใน งาน jamnight อะไร ก็ช่าง xxunk ( ชุ่ย ) นำ ทีม โดย soul after six , the parkinson และ the xxup toys งาน นี้ นอกจาก จะ ได้ ดู โชว์ แบบ เต็ม รูปแบบ จาก ทั้ง สาม วง แล้ว ยัง มี โชว์ สุด พิเศษ ที่ ทั้ง สาม จะ ร่วม แจม กัน ด้วย ไม่ อยาก ให้ พลาด เจอกัน วันที่ 29 กันยายน นี้ ที่ ช่าง ชุ่ย ประตู เปิด 19.00 น. เป็นต้นไป สามารถ ซื้อ บัตร ได้ แล้ว ที่ event pop : http : / / go . eventpop . me / jamnight * จำกัด ผู้ ที่ มีอายุ 20 ปี ขึ้นไป # jamnightbyjameson # jamesonthailand # soulaftersix # theparkinson # thetoys,xxbos 👌 🏻 👌 🏻 👌 🏻 xxwrep 2 😆,xxbos จ - ศ แถม ถึง 29 ไม่ทัน มะ ว้า xxrep 4 ,xxbos ใช้ ดี ค่ะ บอกต่อ คือ เป็น คน แพ้ ง่าย มาก กก ใช้ กา นิ เย หรือ พอน ก็ แพ้ แต่ ใช้ ครีม แตงโม แล้ว คือ ดี สิว ลด กันน้ำ ค่ะ นี้ ใช้ ไป เล่น สงกรานต์ มา รอด ค่ะ 555 เล่อ ค่า xxrep 5 \n", - "y: CategoryList\n", - "neg,neu,neu,neu,neg\n", - "Path: wisesight_data;\n", - "\n", - "Valid: LabelList (3610 items)\n", - "x: TextList\n", - "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", - "y: CategoryList\n", - "neu,neu,neg,neu,neg\n", - "Path: wisesight_data;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): MultiBatchEncoder(\n", - " (module): AWD_LSTM(\n", - " (encoder): Embedding(15000, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " )\n", - " (1): PoolingLinearClassifier(\n", - " (layers): Sequential(\n", - " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (1): Dropout(p=0.27999999999999997)\n", - " (2): Linear(in_features=1200, out_features=50, bias=True)\n", - " (3): ReLU(inplace)\n", - " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (5): Dropout(p=0.1)\n", - " (6): Linear(in_features=50, out_features=4, bias=True)\n", - " )\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False)], callbacks=[RNNTrainer\n", - "learn: RNNLearner(data=TextClasDataBunch;\n", - "\n", - "Train: LabelList (20453 items)\n", - "x: TextList\n", - "xxbos กันแดด คิว เพลส ตัวใหม่ นี่ คุม มัน ดีจริง อ่ะ นี่ หน้า มัน ยิ่ง ที โซน ยิ่ง มัน เยอะ นีเวีย หลอด ยาว ๆ ฝา เขียว ก็ เอา ไม่อยู่ อ่ะ แล้ว xxunk,xxbos พบ กับ การ ร่วม ตัว ของ ศิลปิน soul pop สาม ยุค สาม สไตล์ ใน งาน jamnight อะไร ก็ช่าง xxunk ( ชุ่ย ) นำ ทีม โดย soul after six , the parkinson และ the xxup toys งาน นี้ นอกจาก จะ ได้ ดู โชว์ แบบ เต็ม รูปแบบ จาก ทั้ง สาม วง แล้ว ยัง มี โชว์ สุด พิเศษ ที่ ทั้ง สาม จะ ร่วม แจม กัน ด้วย ไม่ อยาก ให้ พลาด เจอกัน วันที่ 29 กันยายน นี้ ที่ ช่าง ชุ่ย ประตู เปิด 19.00 น. เป็นต้นไป สามารถ ซื้อ บัตร ได้ แล้ว ที่ event pop : http : / / go . eventpop . me / jamnight * จำกัด ผู้ ที่ มีอายุ 20 ปี ขึ้นไป # jamnightbyjameson # jamesonthailand # soulaftersix # theparkinson # thetoys,xxbos 👌 🏻 👌 🏻 👌 🏻 xxwrep 2 😆,xxbos จ - ศ แถม ถึง 29 ไม่ทัน มะ ว้า xxrep 4 ,xxbos ใช้ ดี ค่ะ บอกต่อ คือ เป็น คน แพ้ ง่าย มาก กก ใช้ กา นิ เย หรือ พอน ก็ แพ้ แต่ ใช้ ครีม แตงโม แล้ว คือ ดี สิว ลด กันน้ำ ค่ะ นี้ ใช้ ไป เล่น สงกรานต์ มา รอด ค่ะ 555 เล่อ ค่า xxrep 5 \n", - "y: CategoryList\n", - "neg,neu,neu,neu,neg\n", - "Path: wisesight_data;\n", - "\n", - "Valid: LabelList (3610 items)\n", - "x: TextList\n", - "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", - "y: CategoryList\n", - "neu,neu,neg,neu,neg\n", - "Path: wisesight_data;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): MultiBatchEncoder(\n", - " (module): AWD_LSTM(\n", - " (encoder): Embedding(15000, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " )\n", - " (1): PoolingLinearClassifier(\n", - " (layers): Sequential(\n", - " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (1): Dropout(p=0.27999999999999997)\n", - " (2): Linear(in_features=1200, out_features=50, bias=True)\n", - " (3): ReLU(inplace)\n", - " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (5): Dropout(p=0.1)\n", - " (6): Linear(in_features=50, out_features=4, bias=True)\n", - " )\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False)], callbacks=[...], layer_groups=[Sequential(\n", - " (0): Embedding(15000, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): PoolingLinearClassifier(\n", - " (layers): Sequential(\n", - " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (1): Dropout(p=0.27999999999999997)\n", - " (2): Linear(in_features=1200, out_features=50, bias=True)\n", - " (3): ReLU(inplace)\n", - " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (5): Dropout(p=0.1)\n", - " (6): Linear(in_features=50, out_features=4, bias=True)\n", - " )\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)\n", - "alpha: 2\n", - "beta: 1], layer_groups=[Sequential(\n", - " (0): Embedding(15000, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(15000, 400, padding_idx=1)\n", - " )\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): PoolingLinearClassifier(\n", - " (layers): Sequential(\n", - " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (1): Dropout(p=0.27999999999999997)\n", - " (2): Linear(in_features=1200, out_features=50, bias=True)\n", - " (3): ReLU(inplace)\n", - " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", - " (5): Dropout(p=0.1)\n", - " (6): Linear(in_features=50, out_features=4, bias=True)\n", - " )\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 40 - } + "text/plain": [ + "" ] + }, + "metadata": { + "tags": [] + }, + "output_type": "display_data" + } + ], + "source": [ + "#train unfrozen\n", + "print(\"training unfrozen\")\n", + "learn.unfreeze()\n", + "learn.fit_one_cycle(5, 1e-3, moms=(0.8, 0.7))" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "OZC4BGnB6z6L" + }, + "outputs": [], + "source": [ + "# learn.save('wisesight_lm')\n", + "learn.save_encoder(\"wisesight_enc\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "hTTQ76Ls6z6N" + }, + "source": [ + "### Train Text Classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "A2Z09Mf26z6N", + "outputId": "27cfec82-23e3-4e0b-dd0d-7b4ba855e646" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "pRgoPD766z6S", - "colab_type": "code", - "colab": {} - }, - "source": [ - "# #train unfrozen\n", - "# learn.freeze_to(-1)\n", - "# learn.fit_one_cycle(1, 2e-2, moms=(0.8, 0.7))\n", - "# learn.freeze_to(-2)\n", - "# learn.fit_one_cycle(1, slice(1e-2 / (2.6 ** 4), 1e-2), moms=(0.8, 0.7))\n", - "# learn.freeze_to(-3)\n", - "# learn.fit_one_cycle(1, slice(5e-3 / (2.6 ** 4), 5e-3), moms=(0.8, 0.7))\n", - "# learn.unfreeze()\n", - "# learn.fit_one_cycle(10, slice(1e-3 / (2.6 ** 4), 1e-3), moms=(0.8, 0.7),\n", - "# callbacks=[SaveModelCallback(learn, every='improvement', monitor='accuracy', name='bestmodel')])" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "w54ZOwk66z6U", - "colab_type": "text" - }, - "source": [ - "Training takes about 20 minutes so we use the script `train_model.py` to do it with the following results (validation run):\n", - "\n", - "```\n", - "epoch train_loss valid_loss accuracy\n", - "1 0.812156 0.753478 0.687532\n", - "Total time: 00:56\n", - "epoch train_loss valid_loss accuracy\n", - "1 0.740403 0.699093 0.714394\n", - "Total time: 00:57\n", - "epoch train_loss valid_loss accuracy\n", - "1 0.727394 0.668807 0.723011\n", - "Total time: 01:34\n", - "epoch train_loss valid_loss accuracy\n", - "1 0.722163 0.675351 0.723517\n", - "2 0.675266 0.654477 0.738723\n", - "3 0.669178 0.641070 0.737962\n", - "4 0.612528 0.637456 0.744551\n", - "5 0.618259 0.635149 0.749366\n", - "6 0.572621 0.651169 0.749873\n", - "7 0.561985 0.661739 0.747593\n", - "8 0.534753 0.673563 0.738469\n", - "9 0.530844 0.688871 0.746072\n", - "10 0.522788 0.670024 0.743031\n", - "Total time: 23:42\n", - "```" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "15000\n" + ] + } + ], + "source": [ + "#lm data\n", + "data_lm = load_data(model_path, \"wisesight_lm.pkl\")\n", + "data_lm.sanity_check()\n", + "\n", + "#classification data\n", + "tt = Tokenizer(tok_func=ThaiTokenizer, lang=\"th\", pre_rules=pre_rules_th, post_rules=post_rules_th)\n", + "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", + " NumericalizeProcessor(vocab=data_lm.vocab, max_vocab=60000, min_freq=20)]\n", + "\n", + "data_cls = (ItemLists(model_path,train=TextList.from_df(train_df, model_path, cols=[\"texts\"], processor=processor),\n", + " valid=TextList.from_df(valid_df, model_path, cols=[\"texts\"], processor=processor))\n", + " .label_from_df(\"category\")\n", + " .databunch(bs=50)\n", + " )\n", + "data_cls.sanity_check()\n", + "print(len(data_cls.vocab.itos))" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 }, + "colab_type": "code", + "id": "RjRFWx8-6z6P", + "outputId": "76a4bb55-a3cd-4d51-d5fc-6c2fec878573" + }, + "outputs": [ { - "cell_type": "markdown", - "metadata": { - "id": "vM--oaCJ6z6V", - "colab_type": "text" - }, - "source": [ - "### See Results" + "data": { + "text/plain": [ + "RNNLearner(data=TextClasDataBunch;\n", + "\n", + "Train: LabelList (20453 items)\n", + "x: TextList\n", + "xxbos กันแดด คิว เพลส ตัวใหม่ นี่ คุม มัน ดีจริง อ่ะ นี่ หน้า มัน ยิ่ง ที โซน ยิ่ง มัน เยอะ นีเวีย หลอด ยาว ๆ ฝา เขียว ก็ เอา ไม่อยู่ อ่ะ แล้ว xxunk,xxbos พบ กับ การ ร่วม ตัว ของ ศิลปิน soul pop สาม ยุค สาม สไตล์ ใน งาน jamnight อะไร ก็ช่าง xxunk ( ชุ่ย ) นำ ทีม โดย soul after six , the parkinson และ the xxup toys งาน นี้ นอกจาก จะ ได้ ดู โชว์ แบบ เต็ม รูปแบบ จาก ทั้ง สาม วง แล้ว ยัง มี โชว์ สุด พิเศษ ที่ ทั้ง สาม จะ ร่วม แจม กัน ด้วย ไม่ อยาก ให้ พลาด เจอกัน วันที่ 29 กันยายน นี้ ที่ ช่าง ชุ่ย ประตู เปิด 19.00 น. เป็นต้นไป สามารถ ซื้อ บัตร ได้ แล้ว ที่ event pop : http : / / go . eventpop . me / jamnight * จำกัด ผู้ ที่ มีอายุ 20 ปี ขึ้นไป # jamnightbyjameson # jamesonthailand # soulaftersix # theparkinson # thetoys,xxbos 👌 🏻 👌 🏻 👌 🏻 xxwrep 2 😆,xxbos จ - ศ แถม ถึง 29 ไม่ทัน มะ ว้า xxrep 4 ,xxbos ใช้ ดี ค่ะ บอกต่อ คือ เป็น คน แพ้ ง่าย มาก กก ใช้ กา นิ เย หรือ พอน ก็ แพ้ แต่ ใช้ ครีม แตงโม แล้ว คือ ดี สิว ลด กันน้ำ ค่ะ นี้ ใช้ ไป เล่น สงกรานต์ มา รอด ค่ะ 555 เล่อ ค่า xxrep 5 \n", + "y: CategoryList\n", + "neg,neu,neu,neu,neg\n", + "Path: wisesight_data;\n", + "\n", + "Valid: LabelList (3610 items)\n", + "x: TextList\n", + "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", + "y: CategoryList\n", + "neu,neu,neg,neu,neg\n", + "Path: wisesight_data;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): MultiBatchEncoder(\n", + " (module): AWD_LSTM(\n", + " (encoder): Embedding(15000, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " )\n", + " (1): PoolingLinearClassifier(\n", + " (layers): Sequential(\n", + " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (1): Dropout(p=0.27999999999999997)\n", + " (2): Linear(in_features=1200, out_features=50, bias=True)\n", + " (3): ReLU(inplace)\n", + " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (5): Dropout(p=0.1)\n", + " (6): Linear(in_features=50, out_features=4, bias=True)\n", + " )\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False)], callbacks=[RNNTrainer\n", + "learn: RNNLearner(data=TextClasDataBunch;\n", + "\n", + "Train: LabelList (20453 items)\n", + "x: TextList\n", + "xxbos กันแดด คิว เพลส ตัวใหม่ นี่ คุม มัน ดีจริง อ่ะ นี่ หน้า มัน ยิ่ง ที โซน ยิ่ง มัน เยอะ นีเวีย หลอด ยาว ๆ ฝา เขียว ก็ เอา ไม่อยู่ อ่ะ แล้ว xxunk,xxbos พบ กับ การ ร่วม ตัว ของ ศิลปิน soul pop สาม ยุค สาม สไตล์ ใน งาน jamnight อะไร ก็ช่าง xxunk ( ชุ่ย ) นำ ทีม โดย soul after six , the parkinson และ the xxup toys งาน นี้ นอกจาก จะ ได้ ดู โชว์ แบบ เต็ม รูปแบบ จาก ทั้ง สาม วง แล้ว ยัง มี โชว์ สุด พิเศษ ที่ ทั้ง สาม จะ ร่วม แจม กัน ด้วย ไม่ อยาก ให้ พลาด เจอกัน วันที่ 29 กันยายน นี้ ที่ ช่าง ชุ่ย ประตู เปิด 19.00 น. เป็นต้นไป สามารถ ซื้อ บัตร ได้ แล้ว ที่ event pop : http : / / go . eventpop . me / jamnight * จำกัด ผู้ ที่ มีอายุ 20 ปี ขึ้นไป # jamnightbyjameson # jamesonthailand # soulaftersix # theparkinson # thetoys,xxbos 👌 🏻 👌 🏻 👌 🏻 xxwrep 2 😆,xxbos จ - ศ แถม ถึง 29 ไม่ทัน มะ ว้า xxrep 4 ,xxbos ใช้ ดี ค่ะ บอกต่อ คือ เป็น คน แพ้ ง่าย มาก กก ใช้ กา นิ เย หรือ พอน ก็ แพ้ แต่ ใช้ ครีม แตงโม แล้ว คือ ดี สิว ลด กันน้ำ ค่ะ นี้ ใช้ ไป เล่น สงกรานต์ มา รอด ค่ะ 555 เล่อ ค่า xxrep 5 \n", + "y: CategoryList\n", + "neg,neu,neu,neu,neg\n", + "Path: wisesight_data;\n", + "\n", + "Valid: LabelList (3610 items)\n", + "x: TextList\n", + "xxbos เห็น คน ลบ แอ พ viu ก็ เห็นใจ และ เข้าใจ เขา นะคะ แผล มัน ยัง ใหม่ แถม อารมณ์ ยิ่ง โดน xxunk ง่าย อยู่ นี่ เนอะ 5 xxrep 7 ส่วน ทาง นี้ ก็ กอด netflix แน่น มาก เธอ อย่า ทำร้าย เรา นะ เรา รู้ เธอ ไม่ ทำร้าย เรา แน่นอน,xxbos ไป ชม ไม้ คิว ของ แชมป์ และ รอง แชมป์ กัน จ้า ! . xxrep 32 เก็บตก จาก การแข่งขัน แสงโสม สนุกเกอร์ 6 แดง โอเพ่น ประจำปี 2560 สนาม ที่ 2 ณ มัง กี้ สนุกเกอร์ คลับ ซอย โชค ชัย 4 ลาดพร้าว เมื่อ วันที่ 12 ต.ค. 60,xxbos กลุ่ม รถ ซีวิค เป็น กลุ่ม ที่ น่า รำ คาน มาก xxrep 9 อวด รถ กัน ได้ ทุก วินาที อวด ทำไม มึง ก็ ใช้ รถ เหมือนกัน ทุกคน ละ ก็ พวก xxunk ที่ บอ กว่า อวด รถ แต่ ถ่าย นม ตัวเอง ชัด ละ รถ เบลอ นี่ คือ ? xxrep 5 ,xxbos อยาก สวย เหมือน เจ้าของ แบรนด์ สิ คะ เนย โชติ กา ใบหน้า สวย ใส xxunk แม้ แต่งหน้า นี่ ขนาด เป็น คุณแม่ แล้ว นะเนี่ย ก็ ยัง สวย ไม่ xxunk ผ่าน ไป กี่ ปี ๆ ก็ ไม่ เปลี่ยน ผิว ดี๊ ดี ความ สวย . เรา สร้าง เอง ได้ ด้วยตัวเอง ถ้า ได้ ใช้ มาส ์กโช ต้อง สวย เหมือน โชติ กา แน่นอน ค่ะ # มาส ์กโช สวย ข้ามคืน # cho _ cosmetics # daradaily # ดารา เดลี่,xxbos ข้าว โถ ละ ร้อย แพง เพราะ ตัก เป็น จาน ๆ ละ 15 เต็มที่ ก็ 5 จาน คนไทย ต้อง กินข้าว ประเทศ xxunk ข้าว กินข้าว ในประเทศ ตัวเอง หม้อ เป็น ร้อย เป็นลม ดีกว่า ค่า ฉะ xxunk ถุง 5 โล ไม่ เกิน 200 เป็น ข้าว มะลิ ไก่ นี่ ไม่รู้ ว่า เป็นตัว หรือเปล่า แต่ ถ้า ตัว ละ 250 บาท แพง ไก่ย่าง ขาย 140 - 160 มี เยอะแยะ ยัง ได้ กำไร แพง สุด ไม่ ควร xxunk 200 ข้าวผัด ปู จาน ใหญ่ 300 ร้อย แพง ถ้า ผัด เป็น จาน ๆ ละ 50 ผัด 4 จาน ก็ เต็ม ถาด ใหญ่ แล้ว ส่วน เครื่อง ดืม ด้านบน อะไร 80 ถ้า เป็น ชาเย็น แพง มาก น้ำ ดืม ขวด ใหญ่ ขวด ละ 50 แพง บ้าน เรา เมืองร้อน อย่า เห็นแก่ตัว 30 ก็ พอแล้ว คน ต้อง ซื้อ เยอะ เบียร์ ช้าง ขวด ละ 120 กำไร xxunk น่าเกลียด มา 3 ขวด 360 แพง xxunk ขวด ใหญ่ ก็ แพง แต่ น้ำแข็ง พอได้ เพราะ อากาศ บ้าน เรา ร้อน ละลาย ง่าย อันนี้ พอ เข้าใจ คน ขาย แต่ ทะเล เผา ทะเล ลวก ไม่เห็น หน้าตา ว่า มี อะไร บ้าง ก็ กุ้ง หมึก ปู xxunk 300 ตัว กลางๆ ใส่ มา อย่าง 5 ตัว ปู สัก ตัว กำไร xxunk ตำ ทะเล ตำ กุ้ง สด 150 ไม่ แพง กุ้ง ชุ ป แป้ง ทอด แพง มาก ๆ ต้มยำ หม้อ ละ 300 ร้อย ถือว่า แพง มาก เพราะ มัน ใส่ ได้ ไม่ เยอะ หรอก มันดี ตรง ที่ มี น้ำ กับ ไฟ อุ่น ร้อน ของ กินใน บ้าน ยัง แทบ แตะ ไม่ได้ ทั้งที่ ป ระ ก็ xxunk คน ในประเทศ ยัง กิน ไม่ อิม ส่งออก นอก พอ มี น้อย เหลือ น้อย ก็ ขาย ให้ กัน แพง ๆ ระบบ แย่ เอาเปรียบ กันเอง ที่ บ้าน ขาย อาหาร กับข้าว ตาม สั่ง ป รุ่ง สุก ใหม่ แค่ จาน ละ 100 - 150 คน ยัง ว่า แพง ทั้งที่ บอ กว่า อร่อย ถ้า ไป เจอ แบบนี้ สงสัย ช็อค ตาย คา ร้าน เลย มัง ถ้า ต้อง ไป เจอ ทั้ง แพง ทั้ง ไม่อร่อย สัก แต่ ทำ ขาย ใคร ว่า ไม่ แพง ยินดี ด้วย ที่ คุณ เป็น คน มี ตัง แต่ เรา มอง จาก ค่าแรง กลางๆ ของ คน ในประเทศ นะ ซึ่ง ส่วนมาก คนใน ประเทศไทย ได้ แต่ ค่าแรงขั้นต่ำ กับ เบี้ย ขยัน เล็กน้อย คนจน เยอะ กว่า คนรวย ด้วย ทำ อะไร ต้อง นึกถึง ความ สมควร นึกถึง กันและกัน แต่ เรา ไม่ใช่ คน xxunk ชอบ มอง และ คิด จาก ความเป็นจริง ถึง ขาย ให้ ชาวต่างชาติ ก็ เถอะ เหมือน คนไทย เอาเปรียบ ช่วย โอกาส และ ไม่ ค่อย xxunk\n", + "y: CategoryList\n", + "neu,neu,neg,neu,neg\n", + "Path: wisesight_data;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): MultiBatchEncoder(\n", + " (module): AWD_LSTM(\n", + " (encoder): Embedding(15000, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " )\n", + " (1): PoolingLinearClassifier(\n", + " (layers): Sequential(\n", + " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (1): Dropout(p=0.27999999999999997)\n", + " (2): Linear(in_features=1200, out_features=50, bias=True)\n", + " (3): ReLU(inplace)\n", + " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (5): Dropout(p=0.1)\n", + " (6): Linear(in_features=50, out_features=4, bias=True)\n", + " )\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('wisesight_data'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False)], callbacks=[...], layer_groups=[Sequential(\n", + " (0): Embedding(15000, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): PoolingLinearClassifier(\n", + " (layers): Sequential(\n", + " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (1): Dropout(p=0.27999999999999997)\n", + " (2): Linear(in_features=1200, out_features=50, bias=True)\n", + " (3): ReLU(inplace)\n", + " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (5): Dropout(p=0.1)\n", + " (6): Linear(in_features=50, out_features=4, bias=True)\n", + " )\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)\n", + "alpha: 2\n", + "beta: 1], layer_groups=[Sequential(\n", + " (0): Embedding(15000, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(15000, 400, padding_idx=1)\n", + " )\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): PoolingLinearClassifier(\n", + " (layers): Sequential(\n", + " (0): BatchNorm1d(1200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (1): Dropout(p=0.27999999999999997)\n", + " (2): Linear(in_features=1200, out_features=50, bias=True)\n", + " (3): ReLU(inplace)\n", + " (4): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (5): Dropout(p=0.1)\n", + " (6): Linear(in_features=50, out_features=4, bias=True)\n", + " )\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)" ] - }, - { - "cell_type": "code", - "metadata": { - "id": "eOCe24KL6z6W", - "colab_type": "code", - "colab": {} - }, - "source": [ - "learn.load(\"bestmodel\")\n", - "\n", - "#get predictions\n", - "probs, y_true, loss = learn.get_preds(ds_type = DatasetType.Valid, ordered=True, with_loss=True)\n", - "classes = learn.data.train_ds.classes\n", - "y_true = np.array([classes[i] for i in y_true.numpy()])\n", - "preds = np.array([classes[i] for i in probs.argmax(1).numpy()])\n", - "prob = probs.numpy()\n", - "loss = loss.numpy()" - ], - "execution_count": 0, - "outputs": [] - }, + }, + "execution_count": 40, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "#model\n", + "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False,\n", + " output_p=0.4, hidden_p=0.2, input_p=0.6, embed_p=0.1, weight_p=0.5)\n", + "trn_args = dict(bptt=70, drop_mult=0.7, alpha=2, beta=1, max_len=500)\n", + "\n", + "learn = text_classifier_learner(data_cls, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", + "#load pretrained finetuned model\n", + "learn.load_encoder(\"wisesight_enc\")" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "pRgoPD766z6S" + }, + "outputs": [], + "source": [ + "# #train unfrozen\n", + "# learn.freeze_to(-1)\n", + "# learn.fit_one_cycle(1, 2e-2, moms=(0.8, 0.7))\n", + "# learn.freeze_to(-2)\n", + "# learn.fit_one_cycle(1, slice(1e-2 / (2.6 ** 4), 1e-2), moms=(0.8, 0.7))\n", + "# learn.freeze_to(-3)\n", + "# learn.fit_one_cycle(1, slice(5e-3 / (2.6 ** 4), 5e-3), moms=(0.8, 0.7))\n", + "# learn.unfreeze()\n", + "# learn.fit_one_cycle(10, slice(1e-3 / (2.6 ** 4), 1e-3), moms=(0.8, 0.7),\n", + "# callbacks=[SaveModelCallback(learn, every='improvement', monitor='accuracy', name='bestmodel')])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "w54ZOwk66z6U" + }, + "source": [ + "Training takes about 20 minutes so we use the script `train_model.py` to do it with the following results (validation run):\n", + "\n", + "```\n", + "epoch train_loss valid_loss accuracy\n", + "1 0.812156 0.753478 0.687532\n", + "Total time: 00:56\n", + "epoch train_loss valid_loss accuracy\n", + "1 0.740403 0.699093 0.714394\n", + "Total time: 00:57\n", + "epoch train_loss valid_loss accuracy\n", + "1 0.727394 0.668807 0.723011\n", + "Total time: 01:34\n", + "epoch train_loss valid_loss accuracy\n", + "1 0.722163 0.675351 0.723517\n", + "2 0.675266 0.654477 0.738723\n", + "3 0.669178 0.641070 0.737962\n", + "4 0.612528 0.637456 0.744551\n", + "5 0.618259 0.635149 0.749366\n", + "6 0.572621 0.651169 0.749873\n", + "7 0.561985 0.661739 0.747593\n", + "8 0.534753 0.673563 0.738469\n", + "9 0.530844 0.688871 0.746072\n", + "10 0.522788 0.670024 0.743031\n", + "Total time: 23:42\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vM--oaCJ6z6V" + }, + "source": [ + "### See Results" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "eOCe24KL6z6W" + }, + "outputs": [], + "source": [ + "learn.load(\"bestmodel\")\n", + "\n", + "#get predictions\n", + "probs, y_true, loss = learn.get_preds(ds_type = DatasetType.Valid, ordered=True, with_loss=True)\n", + "classes = learn.data.train_ds.classes\n", + "y_true = np.array([classes[i] for i in y_true.numpy()])\n", + "preds = np.array([classes[i] for i in probs.argmax(1).numpy()])\n", + "prob = probs.numpy()\n", + "loss = loss.numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "LaJYU8f56z6Z", + "outputId": "28603bc9-8cf5-4aba-cfee-836d4c6b5b91" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "LaJYU8f56z6Z", - "colab_type": "code", - "colab": {}, - "outputId": "28603bc9-8cf5-4aba-cfee-836d4c6b5b91" - }, - "source": [ - "to_df = np.concatenate([y_true[:,None],preds[:,None],loss[:,None],prob],1)\n", - "probs_df = pd.DataFrame(to_df)\n", - "probs_df.columns = [\"category\",\"preds\",\"loss\"] + classes\n", - "probs_df[\"hit\"] = (probs_df.category == probs_df.preds)\n", - "probs_df[\"texts\"] = valid_df.texts\n", - "(y_true==preds).mean()" - ], - "execution_count": 0, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "0.8392661555312158" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 32 - } + "data": { + "text/plain": [ + "0.8392661555312158" ] - }, + }, + "execution_count": 32, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "to_df = np.concatenate([y_true[:,None],preds[:,None],loss[:,None],prob],1)\n", + "probs_df = pd.DataFrame(to_df)\n", + "probs_df.columns = [\"category\",\"preds\",\"loss\"] + classes\n", + "probs_df[\"hit\"] = (probs_df.category == probs_df.preds)\n", + "probs_df[\"texts\"] = valid_df.texts\n", + "(y_true==preds).mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "l_evHEMM6z6b", + "outputId": "732e91f4-a281-4a70-bf3b-8c6d43cad41a" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "l_evHEMM6z6b", - "colab_type": "code", - "colab": {}, - "outputId": "732e91f4-a281-4a70-bf3b-8c6d43cad41a" - }, - "source": [ - "from sklearn.metrics import confusion_matrix\n", - "import seaborn as sns\n", - "\n", - "conf_mat = confusion_matrix(probs_df.category,probs_df.preds)\n", - "sns.heatmap(conf_mat, annot=True, fmt=\"d\",\n", - " xticklabels=classes, yticklabels=classes)\n", - "plt.ylabel(\"Actual\")\n", - "plt.xlabel(\"Predicted\")\n", - "plt.show()" - ], - "execution_count": 0, - "outputs": [ - { - "output_type": "display_data", - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [], - "needs_background": "light" - } - } + "data": { + "image/png": "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\n", + "text/plain": [ + "
" ] + }, + "metadata": { + "needs_background": "light", + "tags": [] + }, + "output_type": "display_data" } - ] -} \ No newline at end of file + ], + "source": [ + "from sklearn.metrics import confusion_matrix\n", + "import seaborn as sns\n", + "\n", + "conf_mat = confusion_matrix(probs_df.category,probs_df.preds)\n", + "sns.heatmap(conf_mat, annot=True, fmt=\"d\",\n", + " xticklabels=classes, yticklabels=classes)\n", + "plt.ylabel(\"Actual\")\n", + "plt.xlabel(\"Predicted\")\n", + "plt.show()" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "name": "sentiment_analysis.ipynb", + "provenance": [], + "version": "0.3.2" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/text_generation.ipynb b/notebooks/text_generation.ipynb index f39407fcc..63918e2a6 100644 --- a/notebooks/text_generation.ipynb +++ b/notebooks/text_generation.ipynb @@ -1,638 +1,553 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.8" - }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vfD07MBXKROC" + }, + "source": [ + "# Thai Wiki Language Model for Text Generation" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "BunBriX0KROF" + }, + "source": [ + "This notebook details how you can use pretrained language model on [Thai Wikipedia Dump](https://dumps.wikimedia.org/thwiki/latest/thwiki-latest-pages-articles.xml.bz2) to generate texts." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { "colab": { - "name": "text_generation.ipynb", - "version": "0.3.2", - "provenance": [] + "base_uri": "https://localhost:8080/", + "height": 1000 }, - "accelerator": "GPU" + "colab_type": "code", + "id": "O8IVDoE9KROG", + "outputId": "935e7e3e-6f0d-4880-86b8-30df8e2eb853" + }, + "outputs": [], + "source": [ + "# #uncomment if you are running from google colab\n", + "# !pip install sklearn_crfsuite\n", + "# !pip install https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", + "# !pip install fastai\n", + "# !pip install emoji" + ] }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "vfD07MBXKROC", - "colab_type": "text" - }, - "source": [ - "# Thai Wiki Language Model for Text Generation" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "BunBriX0KROF", - "colab_type": "text" - }, - "source": [ - "This notebook details how you can use pretrained language model on [Thai Wikipedia Dump](https://dumps.wikimedia.org/thwiki/latest/thwiki-latest-pages-articles.xml.bz2) to generate texts." - ] + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 119 }, + "colab_type": "code", + "id": "DvwUYZGmKROK", + "outputId": "03569098-5d70-4756-f8b4-c77de3cd4b5c" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "O8IVDoE9KROG", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "outputId": "935e7e3e-6f0d-4880-86b8-30df8e2eb853" - }, - "source": [ - "#uncomment if you are running from google colab\n", - "!pip install sklearn_crfsuite\n", - "!pip install https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "!pip install fastai\n", - "!pip install emoji" - ], - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "text": [ - "Requirement already satisfied: sklearn_crfsuite in /usr/local/lib/python3.6/dist-packages (0.3.6)\n", - "Requirement already satisfied: python-crfsuite>=0.8.3 in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (0.9.6)\n", - "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (1.12.0)\n", - "Requirement already satisfied: tqdm>=2.0 in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (4.28.1)\n", - "Requirement already satisfied: tabulate in /usr/local/lib/python3.6/dist-packages (from sklearn_crfsuite) (0.8.3)\n", - "Collecting https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "\u001b[?25l Downloading https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", - "\u001b[K - 11.2MB 218kB/s\n", - "\u001b[?25hRequirement already satisfied (use --upgrade to upgrade): pythainlp==2.1.dev2 from https://github.com/PyThaiNLP/pythainlp/archive/dev.zip in /usr/local/lib/python3.6/dist-packages\n", - "Requirement already satisfied: dill in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (0.3.0)\n", - "Requirement already satisfied: marisa-trie==0.7.4 in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (0.7.4)\n", - "Requirement already satisfied: nltk>=3.2.2 in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (3.2.5)\n", - "Requirement already satisfied: pytz in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (2018.9)\n", - "Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (2.21.0)\n", - "Requirement already satisfied: tinydb in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (3.13.0)\n", - "Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (from pythainlp==2.1.dev2) (4.28.1)\n", - "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from nltk>=3.2.2->pythainlp==2.1.dev2) (1.12.0)\n", - "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (2.8)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (2019.6.16)\n", - "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (1.24.3)\n", - "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->pythainlp==2.1.dev2) (3.0.4)\n", - "Building wheels for collected packages: pythainlp\n", - " Building wheel for pythainlp (setup.py) ... \u001b[?25l\u001b[?25hdone\n", - " Created wheel for pythainlp: filename=pythainlp-2.1.dev2-cp36-none-any.whl size=11014043 sha256=3dfa6501ae5079e51204d5ab850ab32965c85f27bb642a67712b39b106feb3fc\n", - " Stored in directory: /tmp/pip-ephem-wheel-cache-5gfc5rda/wheels/79/4e/1e/26f3198c6712ecfbee92928ed1dde923a078da3d222401cc78\n", - "Successfully built pythainlp\n", - "Requirement already satisfied: fastai in /usr/local/lib/python3.6/dist-packages (1.0.57)\n", - "Requirement already satisfied: pyyaml in /usr/local/lib/python3.6/dist-packages (from fastai) (3.13)\n", - "Requirement already satisfied: spacy>=2.0.18 in /usr/local/lib/python3.6/dist-packages (from fastai) (2.1.8)\n", - "Requirement already satisfied: typing; python_version < \"3.7\" in /usr/local/lib/python3.6/dist-packages (from fastai) (3.7.4)\n", - "Requirement already satisfied: scipy in /usr/local/lib/python3.6/dist-packages (from fastai) (1.3.1)\n", - "Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.6/dist-packages (from fastai) (4.6.3)\n", - "Requirement already satisfied: packaging in /usr/local/lib/python3.6/dist-packages (from fastai) (19.1)\n", - "Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from fastai) (3.0.3)\n", - "Requirement already satisfied: Pillow in /usr/local/lib/python3.6/dist-packages (from fastai) (4.3.0)\n", - "Requirement already satisfied: torch>=1.0.0 in /usr/local/lib/python3.6/dist-packages (from fastai) (1.1.0)\n", - "Requirement already satisfied: fastprogress>=0.1.19 in /usr/local/lib/python3.6/dist-packages (from fastai) (0.1.21)\n", - "Requirement already satisfied: torchvision in /usr/local/lib/python3.6/dist-packages (from fastai) (0.3.0)\n", - "Requirement already satisfied: nvidia-ml-py3 in /usr/local/lib/python3.6/dist-packages (from fastai) (7.352.0)\n", - "Requirement already satisfied: bottleneck in /usr/local/lib/python3.6/dist-packages (from fastai) (1.2.1)\n", - "Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from fastai) (2.21.0)\n", - "Requirement already satisfied: numexpr in /usr/local/lib/python3.6/dist-packages (from fastai) (2.6.9)\n", - "Requirement already satisfied: numpy>=1.15 in /usr/local/lib/python3.6/dist-packages (from fastai) (1.16.4)\n", - "Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from fastai) (0.24.2)\n", - "Requirement already satisfied: dataclasses; python_version < \"3.7\" in /usr/local/lib/python3.6/dist-packages (from fastai) (0.6)\n", - "Requirement already satisfied: wasabi<1.1.0,>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.2.2)\n", - "Requirement already satisfied: plac<1.0.0,>=0.9.6 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.9.6)\n", - "Requirement already satisfied: blis<0.3.0,>=0.2.2 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.2.4)\n", - "Requirement already satisfied: srsly<1.1.0,>=0.0.6 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.0.7)\n", - "Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (1.0.2)\n", - "Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (2.0.2)\n", - "Requirement already satisfied: thinc<7.1.0,>=7.0.8 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (7.0.8)\n", - "Requirement already satisfied: preshed<2.1.0,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (2.0.1)\n", - "Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.6/dist-packages (from packaging->fastai) (2.4.2)\n", - "Requirement already satisfied: attrs in /usr/local/lib/python3.6/dist-packages (from packaging->fastai) (19.1.0)\n", - "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from packaging->fastai) (1.12.0)\n", - "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (0.10.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (1.1.0)\n", - "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (2.5.3)\n", - "Requirement already satisfied: olefile in /usr/local/lib/python3.6/dist-packages (from Pillow->fastai) (0.46)\n", - "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (1.24.3)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (2019.6.16)\n", - "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (2.8)\n", - "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (3.0.4)\n", - "Requirement already satisfied: pytz>=2011k in /usr/local/lib/python3.6/dist-packages (from pandas->fastai) (2018.9)\n", - "Requirement already satisfied: tqdm<5.0.0,>=4.10.0 in /usr/local/lib/python3.6/dist-packages (from thinc<7.1.0,>=7.0.8->spacy>=2.0.18->fastai) (4.28.1)\n", - "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from kiwisolver>=1.0.1->matplotlib->fastai) (41.0.1)\n", - "Collecting emoji\n", - "\u001b[?25l Downloading https://files.pythonhosted.org/packages/1b/d7/2746b4dd67375ce253e777ba54869545d24d2b0249ebcf83735c99df68d5/emoji-0.5.3.tar.gz (43kB)\n", - "\u001b[K |████████████████████████████████| 51kB 4.4MB/s \n", - "\u001b[?25hBuilding wheels for collected packages: emoji\n", - " Building wheel for emoji (setup.py) ... \u001b[?25l\u001b[?25hdone\n", - " Created wheel for emoji: filename=emoji-0.5.3-cp36-none-any.whl size=42175 sha256=c3f1611ca03c91684bc818c0ad78dcb8d0542c7eab7fc3dfe3a6640090c8f196\n", - " Stored in directory: /root/.cache/pip/wheels/86/09/26/f944015841423cd516e8a97f30e29be59e53461aea8b7d3458\n", - "Successfully built emoji\n", - "Installing collected packages: emoji\n", - "Successfully installed emoji-0.5.3\n" - ], - "name": "stdout" - } - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "Download: wiki_lm_lstm\n", + "wiki_lm_lstm 0.32\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "DvwUYZGmKROK", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 119 - }, - "outputId": "03569098-5d70-4756-f8b4-c77de3cd4b5c" - }, - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "from ast import literal_eval\n", - "from tqdm import tqdm_notebook\n", - "from collections import Counter\n", - "import re\n", - "\n", - "#viz\n", - "import matplotlib.pyplot as plt\n", - "import seaborn as sns\n", - "\n", - "#fastai\n", - "import fastai\n", - "from fastai.text import *\n", - "from fastai.callbacks import CSVLogger\n", - "\n", - "#pythainlp\n", - "from pythainlp.ulmfit import *" - ], - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "text": [ - "Download: wiki_lm_lstm\n", - "wiki_lm_lstm 0.32\n" - ], - "name": "stdout" - }, - { - "output_type": "stream", - "text": [ - "100%|██████████| 1050919089/1050919089 [00:25<00:00, 41157162.35it/s]\n" - ], - "name": "stderr" - }, - { - "output_type": "stream", - "text": [ - "Download: wiki_itos_lstm\n", - "wiki_itos_lstm 0.32\n" - ], - "name": "stdout" - }, - { - "output_type": "stream", - "text": [ - "100%|██████████| 1530484/1530484 [00:00<00:00, 19090275.60it/s]\n" - ], - "name": "stderr" - } - ] + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1050919089/1050919089 [00:25<00:00, 41157162.35it/s]\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "PnQcr3gWKROS", - "colab_type": "code", - "colab": {} - }, - "source": [ - "#get dummy data\n", - "imdb = untar_data(URLs.IMDB_SAMPLE)\n", - "dummy_df = pd.read_csv(imdb/'texts.csv')\n", - "\n", - "#get vocab\n", - "thwiki_itos = pickle.load(open(_THWIKI_LSTM['itos_fname'],'rb'))\n", - "thwiki_vocab = fastai.text.transform.Vocab(thwiki_itos)\n", - "\n", - "#dummy databunch\n", - "tt = Tokenizer(tok_func = ThaiTokenizer, lang = 'th', pre_rules = pre_rules_th, post_rules=post_rules_th)\n", - "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", - " NumericalizeProcessor(vocab=thwiki_vocab, max_vocab=60000, min_freq=3)]\n", - "data_lm = (TextList.from_df(dummy_df, imdb, cols=['text'], processor=processor)\n", - " .random_split_by_pct(0.2)\n", - " .label_for_lm()\n", - " .databunch(bs=64))\n", - "\n", - "\n", - "data_lm.sanity_check()" - ], - "execution_count": 0, - "outputs": [] + "name": "stdout", + "output_type": "stream", + "text": [ + "Download: wiki_itos_lstm\n", + "wiki_itos_lstm 0.32\n" + ] }, { - "cell_type": "code", - "metadata": { - "id": "VJI1MZzvKROW", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 34 - }, - "outputId": "f8db8372-fc6a-44ff-f7cd-9e4e8d99684b" - }, - "source": [ - "#check vocab size\n", - "len(data_lm.vocab.itos)" - ], - "execution_count": 6, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "60005" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 6 - } - ] + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1530484/1530484 [00:00<00:00, 19090275.60it/s]\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from ast import literal_eval\n", + "from tqdm import tqdm_notebook\n", + "from collections import Counter\n", + "import re\n", + "\n", + "#viz\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "#fastai\n", + "import fastai\n", + "from fastai.text import *\n", + "from fastai.callbacks import CSVLogger\n", + "\n", + "#pythainlp\n", + "from pythainlp.ulmfit import *" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "PnQcr3gWKROS" + }, + "outputs": [], + "source": [ + "#get dummy data\n", + "imdb = untar_data(URLs.IMDB_SAMPLE)\n", + "dummy_df = pd.read_csv(imdb/'texts.csv')\n", + "\n", + "#get vocab\n", + "thwiki_itos = pickle.load(open(_THWIKI_LSTM['itos_fname'],'rb'))\n", + "thwiki_vocab = fastai.text.transform.Vocab(thwiki_itos)\n", + "\n", + "#dummy databunch\n", + "tt = Tokenizer(tok_func = ThaiTokenizer, lang = 'th', pre_rules = pre_rules_th, post_rules=post_rules_th)\n", + "processor = [TokenizeProcessor(tokenizer=tt, chunksize=10000, mark_fields=False),\n", + " NumericalizeProcessor(vocab=thwiki_vocab, max_vocab=60000, min_freq=3)]\n", + "data_lm = (TextList.from_df(dummy_df, imdb, cols=['text'], processor=processor)\n", + " .random_split_by_pct(0.2)\n", + " .label_for_lm()\n", + " .databunch(bs=64))\n", + "\n", + "\n", + "data_lm.sanity_check()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 }, + "colab_type": "code", + "id": "VJI1MZzvKROW", + "outputId": "f8db8372-fc6a-44ff-f7cd-9e4e8d99684b" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "B9DJVRZ-KROb", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "outputId": "54031979-d708-4550-d0b7-8cd42b07cf96" - }, - "source": [ - "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False, tie_weights=True, out_bias=True,\n", - " output_p=0.25, hidden_p=0.1, input_p=0.2, embed_p=0.02, weight_p=0.15)\n", - "trn_args = dict(drop_mult=0.9, clip=0.12, alpha=2, beta=1)\n", - "\n", - "learn = language_model_learner(data_lm, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", - "\n", - "#load pretrained models\n", - "learn.load_pretrained(**_THWIKI_LSTM)" - ], - "execution_count": 7, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "LanguageLearner(data=TextLMDataBunch;\n", - "\n", - "Train: LabelList (800 items)\n", - "x: LMTextList\n", - "xxbos every once in a long while a movie will come along that will be so xxunk that i feel xxunk to xxunk people . if i labor all my days and i can save but one soul from xxunk this movie , how great will be my joy . \n", - " \n", - " where to begin my xxunk of pain . for xxunk , there was a musical xxunk every five minutes . there was no character development . every character was a stereotype . we had xxunk guy , fat guy who xxunk xxunk , xxunk foreign guy , etc . the script xxunk as if it were being written as the movie was being shot . the production value was so xxunk low that it xxunk like i was xxunk a junior high video presentation . have the directors , producers , etc . ever even seen a movie before ? xxunk is getting worse and worse with every new entry . the concept for this movie xxunk so funny . how could you go wrong with gary coleman and a xxunk of xxunk xxunk actors . but trust me when i say this , things went wrong , xxup very xxup wrong .,xxbos name just says it all . i xxunk this movie with my dad when it came out and having xxunk in korea he had great xxunk for the man . the xxunk thing about this film is that it only xxunk on a short period of the man ' s life - xxunk enough the man ' s entire life would have made such an epic xxunk that it is xxunk to imagine the cost for production . \n", - " \n", - " some xxunk xxunk to the xxunk xxunk about the man , which are cheap xxunk . the theme of the movie \" duty , honor , country \" are not just xxunk words xxunk from the lips of a xxunk officer - it is the deep declaration of one man ' s total xxunk to his country . \n", - " \n", - " xxunk peck being the liberal that he was xxunk a better understanding of the man . he does a great job xxunk the fearless general xxunk with the humane side of the man .,xxbos this movie xxunk at being one of the most unique movies you ' ve seen . however this comes from the fact that you can ' t make heads or tails of this mess . it almost xxunk as a series of challenges set up to xxunk xxunk or not you are xxunk to walk out of the movie and give up the money you just paid . if you don ' t want to feel xxunk you ' ll sit through this xxunk film and xxunk a real sense of xxunk for the actors xxunk , they ' ve all seen better days , but then you xxunk they xxunk got paid xxunk a bit of money to do this and you ' ll lose xxunk for them just like you ' ve xxunk done for the film . i can ' t go on enough about this xxunk movie , its almost something that ed wood would have made and in that case it xxunk would have been his xxunk . \n", - " \n", - " to start you are forced to sit through an opening dialogue the xxunk of which you ' ve never seen / heard , this thing has got to be five minutes long . on top of that it is xxunk , as to xxunk that you the viewer cannot read . then we meet mr . xxunk and the xxunk of xxunk lines gets xxunk , it is as if he is operating xxunk to get lines on to the movie xxunk tag line . soon we meet stephen xxunk , who i xxunk xxunk ) and he does his best not to xxunk in this but xxunk he does . then comes the ultimate xxunk , tara reid playing an intelligent role , oh help us ! tara reid is not a very talented actress and xxunk she xxunk gets xxunk in movies , in my xxunk though she should stick to movies of the american pie type . \n", - " \n", - " all in all you just may want to see this for yourself when it comes out on video , i know that i got a kick out of it , i mean xxunk all be xxunk here , xxunk its xxunk to xxunk in the xxunk of others .,xxbos from the start , you know how this movie will end . it ' s so full of clich é s your typical xxup xxunk member will not even like this movie . i give it 2 out of 10, only because of the acting of william benton . i can ' t believe people xxunk 6 + for this movie . it ' s so biased towards a ' certain point of view ' ( once a thief xxunk people xxunk ' t born bad . neither are they born good . they are born with a clean slate . it ' s society , parents and education what makes them who they are . and if they take the wrong turn , somewhere down the line , it xxunk isn ' t going to be the american xxunk system that gets them back on track ! xxunk , xxunk this movie like the xxunk . i bet you have better things to do with your time than waste it on this piece of xxunk . \n", - " \n", - " ,xxbos i was xxunk enough to meet george pal ( and still have my xxup ds : xxup xxunk xxunk xxunk by him ) at a convention xxunk after the release , and xxunk him why he xxunk to do the film \" camp \". before he could answer , two studio xxunk xxunk and xxunk me on how the studio \" knew best \" and how \" no one will take such a film xxunk \". i had been reading the xxunk xxunk for a couple of years thanks to a friend ( xxunk xxunk of the 1970 s will recall xxunk and his band ? i was in a couple of years of that with him ), and had higher hopes than what we got . \n", - " \n", - " the xxunk xxunk that no high adventure would ever be done xxunk , and so doing ' camp ' was the only way . several other xxunk xxunk in on my side , with pal listening as best he could . at the end of the little event , pal came up to us and xxunk , xxunk he could have done more and better . \n", - " \n", - " xxup star xxup wars put the lie to the xxunk , and a year after pal ' s death , spielberg and lucas xxunk that doc savage could have xxunk been the next major movie franchise xxunk if it xxunk ' t been for the xxunk . \n", - " \n", - " tear out the memory or history of doc , and the film would have been worth a 6 / 10 rating as nothing more than a xxunk xxunk seller . \n", - " \n", - " but xxunk the legacy like that was no less an xxunk than killing a baby in the xxunk . \n", - " \n", - " doc savage can still come to the screen , and survive the xxunk xxunk by the xxunk to indiana jones , but it would have to be done in all xxunk and xxunk to xxunk the glory that we should expect from the first american xxunk . \n", - " \n", - " xxup xxunk : yes , there was a second script for xxup xxunk xxup of xxup evil , and it ' s a lot more serious . yes , there was xxunk xxunk shot , but mostly xxunk xxunk and very little with actors . and , yes , there _ is _ a xxunk of ron xxunk xxunk over a brick wall and xxunk at something over his shoulder with a xxunk built bronze xxunk . xxunk ' s xxunk a xxunk over a button down white shirt with a bronze tie , and the words \" xxup doc xxup savage : xxup xxunk xxup of xxup evil xxunk coming next summer !\" xxup xxunk : if anyone knows who the studio xxunk were that xxunk george pal in 1975 to san diego for the convention , xxunk the xxunk up the side of the head and call them the xxunk that they are . at the time , they were doing xxunk and fu xxunk in stripes and xxunk canvas xxunk , and carrying paramount xxunk .\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: /root/.fastai/data/imdb_sample;\n", - "\n", - "Valid: LabelList (200 items)\n", - "x: LMTextList\n", - "xxbos does any one know what the 2 sports cars were ? i think robert stack ' s might have been a xxunk . rock hudson ' s character told his father he was taking a job in iraq , isn ' t that xxunk ? i have had xxunk malone in my xxunk bank most of my life , maybe this was the film that xxunk me . xxunk xxunk sure did have some xxunk in this film and xxunk xxunk malone but xxunk ' s part made a more xxunk impact so she got the oscar for best supporting role . was xxunk ' s part xxunk a leading role ? old man xxunk character was was xxunk a pretty common picture of xxunk of his era in that he was a regular guy who made it big in an emerging industry but in building a whole town he had xxunk his children to have his wife bring them up . in time , being xxunk he xxunk that they were all he really had and they were xxunk rotten , looking for attention , so rather than try to xxunk to his children he xxunk his head off . an ancient morality tale . but xxunk , what were those sports cars ?,xxbos god bless 80 ' s xxunk films . this is a fun , fun movie . this is what xxunk films are all about . now i ' m not xxunk horror movies , just xxunk films . it goes like this : a high school nerd is xxunk on by all these stupid xxunk and xxunk , and then one of their xxunk goes xxunk wrong . xxunk and back for revenge , xxunk a joker / xxunk mask ( pretty xxunk looking , might i add ), marty begins to kill off those xxunk one by one many years later , after he xxunk to make them believe that their old xxunk high school is having a reunion . that is xxunk the plot ? what ' s wrong with that ? that ' s the beauty of 80 ' s xxunk films , most of them i would say . a lot of things could be so xxunk , but they keep drawing you more in an ' in as they go by . xxunk this film . \n", - " \n", - " it features some xxunk xxunk , and some are xxunk creative as well . ( poisoning of a xxunk can , acid bath , i can ' t remember a xxunk ever being used before in any other xxunk film either ) it really is a fun , fun movie . that ' s all it is . nevermind the fact that the characters are complete xxunk , never mind their xxunk , and never mind the xxunk , random things that xxunk in this film . such as lights being able to be controlled by the killer ( when he ' s not even switching any xxunk , you ' ll see ) and xxunk being able to xxunk up blood , xxunk being able to have acid come out of them , just use that as part of your entertainment ! because xxunk what really makes it xxunk . \n", - " \n", - " movies like this represent 80 ' s xxunk . never again could movies like this get made , know why ? it isn ' t the 80 ' s xxunk . that is why you should just xxunk them for what they are , good fun ! i highly xxunk this film if you ' re a hardcore fan of xxunk such as friday the 13 th . \n", - " \n", - " one last note this movie also had a kick ass xxunk as well , marty xxunk . a xxunk , nerd , who kills all his old xxunk in a xxunk xxunk mask . a good xxunk makes a good xxunk . simon xxunk , who played marty xxunk xxunk suicide xxunk after xxunk high was released . that alone xxunk something xxunk to the film , and sticks with it and it even makes you feel more sorry for the marty character , i guess . all in all , great 80 ' s xxunk fun ! it ' s a shame it will never be the same again xxunk,xxbos the basic formula for the original series was ; take someone , get the audience to like them , then put them into xxunk danger . this formula xxunk for the 32 xxunk made between 1964 - 68. \n", - " \n", - " now , we jump forward 40 years to xxunk we are xxunk to alan tracy , a xxunk xxunk college school kid , with his friend , fermat , a young xxunk . they are xxunk off by lady xxunk in her pink ford xxunk to the island paradise where the tracy family live , for the school xxunk . almost xxunk , they are left in the care of xxunk and his daughter , xxunk xxunk the xxunk go to rescue john from xxunk 5 which has been xxunk by a xxunk xxunk . this is all part of the hood ' s scheme to take over tracy island so that he can steal the xxunk machines xxunk \n", - " \n", - " xxunk to rob a bank ! \n", - " \n", - " yes . the plot xxup is as xxunk as that ! \n", - " \n", - " the dialogue is xxunk , the acting more wooden than that of the ( xxunk ) puppets , the effects , anything but special and hans xxunk ' s score xxunk what little there was of barry gray ' s glorious theme xxunk through xxunk ' s xxunk xxunk . the rest of the score was xxunk xxunk . in fact , part of the score was broadcast the following week on the radio and didn ' t xxunk it ! i didn ' t even xxunk to stay to witness xxunk ' s xxunk xxunk with the end titles \n", - " \n", - " to be fair , ron cook xxunk xxunk well as parker , he and sophia myles as xxunk xxunk xxunk . with the right material , they could have been show xxunk . the xxup cgi work was what i would have called leading edge - 5 years ago . \n", - " \n", - " the dynamics of the main craft were just wrong ; the original series models at least xxunk as if they had mass \n", - " \n", - " another xxunk point is that the whole production xxunk to be one long set of product xxunk , from every vehicle being built by ford to the entire content of the tracy xxunk being produced by ben & jerry ' s . \n", - " \n", - " my son ( 9 ) xxunk the film but this cross between spy kids and ' xxunk ', xxunk xxunk at his age group , added nothing to the xxunk legend . when star trek hit the big screen in 1979 with ' the motion picture ', a whole new xxunk of life was xxunk into the franchise which then continued for another 20 years or so . with this film , xxunk has xxunk a golden opportunity to do the same with the xxunk franchise . \n", - " \n", - " i xxunk that this film , like ' the avengers ' and ' the saint ' before it , will sink into xxunk within 6 months , leaving the original series to its ' classic ' status .,xxbos the views of earth that are xxunk in this film to have been xxunk by xxup nasa have xxunk been xxunk with the historical weather data for the time of apollo 11, and show a good match between the cloud patterns in the video sequence and the xxunk xxunk records on the day . \n", - " \n", - " this would xxunk to xxunk the entire argument put forward in the film that the \" whole earth \" picture is xxunk a small part of the planet framed by the spacecraft window . \n", - " \n", - " i am waiting for bart xxunk to now xxunk that the historical weather data has been xxunk by xxup nasa , though that would no doubt xxunk them in also xxunk every xxunk newspaper copy with a weather map , and the ones in private hands would still be a problem . \n", - " \n", - " ah , a response : \" xxunk to xxunk this movie by xxunk to xxup nasa weather data i ' d say is a xxunk , but weak and xxunk argument . what about the rest of the xxunk and xxunk in the movie ? a certain wise man once said something about xxunk xxunk and xxunk xxunk . do you in any way feel that maybe this could xxunk to what you are xxunk to do here ? : - ) this movie is just packed with xxunk evidence against the xxunk once made by u . s . government that the xxunk were a success , and that man now are true masters of the universe . things are xxunk never xxunk what they xxunk .. just watch the movie , and i dear say you ' ll see things a bit different than before .\" \n", - " \n", - " first off , weather data doesn ' t come from xxup nasa , it comes for met xxunk around the world . second , the weather data xxunk a major xxunk in the film . third , far from being \" packed with xxunk evidence \", the remaining xxunk in the film have been xxunk xxunk . xxunk thought he had a xxunk secret piece of film , so he edited it and added his own interpretation . xxunk for him , his source film is public domain , and the xxunk xxunk edited out xxunk his xxunk .,xxbos xxup swing ! is an important film because it ' s one of the remaining xxunk and xxunk films from the 1930 s . many of these films have simply xxunk so xxunk that they are xxunk , but this one is in xxunk good shape . it ' s also a nice chance to see many of the talented black xxunk of the period just after the xxunk of the old cotton xxunk time all but xxunk today . \n", - " \n", - " xxunk , while the film is xxunk important and has some lovely performances , it ' s also a mess . the main plot is very similar to the hollywood xxunk of the xxunk a prima donna who is going to xxunk the show and the surprise unknown who xxunk from no where to save the day . however , the writing is just xxunk and a bit xxunk at xxunk projects images of black america that some might find a bit xxunk . this is because before the plot really gets going , you are xxunk to a xxunk xxunk who lives off his hard working wife ( a popular stereotype of the time ) and when he is xxunk with a xxunk ( who , by the way , xxunk xxunk this role ), they have a fight which xxunk like a scene from xxup wwe smackdown ! and , the one lady wants to cut the other lady with a straight xxunk xxunk scene xxunk ! later in the film , when the prima donna is xxunk xxunk , her husband xxunk her in the face and everyone xxunk him ! it xxunk like the film , at times , wants to appeal to the xxunk common xxunk in the audience xxup plus they can ' t even do this xxunk some of the worst acting i ' ve seen in a very long time . \n", - " \n", - " still , if you can look past a xxunk production in just about every way ( with xxunk characters , bad acting and direction and poor writing ), this one might be worth a xxunk so you can see excellent singing and tap xxunk well as to catch a xxunk of xxunk black culture . just don ' t say i didn ' t xxunk you about the xxunk ' s really , really bad !\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: /root/.fastai/data/imdb_sample;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): AWD_LSTM(\n", - " (encoder): Embedding(60005, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(60005, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " (1): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('/root/.fastai/data/imdb_sample'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[RNNTrainer\n", - "learn: LanguageLearner(data=TextLMDataBunch;\n", - "\n", - "Train: LabelList (800 items)\n", - "x: LMTextList\n", - "xxbos every once in a long while a movie will come along that will be so xxunk that i feel xxunk to xxunk people . if i labor all my days and i can save but one soul from xxunk this movie , how great will be my joy . \n", - " \n", - " where to begin my xxunk of pain . for xxunk , there was a musical xxunk every five minutes . there was no character development . every character was a stereotype . we had xxunk guy , fat guy who xxunk xxunk , xxunk foreign guy , etc . the script xxunk as if it were being written as the movie was being shot . the production value was so xxunk low that it xxunk like i was xxunk a junior high video presentation . have the directors , producers , etc . ever even seen a movie before ? xxunk is getting worse and worse with every new entry . the concept for this movie xxunk so funny . how could you go wrong with gary coleman and a xxunk of xxunk xxunk actors . but trust me when i say this , things went wrong , xxup very xxup wrong .,xxbos name just says it all . i xxunk this movie with my dad when it came out and having xxunk in korea he had great xxunk for the man . the xxunk thing about this film is that it only xxunk on a short period of the man ' s life - xxunk enough the man ' s entire life would have made such an epic xxunk that it is xxunk to imagine the cost for production . \n", - " \n", - " some xxunk xxunk to the xxunk xxunk about the man , which are cheap xxunk . the theme of the movie \" duty , honor , country \" are not just xxunk words xxunk from the lips of a xxunk officer - it is the deep declaration of one man ' s total xxunk to his country . \n", - " \n", - " xxunk peck being the liberal that he was xxunk a better understanding of the man . he does a great job xxunk the fearless general xxunk with the humane side of the man .,xxbos this movie xxunk at being one of the most unique movies you ' ve seen . however this comes from the fact that you can ' t make heads or tails of this mess . it almost xxunk as a series of challenges set up to xxunk xxunk or not you are xxunk to walk out of the movie and give up the money you just paid . if you don ' t want to feel xxunk you ' ll sit through this xxunk film and xxunk a real sense of xxunk for the actors xxunk , they ' ve all seen better days , but then you xxunk they xxunk got paid xxunk a bit of money to do this and you ' ll lose xxunk for them just like you ' ve xxunk done for the film . i can ' t go on enough about this xxunk movie , its almost something that ed wood would have made and in that case it xxunk would have been his xxunk . \n", - " \n", - " to start you are forced to sit through an opening dialogue the xxunk of which you ' ve never seen / heard , this thing has got to be five minutes long . on top of that it is xxunk , as to xxunk that you the viewer cannot read . then we meet mr . xxunk and the xxunk of xxunk lines gets xxunk , it is as if he is operating xxunk to get lines on to the movie xxunk tag line . soon we meet stephen xxunk , who i xxunk xxunk ) and he does his best not to xxunk in this but xxunk he does . then comes the ultimate xxunk , tara reid playing an intelligent role , oh help us ! tara reid is not a very talented actress and xxunk she xxunk gets xxunk in movies , in my xxunk though she should stick to movies of the american pie type . \n", - " \n", - " all in all you just may want to see this for yourself when it comes out on video , i know that i got a kick out of it , i mean xxunk all be xxunk here , xxunk its xxunk to xxunk in the xxunk of others .,xxbos from the start , you know how this movie will end . it ' s so full of clich é s your typical xxup xxunk member will not even like this movie . i give it 2 out of 10, only because of the acting of william benton . i can ' t believe people xxunk 6 + for this movie . it ' s so biased towards a ' certain point of view ' ( once a thief xxunk people xxunk ' t born bad . neither are they born good . they are born with a clean slate . it ' s society , parents and education what makes them who they are . and if they take the wrong turn , somewhere down the line , it xxunk isn ' t going to be the american xxunk system that gets them back on track ! xxunk , xxunk this movie like the xxunk . i bet you have better things to do with your time than waste it on this piece of xxunk . \n", - " \n", - " ,xxbos i was xxunk enough to meet george pal ( and still have my xxup ds : xxup xxunk xxunk xxunk by him ) at a convention xxunk after the release , and xxunk him why he xxunk to do the film \" camp \". before he could answer , two studio xxunk xxunk and xxunk me on how the studio \" knew best \" and how \" no one will take such a film xxunk \". i had been reading the xxunk xxunk for a couple of years thanks to a friend ( xxunk xxunk of the 1970 s will recall xxunk and his band ? i was in a couple of years of that with him ), and had higher hopes than what we got . \n", - " \n", - " the xxunk xxunk that no high adventure would ever be done xxunk , and so doing ' camp ' was the only way . several other xxunk xxunk in on my side , with pal listening as best he could . at the end of the little event , pal came up to us and xxunk , xxunk he could have done more and better . \n", - " \n", - " xxup star xxup wars put the lie to the xxunk , and a year after pal ' s death , spielberg and lucas xxunk that doc savage could have xxunk been the next major movie franchise xxunk if it xxunk ' t been for the xxunk . \n", - " \n", - " tear out the memory or history of doc , and the film would have been worth a 6 / 10 rating as nothing more than a xxunk xxunk seller . \n", - " \n", - " but xxunk the legacy like that was no less an xxunk than killing a baby in the xxunk . \n", - " \n", - " doc savage can still come to the screen , and survive the xxunk xxunk by the xxunk to indiana jones , but it would have to be done in all xxunk and xxunk to xxunk the glory that we should expect from the first american xxunk . \n", - " \n", - " xxup xxunk : yes , there was a second script for xxup xxunk xxup of xxup evil , and it ' s a lot more serious . yes , there was xxunk xxunk shot , but mostly xxunk xxunk and very little with actors . and , yes , there _ is _ a xxunk of ron xxunk xxunk over a brick wall and xxunk at something over his shoulder with a xxunk built bronze xxunk . xxunk ' s xxunk a xxunk over a button down white shirt with a bronze tie , and the words \" xxup doc xxup savage : xxup xxunk xxup of xxup evil xxunk coming next summer !\" xxup xxunk : if anyone knows who the studio xxunk were that xxunk george pal in 1975 to san diego for the convention , xxunk the xxunk up the side of the head and call them the xxunk that they are . at the time , they were doing xxunk and fu xxunk in stripes and xxunk canvas xxunk , and carrying paramount xxunk .\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: /root/.fastai/data/imdb_sample;\n", - "\n", - "Valid: LabelList (200 items)\n", - "x: LMTextList\n", - "xxbos does any one know what the 2 sports cars were ? i think robert stack ' s might have been a xxunk . rock hudson ' s character told his father he was taking a job in iraq , isn ' t that xxunk ? i have had xxunk malone in my xxunk bank most of my life , maybe this was the film that xxunk me . xxunk xxunk sure did have some xxunk in this film and xxunk xxunk malone but xxunk ' s part made a more xxunk impact so she got the oscar for best supporting role . was xxunk ' s part xxunk a leading role ? old man xxunk character was was xxunk a pretty common picture of xxunk of his era in that he was a regular guy who made it big in an emerging industry but in building a whole town he had xxunk his children to have his wife bring them up . in time , being xxunk he xxunk that they were all he really had and they were xxunk rotten , looking for attention , so rather than try to xxunk to his children he xxunk his head off . an ancient morality tale . but xxunk , what were those sports cars ?,xxbos god bless 80 ' s xxunk films . this is a fun , fun movie . this is what xxunk films are all about . now i ' m not xxunk horror movies , just xxunk films . it goes like this : a high school nerd is xxunk on by all these stupid xxunk and xxunk , and then one of their xxunk goes xxunk wrong . xxunk and back for revenge , xxunk a joker / xxunk mask ( pretty xxunk looking , might i add ), marty begins to kill off those xxunk one by one many years later , after he xxunk to make them believe that their old xxunk high school is having a reunion . that is xxunk the plot ? what ' s wrong with that ? that ' s the beauty of 80 ' s xxunk films , most of them i would say . a lot of things could be so xxunk , but they keep drawing you more in an ' in as they go by . xxunk this film . \n", - " \n", - " it features some xxunk xxunk , and some are xxunk creative as well . ( poisoning of a xxunk can , acid bath , i can ' t remember a xxunk ever being used before in any other xxunk film either ) it really is a fun , fun movie . that ' s all it is . nevermind the fact that the characters are complete xxunk , never mind their xxunk , and never mind the xxunk , random things that xxunk in this film . such as lights being able to be controlled by the killer ( when he ' s not even switching any xxunk , you ' ll see ) and xxunk being able to xxunk up blood , xxunk being able to have acid come out of them , just use that as part of your entertainment ! because xxunk what really makes it xxunk . \n", - " \n", - " movies like this represent 80 ' s xxunk . never again could movies like this get made , know why ? it isn ' t the 80 ' s xxunk . that is why you should just xxunk them for what they are , good fun ! i highly xxunk this film if you ' re a hardcore fan of xxunk such as friday the 13 th . \n", - " \n", - " one last note this movie also had a kick ass xxunk as well , marty xxunk . a xxunk , nerd , who kills all his old xxunk in a xxunk xxunk mask . a good xxunk makes a good xxunk . simon xxunk , who played marty xxunk xxunk suicide xxunk after xxunk high was released . that alone xxunk something xxunk to the film , and sticks with it and it even makes you feel more sorry for the marty character , i guess . all in all , great 80 ' s xxunk fun ! it ' s a shame it will never be the same again xxunk,xxbos the basic formula for the original series was ; take someone , get the audience to like them , then put them into xxunk danger . this formula xxunk for the 32 xxunk made between 1964 - 68. \n", - " \n", - " now , we jump forward 40 years to xxunk we are xxunk to alan tracy , a xxunk xxunk college school kid , with his friend , fermat , a young xxunk . they are xxunk off by lady xxunk in her pink ford xxunk to the island paradise where the tracy family live , for the school xxunk . almost xxunk , they are left in the care of xxunk and his daughter , xxunk xxunk the xxunk go to rescue john from xxunk 5 which has been xxunk by a xxunk xxunk . this is all part of the hood ' s scheme to take over tracy island so that he can steal the xxunk machines xxunk \n", - " \n", - " xxunk to rob a bank ! \n", - " \n", - " yes . the plot xxup is as xxunk as that ! \n", - " \n", - " the dialogue is xxunk , the acting more wooden than that of the ( xxunk ) puppets , the effects , anything but special and hans xxunk ' s score xxunk what little there was of barry gray ' s glorious theme xxunk through xxunk ' s xxunk xxunk . the rest of the score was xxunk xxunk . in fact , part of the score was broadcast the following week on the radio and didn ' t xxunk it ! i didn ' t even xxunk to stay to witness xxunk ' s xxunk xxunk with the end titles \n", - " \n", - " to be fair , ron cook xxunk xxunk well as parker , he and sophia myles as xxunk xxunk xxunk . with the right material , they could have been show xxunk . the xxup cgi work was what i would have called leading edge - 5 years ago . \n", - " \n", - " the dynamics of the main craft were just wrong ; the original series models at least xxunk as if they had mass \n", - " \n", - " another xxunk point is that the whole production xxunk to be one long set of product xxunk , from every vehicle being built by ford to the entire content of the tracy xxunk being produced by ben & jerry ' s . \n", - " \n", - " my son ( 9 ) xxunk the film but this cross between spy kids and ' xxunk ', xxunk xxunk at his age group , added nothing to the xxunk legend . when star trek hit the big screen in 1979 with ' the motion picture ', a whole new xxunk of life was xxunk into the franchise which then continued for another 20 years or so . with this film , xxunk has xxunk a golden opportunity to do the same with the xxunk franchise . \n", - " \n", - " i xxunk that this film , like ' the avengers ' and ' the saint ' before it , will sink into xxunk within 6 months , leaving the original series to its ' classic ' status .,xxbos the views of earth that are xxunk in this film to have been xxunk by xxup nasa have xxunk been xxunk with the historical weather data for the time of apollo 11, and show a good match between the cloud patterns in the video sequence and the xxunk xxunk records on the day . \n", - " \n", - " this would xxunk to xxunk the entire argument put forward in the film that the \" whole earth \" picture is xxunk a small part of the planet framed by the spacecraft window . \n", - " \n", - " i am waiting for bart xxunk to now xxunk that the historical weather data has been xxunk by xxup nasa , though that would no doubt xxunk them in also xxunk every xxunk newspaper copy with a weather map , and the ones in private hands would still be a problem . \n", - " \n", - " ah , a response : \" xxunk to xxunk this movie by xxunk to xxup nasa weather data i ' d say is a xxunk , but weak and xxunk argument . what about the rest of the xxunk and xxunk in the movie ? a certain wise man once said something about xxunk xxunk and xxunk xxunk . do you in any way feel that maybe this could xxunk to what you are xxunk to do here ? : - ) this movie is just packed with xxunk evidence against the xxunk once made by u . s . government that the xxunk were a success , and that man now are true masters of the universe . things are xxunk never xxunk what they xxunk .. just watch the movie , and i dear say you ' ll see things a bit different than before .\" \n", - " \n", - " first off , weather data doesn ' t come from xxup nasa , it comes for met xxunk around the world . second , the weather data xxunk a major xxunk in the film . third , far from being \" packed with xxunk evidence \", the remaining xxunk in the film have been xxunk xxunk . xxunk thought he had a xxunk secret piece of film , so he edited it and added his own interpretation . xxunk for him , his source film is public domain , and the xxunk xxunk edited out xxunk his xxunk .,xxbos xxup swing ! is an important film because it ' s one of the remaining xxunk and xxunk films from the 1930 s . many of these films have simply xxunk so xxunk that they are xxunk , but this one is in xxunk good shape . it ' s also a nice chance to see many of the talented black xxunk of the period just after the xxunk of the old cotton xxunk time all but xxunk today . \n", - " \n", - " xxunk , while the film is xxunk important and has some lovely performances , it ' s also a mess . the main plot is very similar to the hollywood xxunk of the xxunk a prima donna who is going to xxunk the show and the surprise unknown who xxunk from no where to save the day . however , the writing is just xxunk and a bit xxunk at xxunk projects images of black america that some might find a bit xxunk . this is because before the plot really gets going , you are xxunk to a xxunk xxunk who lives off his hard working wife ( a popular stereotype of the time ) and when he is xxunk with a xxunk ( who , by the way , xxunk xxunk this role ), they have a fight which xxunk like a scene from xxup wwe smackdown ! and , the one lady wants to cut the other lady with a straight xxunk xxunk scene xxunk ! later in the film , when the prima donna is xxunk xxunk , her husband xxunk her in the face and everyone xxunk him ! it xxunk like the film , at times , wants to appeal to the xxunk common xxunk in the audience xxup plus they can ' t even do this xxunk some of the worst acting i ' ve seen in a very long time . \n", - " \n", - " still , if you can look past a xxunk production in just about every way ( with xxunk characters , bad acting and direction and poor writing ), this one might be worth a xxunk so you can see excellent singing and tap xxunk well as to catch a xxunk of xxunk black culture . just don ' t say i didn ' t xxunk you about the xxunk ' s really , really bad !\n", - "y: LMLabelList\n", - ",,,,\n", - "Path: /root/.fastai/data/imdb_sample;\n", - "\n", - "Test: None, model=SequentialRNN(\n", - " (0): AWD_LSTM(\n", - " (encoder): Embedding(60005, 400, padding_idx=1)\n", - " (encoder_dp): EmbeddingDropout(\n", - " (emb): Embedding(60005, 400, padding_idx=1)\n", - " )\n", - " (rnns): ModuleList(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (2): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (3): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " )\n", - " (input_dp): RNNDropout()\n", - " (hidden_dps): ModuleList(\n", - " (0): RNNDropout()\n", - " (1): RNNDropout()\n", - " (2): RNNDropout()\n", - " (3): RNNDropout()\n", - " )\n", - " )\n", - " (1): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('/root/.fastai/data/imdb_sample'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[...], layer_groups=[Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): Embedding(60005, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(60005, 400, padding_idx=1)\n", - " )\n", - " (2): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)\n", - "alpha: 2\n", - "beta: 1], layer_groups=[Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(400, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 1550, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): WeightDropout(\n", - " (module): LSTM(1550, 400, batch_first=True)\n", - " )\n", - " (1): RNNDropout()\n", - "), Sequential(\n", - " (0): Embedding(60005, 400, padding_idx=1)\n", - " (1): EmbeddingDropout(\n", - " (emb): Embedding(60005, 400, padding_idx=1)\n", - " )\n", - " (2): LinearDecoder(\n", - " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", - " (output_dp): RNNDropout()\n", - " )\n", - ")], add_time=True, silent=False, cb_fns_registered=False)" - ] - }, - "metadata": { - "tags": [] - }, - "execution_count": 7 - } + "data": { + "text/plain": [ + "60005" ] + }, + "execution_count": 6, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "#check vocab size\n", + "len(data_lm.vocab.itos)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 }, + "colab_type": "code", + "id": "B9DJVRZ-KROb", + "outputId": "54031979-d708-4550-d0b7-8cd42b07cf96" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "SwJK_G80KROl", - "colab_type": "code", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 122 - }, - "outputId": "2d1fdff0-66e7-4f96-93fc-7e112c4306c8" - }, - "source": [ - "print(learn.predict('กาลครั้งหนึ่งนานมาแล้ว ', 200, temperature=0.8, min_p=0.005, sep = ''))" - ], - "execution_count": 24, - "outputs": [ - { - "output_type": "stream", - "text": [ - "กาลครั้งหนึ่งนานมาแล้ว คุณวันจันทร์ได้รับการอุปการะจากแม่เธอ \n", - " \n", - " วันต่อมา เธอได้พบกับ \"อาเธอร์ โอลด์เดน\" เด็กหนุ่มที่มีบุคลิกคล้ายกับ \"เอมิลี\" ซึ่งเป็นน้องสาวของนาง เขาจึงได้รับการเลี้ยงดูจาก \"อาเธอร์ ดีอา\" และเป็นผู้ที่คอยดูแลเธออยู่เสมอ เธอได้แนะนำให้เธอเป็นผู้หญิง \n", - " \n", - " โดยมี \"เอลซ่า\" ซึ่งเป็นทายาทของ \"อาเธอร์ ยูจีน\" ผู้เป็นสามีของเขา และเคยช่วยยูนิตที่ถูกส่งตัวไปประจำอยู่ที่ดินแดนแห่งนี้ เธอได้พบกับ \"ยูลิสซิส เกรย์ เอลิซาเบธ เอลลิส \" (เอมิลี่ ไอเซนฮา) ซึ่งเป็นชาว \"เผ่าเอลฟ์ \" และเธอก็ไม่ค่อยมีบุตร แต่เธอก็ได้รับความช่วยเหลือจาก \"\n" - ], - "name": "stdout" - } + "data": { + "text/plain": [ + "LanguageLearner(data=TextLMDataBunch;\n", + "\n", + "Train: LabelList (800 items)\n", + "x: LMTextList\n", + "xxbos every once in a long while a movie will come along that will be so xxunk that i feel xxunk to xxunk people . if i labor all my days and i can save but one soul from xxunk this movie , how great will be my joy . \n", + " \n", + " where to begin my xxunk of pain . for xxunk , there was a musical xxunk every five minutes . there was no character development . every character was a stereotype . we had xxunk guy , fat guy who xxunk xxunk , xxunk foreign guy , etc . the script xxunk as if it were being written as the movie was being shot . the production value was so xxunk low that it xxunk like i was xxunk a junior high video presentation . have the directors , producers , etc . ever even seen a movie before ? xxunk is getting worse and worse with every new entry . the concept for this movie xxunk so funny . how could you go wrong with gary coleman and a xxunk of xxunk xxunk actors . but trust me when i say this , things went wrong , xxup very xxup wrong .,xxbos name just says it all . i xxunk this movie with my dad when it came out and having xxunk in korea he had great xxunk for the man . the xxunk thing about this film is that it only xxunk on a short period of the man ' s life - xxunk enough the man ' s entire life would have made such an epic xxunk that it is xxunk to imagine the cost for production . \n", + " \n", + " some xxunk xxunk to the xxunk xxunk about the man , which are cheap xxunk . the theme of the movie \" duty , honor , country \" are not just xxunk words xxunk from the lips of a xxunk officer - it is the deep declaration of one man ' s total xxunk to his country . \n", + " \n", + " xxunk peck being the liberal that he was xxunk a better understanding of the man . he does a great job xxunk the fearless general xxunk with the humane side of the man .,xxbos this movie xxunk at being one of the most unique movies you ' ve seen . however this comes from the fact that you can ' t make heads or tails of this mess . it almost xxunk as a series of challenges set up to xxunk xxunk or not you are xxunk to walk out of the movie and give up the money you just paid . if you don ' t want to feel xxunk you ' ll sit through this xxunk film and xxunk a real sense of xxunk for the actors xxunk , they ' ve all seen better days , but then you xxunk they xxunk got paid xxunk a bit of money to do this and you ' ll lose xxunk for them just like you ' ve xxunk done for the film . i can ' t go on enough about this xxunk movie , its almost something that ed wood would have made and in that case it xxunk would have been his xxunk . \n", + " \n", + " to start you are forced to sit through an opening dialogue the xxunk of which you ' ve never seen / heard , this thing has got to be five minutes long . on top of that it is xxunk , as to xxunk that you the viewer cannot read . then we meet mr . xxunk and the xxunk of xxunk lines gets xxunk , it is as if he is operating xxunk to get lines on to the movie xxunk tag line . soon we meet stephen xxunk , who i xxunk xxunk ) and he does his best not to xxunk in this but xxunk he does . then comes the ultimate xxunk , tara reid playing an intelligent role , oh help us ! tara reid is not a very talented actress and xxunk she xxunk gets xxunk in movies , in my xxunk though she should stick to movies of the american pie type . \n", + " \n", + " all in all you just may want to see this for yourself when it comes out on video , i know that i got a kick out of it , i mean xxunk all be xxunk here , xxunk its xxunk to xxunk in the xxunk of others .,xxbos from the start , you know how this movie will end . it ' s so full of clich é s your typical xxup xxunk member will not even like this movie . i give it 2 out of 10, only because of the acting of william benton . i can ' t believe people xxunk 6 + for this movie . it ' s so biased towards a ' certain point of view ' ( once a thief xxunk people xxunk ' t born bad . neither are they born good . they are born with a clean slate . it ' s society , parents and education what makes them who they are . and if they take the wrong turn , somewhere down the line , it xxunk isn ' t going to be the american xxunk system that gets them back on track ! xxunk , xxunk this movie like the xxunk . i bet you have better things to do with your time than waste it on this piece of xxunk . \n", + " \n", + " ,xxbos i was xxunk enough to meet george pal ( and still have my xxup ds : xxup xxunk xxunk xxunk by him ) at a convention xxunk after the release , and xxunk him why he xxunk to do the film \" camp \". before he could answer , two studio xxunk xxunk and xxunk me on how the studio \" knew best \" and how \" no one will take such a film xxunk \". i had been reading the xxunk xxunk for a couple of years thanks to a friend ( xxunk xxunk of the 1970 s will recall xxunk and his band ? i was in a couple of years of that with him ), and had higher hopes than what we got . \n", + " \n", + " the xxunk xxunk that no high adventure would ever be done xxunk , and so doing ' camp ' was the only way . several other xxunk xxunk in on my side , with pal listening as best he could . at the end of the little event , pal came up to us and xxunk , xxunk he could have done more and better . \n", + " \n", + " xxup star xxup wars put the lie to the xxunk , and a year after pal ' s death , spielberg and lucas xxunk that doc savage could have xxunk been the next major movie franchise xxunk if it xxunk ' t been for the xxunk . \n", + " \n", + " tear out the memory or history of doc , and the film would have been worth a 6 / 10 rating as nothing more than a xxunk xxunk seller . \n", + " \n", + " but xxunk the legacy like that was no less an xxunk than killing a baby in the xxunk . \n", + " \n", + " doc savage can still come to the screen , and survive the xxunk xxunk by the xxunk to indiana jones , but it would have to be done in all xxunk and xxunk to xxunk the glory that we should expect from the first american xxunk . \n", + " \n", + " xxup xxunk : yes , there was a second script for xxup xxunk xxup of xxup evil , and it ' s a lot more serious . yes , there was xxunk xxunk shot , but mostly xxunk xxunk and very little with actors . and , yes , there _ is _ a xxunk of ron xxunk xxunk over a brick wall and xxunk at something over his shoulder with a xxunk built bronze xxunk . xxunk ' s xxunk a xxunk over a button down white shirt with a bronze tie , and the words \" xxup doc xxup savage : xxup xxunk xxup of xxup evil xxunk coming next summer !\" xxup xxunk : if anyone knows who the studio xxunk were that xxunk george pal in 1975 to san diego for the convention , xxunk the xxunk up the side of the head and call them the xxunk that they are . at the time , they were doing xxunk and fu xxunk in stripes and xxunk canvas xxunk , and carrying paramount xxunk .\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: /root/.fastai/data/imdb_sample;\n", + "\n", + "Valid: LabelList (200 items)\n", + "x: LMTextList\n", + "xxbos does any one know what the 2 sports cars were ? i think robert stack ' s might have been a xxunk . rock hudson ' s character told his father he was taking a job in iraq , isn ' t that xxunk ? i have had xxunk malone in my xxunk bank most of my life , maybe this was the film that xxunk me . xxunk xxunk sure did have some xxunk in this film and xxunk xxunk malone but xxunk ' s part made a more xxunk impact so she got the oscar for best supporting role . was xxunk ' s part xxunk a leading role ? old man xxunk character was was xxunk a pretty common picture of xxunk of his era in that he was a regular guy who made it big in an emerging industry but in building a whole town he had xxunk his children to have his wife bring them up . in time , being xxunk he xxunk that they were all he really had and they were xxunk rotten , looking for attention , so rather than try to xxunk to his children he xxunk his head off . an ancient morality tale . but xxunk , what were those sports cars ?,xxbos god bless 80 ' s xxunk films . this is a fun , fun movie . this is what xxunk films are all about . now i ' m not xxunk horror movies , just xxunk films . it goes like this : a high school nerd is xxunk on by all these stupid xxunk and xxunk , and then one of their xxunk goes xxunk wrong . xxunk and back for revenge , xxunk a joker / xxunk mask ( pretty xxunk looking , might i add ), marty begins to kill off those xxunk one by one many years later , after he xxunk to make them believe that their old xxunk high school is having a reunion . that is xxunk the plot ? what ' s wrong with that ? that ' s the beauty of 80 ' s xxunk films , most of them i would say . a lot of things could be so xxunk , but they keep drawing you more in an ' in as they go by . xxunk this film . \n", + " \n", + " it features some xxunk xxunk , and some are xxunk creative as well . ( poisoning of a xxunk can , acid bath , i can ' t remember a xxunk ever being used before in any other xxunk film either ) it really is a fun , fun movie . that ' s all it is . nevermind the fact that the characters are complete xxunk , never mind their xxunk , and never mind the xxunk , random things that xxunk in this film . such as lights being able to be controlled by the killer ( when he ' s not even switching any xxunk , you ' ll see ) and xxunk being able to xxunk up blood , xxunk being able to have acid come out of them , just use that as part of your entertainment ! because xxunk what really makes it xxunk . \n", + " \n", + " movies like this represent 80 ' s xxunk . never again could movies like this get made , know why ? it isn ' t the 80 ' s xxunk . that is why you should just xxunk them for what they are , good fun ! i highly xxunk this film if you ' re a hardcore fan of xxunk such as friday the 13 th . \n", + " \n", + " one last note this movie also had a kick ass xxunk as well , marty xxunk . a xxunk , nerd , who kills all his old xxunk in a xxunk xxunk mask . a good xxunk makes a good xxunk . simon xxunk , who played marty xxunk xxunk suicide xxunk after xxunk high was released . that alone xxunk something xxunk to the film , and sticks with it and it even makes you feel more sorry for the marty character , i guess . all in all , great 80 ' s xxunk fun ! it ' s a shame it will never be the same again xxunk,xxbos the basic formula for the original series was ; take someone , get the audience to like them , then put them into xxunk danger . this formula xxunk for the 32 xxunk made between 1964 - 68. \n", + " \n", + " now , we jump forward 40 years to xxunk we are xxunk to alan tracy , a xxunk xxunk college school kid , with his friend , fermat , a young xxunk . they are xxunk off by lady xxunk in her pink ford xxunk to the island paradise where the tracy family live , for the school xxunk . almost xxunk , they are left in the care of xxunk and his daughter , xxunk xxunk the xxunk go to rescue john from xxunk 5 which has been xxunk by a xxunk xxunk . this is all part of the hood ' s scheme to take over tracy island so that he can steal the xxunk machines xxunk \n", + " \n", + " xxunk to rob a bank ! \n", + " \n", + " yes . the plot xxup is as xxunk as that ! \n", + " \n", + " the dialogue is xxunk , the acting more wooden than that of the ( xxunk ) puppets , the effects , anything but special and hans xxunk ' s score xxunk what little there was of barry gray ' s glorious theme xxunk through xxunk ' s xxunk xxunk . the rest of the score was xxunk xxunk . in fact , part of the score was broadcast the following week on the radio and didn ' t xxunk it ! i didn ' t even xxunk to stay to witness xxunk ' s xxunk xxunk with the end titles \n", + " \n", + " to be fair , ron cook xxunk xxunk well as parker , he and sophia myles as xxunk xxunk xxunk . with the right material , they could have been show xxunk . the xxup cgi work was what i would have called leading edge - 5 years ago . \n", + " \n", + " the dynamics of the main craft were just wrong ; the original series models at least xxunk as if they had mass \n", + " \n", + " another xxunk point is that the whole production xxunk to be one long set of product xxunk , from every vehicle being built by ford to the entire content of the tracy xxunk being produced by ben & jerry ' s . \n", + " \n", + " my son ( 9 ) xxunk the film but this cross between spy kids and ' xxunk ', xxunk xxunk at his age group , added nothing to the xxunk legend . when star trek hit the big screen in 1979 with ' the motion picture ', a whole new xxunk of life was xxunk into the franchise which then continued for another 20 years or so . with this film , xxunk has xxunk a golden opportunity to do the same with the xxunk franchise . \n", + " \n", + " i xxunk that this film , like ' the avengers ' and ' the saint ' before it , will sink into xxunk within 6 months , leaving the original series to its ' classic ' status .,xxbos the views of earth that are xxunk in this film to have been xxunk by xxup nasa have xxunk been xxunk with the historical weather data for the time of apollo 11, and show a good match between the cloud patterns in the video sequence and the xxunk xxunk records on the day . \n", + " \n", + " this would xxunk to xxunk the entire argument put forward in the film that the \" whole earth \" picture is xxunk a small part of the planet framed by the spacecraft window . \n", + " \n", + " i am waiting for bart xxunk to now xxunk that the historical weather data has been xxunk by xxup nasa , though that would no doubt xxunk them in also xxunk every xxunk newspaper copy with a weather map , and the ones in private hands would still be a problem . \n", + " \n", + " ah , a response : \" xxunk to xxunk this movie by xxunk to xxup nasa weather data i ' d say is a xxunk , but weak and xxunk argument . what about the rest of the xxunk and xxunk in the movie ? a certain wise man once said something about xxunk xxunk and xxunk xxunk . do you in any way feel that maybe this could xxunk to what you are xxunk to do here ? : - ) this movie is just packed with xxunk evidence against the xxunk once made by u . s . government that the xxunk were a success , and that man now are true masters of the universe . things are xxunk never xxunk what they xxunk .. just watch the movie , and i dear say you ' ll see things a bit different than before .\" \n", + " \n", + " first off , weather data doesn ' t come from xxup nasa , it comes for met xxunk around the world . second , the weather data xxunk a major xxunk in the film . third , far from being \" packed with xxunk evidence \", the remaining xxunk in the film have been xxunk xxunk . xxunk thought he had a xxunk secret piece of film , so he edited it and added his own interpretation . xxunk for him , his source film is public domain , and the xxunk xxunk edited out xxunk his xxunk .,xxbos xxup swing ! is an important film because it ' s one of the remaining xxunk and xxunk films from the 1930 s . many of these films have simply xxunk so xxunk that they are xxunk , but this one is in xxunk good shape . it ' s also a nice chance to see many of the talented black xxunk of the period just after the xxunk of the old cotton xxunk time all but xxunk today . \n", + " \n", + " xxunk , while the film is xxunk important and has some lovely performances , it ' s also a mess . the main plot is very similar to the hollywood xxunk of the xxunk a prima donna who is going to xxunk the show and the surprise unknown who xxunk from no where to save the day . however , the writing is just xxunk and a bit xxunk at xxunk projects images of black america that some might find a bit xxunk . this is because before the plot really gets going , you are xxunk to a xxunk xxunk who lives off his hard working wife ( a popular stereotype of the time ) and when he is xxunk with a xxunk ( who , by the way , xxunk xxunk this role ), they have a fight which xxunk like a scene from xxup wwe smackdown ! and , the one lady wants to cut the other lady with a straight xxunk xxunk scene xxunk ! later in the film , when the prima donna is xxunk xxunk , her husband xxunk her in the face and everyone xxunk him ! it xxunk like the film , at times , wants to appeal to the xxunk common xxunk in the audience xxup plus they can ' t even do this xxunk some of the worst acting i ' ve seen in a very long time . \n", + " \n", + " still , if you can look past a xxunk production in just about every way ( with xxunk characters , bad acting and direction and poor writing ), this one might be worth a xxunk so you can see excellent singing and tap xxunk well as to catch a xxunk of xxunk black culture . just don ' t say i didn ' t xxunk you about the xxunk ' s really , really bad !\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: /root/.fastai/data/imdb_sample;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): AWD_LSTM(\n", + " (encoder): Embedding(60005, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(60005, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " (1): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('/root/.fastai/data/imdb_sample'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[RNNTrainer\n", + "learn: LanguageLearner(data=TextLMDataBunch;\n", + "\n", + "Train: LabelList (800 items)\n", + "x: LMTextList\n", + "xxbos every once in a long while a movie will come along that will be so xxunk that i feel xxunk to xxunk people . if i labor all my days and i can save but one soul from xxunk this movie , how great will be my joy . \n", + " \n", + " where to begin my xxunk of pain . for xxunk , there was a musical xxunk every five minutes . there was no character development . every character was a stereotype . we had xxunk guy , fat guy who xxunk xxunk , xxunk foreign guy , etc . the script xxunk as if it were being written as the movie was being shot . the production value was so xxunk low that it xxunk like i was xxunk a junior high video presentation . have the directors , producers , etc . ever even seen a movie before ? xxunk is getting worse and worse with every new entry . the concept for this movie xxunk so funny . how could you go wrong with gary coleman and a xxunk of xxunk xxunk actors . but trust me when i say this , things went wrong , xxup very xxup wrong .,xxbos name just says it all . i xxunk this movie with my dad when it came out and having xxunk in korea he had great xxunk for the man . the xxunk thing about this film is that it only xxunk on a short period of the man ' s life - xxunk enough the man ' s entire life would have made such an epic xxunk that it is xxunk to imagine the cost for production . \n", + " \n", + " some xxunk xxunk to the xxunk xxunk about the man , which are cheap xxunk . the theme of the movie \" duty , honor , country \" are not just xxunk words xxunk from the lips of a xxunk officer - it is the deep declaration of one man ' s total xxunk to his country . \n", + " \n", + " xxunk peck being the liberal that he was xxunk a better understanding of the man . he does a great job xxunk the fearless general xxunk with the humane side of the man .,xxbos this movie xxunk at being one of the most unique movies you ' ve seen . however this comes from the fact that you can ' t make heads or tails of this mess . it almost xxunk as a series of challenges set up to xxunk xxunk or not you are xxunk to walk out of the movie and give up the money you just paid . if you don ' t want to feel xxunk you ' ll sit through this xxunk film and xxunk a real sense of xxunk for the actors xxunk , they ' ve all seen better days , but then you xxunk they xxunk got paid xxunk a bit of money to do this and you ' ll lose xxunk for them just like you ' ve xxunk done for the film . i can ' t go on enough about this xxunk movie , its almost something that ed wood would have made and in that case it xxunk would have been his xxunk . \n", + " \n", + " to start you are forced to sit through an opening dialogue the xxunk of which you ' ve never seen / heard , this thing has got to be five minutes long . on top of that it is xxunk , as to xxunk that you the viewer cannot read . then we meet mr . xxunk and the xxunk of xxunk lines gets xxunk , it is as if he is operating xxunk to get lines on to the movie xxunk tag line . soon we meet stephen xxunk , who i xxunk xxunk ) and he does his best not to xxunk in this but xxunk he does . then comes the ultimate xxunk , tara reid playing an intelligent role , oh help us ! tara reid is not a very talented actress and xxunk she xxunk gets xxunk in movies , in my xxunk though she should stick to movies of the american pie type . \n", + " \n", + " all in all you just may want to see this for yourself when it comes out on video , i know that i got a kick out of it , i mean xxunk all be xxunk here , xxunk its xxunk to xxunk in the xxunk of others .,xxbos from the start , you know how this movie will end . it ' s so full of clich é s your typical xxup xxunk member will not even like this movie . i give it 2 out of 10, only because of the acting of william benton . i can ' t believe people xxunk 6 + for this movie . it ' s so biased towards a ' certain point of view ' ( once a thief xxunk people xxunk ' t born bad . neither are they born good . they are born with a clean slate . it ' s society , parents and education what makes them who they are . and if they take the wrong turn , somewhere down the line , it xxunk isn ' t going to be the american xxunk system that gets them back on track ! xxunk , xxunk this movie like the xxunk . i bet you have better things to do with your time than waste it on this piece of xxunk . \n", + " \n", + " ,xxbos i was xxunk enough to meet george pal ( and still have my xxup ds : xxup xxunk xxunk xxunk by him ) at a convention xxunk after the release , and xxunk him why he xxunk to do the film \" camp \". before he could answer , two studio xxunk xxunk and xxunk me on how the studio \" knew best \" and how \" no one will take such a film xxunk \". i had been reading the xxunk xxunk for a couple of years thanks to a friend ( xxunk xxunk of the 1970 s will recall xxunk and his band ? i was in a couple of years of that with him ), and had higher hopes than what we got . \n", + " \n", + " the xxunk xxunk that no high adventure would ever be done xxunk , and so doing ' camp ' was the only way . several other xxunk xxunk in on my side , with pal listening as best he could . at the end of the little event , pal came up to us and xxunk , xxunk he could have done more and better . \n", + " \n", + " xxup star xxup wars put the lie to the xxunk , and a year after pal ' s death , spielberg and lucas xxunk that doc savage could have xxunk been the next major movie franchise xxunk if it xxunk ' t been for the xxunk . \n", + " \n", + " tear out the memory or history of doc , and the film would have been worth a 6 / 10 rating as nothing more than a xxunk xxunk seller . \n", + " \n", + " but xxunk the legacy like that was no less an xxunk than killing a baby in the xxunk . \n", + " \n", + " doc savage can still come to the screen , and survive the xxunk xxunk by the xxunk to indiana jones , but it would have to be done in all xxunk and xxunk to xxunk the glory that we should expect from the first american xxunk . \n", + " \n", + " xxup xxunk : yes , there was a second script for xxup xxunk xxup of xxup evil , and it ' s a lot more serious . yes , there was xxunk xxunk shot , but mostly xxunk xxunk and very little with actors . and , yes , there _ is _ a xxunk of ron xxunk xxunk over a brick wall and xxunk at something over his shoulder with a xxunk built bronze xxunk . xxunk ' s xxunk a xxunk over a button down white shirt with a bronze tie , and the words \" xxup doc xxup savage : xxup xxunk xxup of xxup evil xxunk coming next summer !\" xxup xxunk : if anyone knows who the studio xxunk were that xxunk george pal in 1975 to san diego for the convention , xxunk the xxunk up the side of the head and call them the xxunk that they are . at the time , they were doing xxunk and fu xxunk in stripes and xxunk canvas xxunk , and carrying paramount xxunk .\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: /root/.fastai/data/imdb_sample;\n", + "\n", + "Valid: LabelList (200 items)\n", + "x: LMTextList\n", + "xxbos does any one know what the 2 sports cars were ? i think robert stack ' s might have been a xxunk . rock hudson ' s character told his father he was taking a job in iraq , isn ' t that xxunk ? i have had xxunk malone in my xxunk bank most of my life , maybe this was the film that xxunk me . xxunk xxunk sure did have some xxunk in this film and xxunk xxunk malone but xxunk ' s part made a more xxunk impact so she got the oscar for best supporting role . was xxunk ' s part xxunk a leading role ? old man xxunk character was was xxunk a pretty common picture of xxunk of his era in that he was a regular guy who made it big in an emerging industry but in building a whole town he had xxunk his children to have his wife bring them up . in time , being xxunk he xxunk that they were all he really had and they were xxunk rotten , looking for attention , so rather than try to xxunk to his children he xxunk his head off . an ancient morality tale . but xxunk , what were those sports cars ?,xxbos god bless 80 ' s xxunk films . this is a fun , fun movie . this is what xxunk films are all about . now i ' m not xxunk horror movies , just xxunk films . it goes like this : a high school nerd is xxunk on by all these stupid xxunk and xxunk , and then one of their xxunk goes xxunk wrong . xxunk and back for revenge , xxunk a joker / xxunk mask ( pretty xxunk looking , might i add ), marty begins to kill off those xxunk one by one many years later , after he xxunk to make them believe that their old xxunk high school is having a reunion . that is xxunk the plot ? what ' s wrong with that ? that ' s the beauty of 80 ' s xxunk films , most of them i would say . a lot of things could be so xxunk , but they keep drawing you more in an ' in as they go by . xxunk this film . \n", + " \n", + " it features some xxunk xxunk , and some are xxunk creative as well . ( poisoning of a xxunk can , acid bath , i can ' t remember a xxunk ever being used before in any other xxunk film either ) it really is a fun , fun movie . that ' s all it is . nevermind the fact that the characters are complete xxunk , never mind their xxunk , and never mind the xxunk , random things that xxunk in this film . such as lights being able to be controlled by the killer ( when he ' s not even switching any xxunk , you ' ll see ) and xxunk being able to xxunk up blood , xxunk being able to have acid come out of them , just use that as part of your entertainment ! because xxunk what really makes it xxunk . \n", + " \n", + " movies like this represent 80 ' s xxunk . never again could movies like this get made , know why ? it isn ' t the 80 ' s xxunk . that is why you should just xxunk them for what they are , good fun ! i highly xxunk this film if you ' re a hardcore fan of xxunk such as friday the 13 th . \n", + " \n", + " one last note this movie also had a kick ass xxunk as well , marty xxunk . a xxunk , nerd , who kills all his old xxunk in a xxunk xxunk mask . a good xxunk makes a good xxunk . simon xxunk , who played marty xxunk xxunk suicide xxunk after xxunk high was released . that alone xxunk something xxunk to the film , and sticks with it and it even makes you feel more sorry for the marty character , i guess . all in all , great 80 ' s xxunk fun ! it ' s a shame it will never be the same again xxunk,xxbos the basic formula for the original series was ; take someone , get the audience to like them , then put them into xxunk danger . this formula xxunk for the 32 xxunk made between 1964 - 68. \n", + " \n", + " now , we jump forward 40 years to xxunk we are xxunk to alan tracy , a xxunk xxunk college school kid , with his friend , fermat , a young xxunk . they are xxunk off by lady xxunk in her pink ford xxunk to the island paradise where the tracy family live , for the school xxunk . almost xxunk , they are left in the care of xxunk and his daughter , xxunk xxunk the xxunk go to rescue john from xxunk 5 which has been xxunk by a xxunk xxunk . this is all part of the hood ' s scheme to take over tracy island so that he can steal the xxunk machines xxunk \n", + " \n", + " xxunk to rob a bank ! \n", + " \n", + " yes . the plot xxup is as xxunk as that ! \n", + " \n", + " the dialogue is xxunk , the acting more wooden than that of the ( xxunk ) puppets , the effects , anything but special and hans xxunk ' s score xxunk what little there was of barry gray ' s glorious theme xxunk through xxunk ' s xxunk xxunk . the rest of the score was xxunk xxunk . in fact , part of the score was broadcast the following week on the radio and didn ' t xxunk it ! i didn ' t even xxunk to stay to witness xxunk ' s xxunk xxunk with the end titles \n", + " \n", + " to be fair , ron cook xxunk xxunk well as parker , he and sophia myles as xxunk xxunk xxunk . with the right material , they could have been show xxunk . the xxup cgi work was what i would have called leading edge - 5 years ago . \n", + " \n", + " the dynamics of the main craft were just wrong ; the original series models at least xxunk as if they had mass \n", + " \n", + " another xxunk point is that the whole production xxunk to be one long set of product xxunk , from every vehicle being built by ford to the entire content of the tracy xxunk being produced by ben & jerry ' s . \n", + " \n", + " my son ( 9 ) xxunk the film but this cross between spy kids and ' xxunk ', xxunk xxunk at his age group , added nothing to the xxunk legend . when star trek hit the big screen in 1979 with ' the motion picture ', a whole new xxunk of life was xxunk into the franchise which then continued for another 20 years or so . with this film , xxunk has xxunk a golden opportunity to do the same with the xxunk franchise . \n", + " \n", + " i xxunk that this film , like ' the avengers ' and ' the saint ' before it , will sink into xxunk within 6 months , leaving the original series to its ' classic ' status .,xxbos the views of earth that are xxunk in this film to have been xxunk by xxup nasa have xxunk been xxunk with the historical weather data for the time of apollo 11, and show a good match between the cloud patterns in the video sequence and the xxunk xxunk records on the day . \n", + " \n", + " this would xxunk to xxunk the entire argument put forward in the film that the \" whole earth \" picture is xxunk a small part of the planet framed by the spacecraft window . \n", + " \n", + " i am waiting for bart xxunk to now xxunk that the historical weather data has been xxunk by xxup nasa , though that would no doubt xxunk them in also xxunk every xxunk newspaper copy with a weather map , and the ones in private hands would still be a problem . \n", + " \n", + " ah , a response : \" xxunk to xxunk this movie by xxunk to xxup nasa weather data i ' d say is a xxunk , but weak and xxunk argument . what about the rest of the xxunk and xxunk in the movie ? a certain wise man once said something about xxunk xxunk and xxunk xxunk . do you in any way feel that maybe this could xxunk to what you are xxunk to do here ? : - ) this movie is just packed with xxunk evidence against the xxunk once made by u . s . government that the xxunk were a success , and that man now are true masters of the universe . things are xxunk never xxunk what they xxunk .. just watch the movie , and i dear say you ' ll see things a bit different than before .\" \n", + " \n", + " first off , weather data doesn ' t come from xxup nasa , it comes for met xxunk around the world . second , the weather data xxunk a major xxunk in the film . third , far from being \" packed with xxunk evidence \", the remaining xxunk in the film have been xxunk xxunk . xxunk thought he had a xxunk secret piece of film , so he edited it and added his own interpretation . xxunk for him , his source film is public domain , and the xxunk xxunk edited out xxunk his xxunk .,xxbos xxup swing ! is an important film because it ' s one of the remaining xxunk and xxunk films from the 1930 s . many of these films have simply xxunk so xxunk that they are xxunk , but this one is in xxunk good shape . it ' s also a nice chance to see many of the talented black xxunk of the period just after the xxunk of the old cotton xxunk time all but xxunk today . \n", + " \n", + " xxunk , while the film is xxunk important and has some lovely performances , it ' s also a mess . the main plot is very similar to the hollywood xxunk of the xxunk a prima donna who is going to xxunk the show and the surprise unknown who xxunk from no where to save the day . however , the writing is just xxunk and a bit xxunk at xxunk projects images of black america that some might find a bit xxunk . this is because before the plot really gets going , you are xxunk to a xxunk xxunk who lives off his hard working wife ( a popular stereotype of the time ) and when he is xxunk with a xxunk ( who , by the way , xxunk xxunk this role ), they have a fight which xxunk like a scene from xxup wwe smackdown ! and , the one lady wants to cut the other lady with a straight xxunk xxunk scene xxunk ! later in the film , when the prima donna is xxunk xxunk , her husband xxunk her in the face and everyone xxunk him ! it xxunk like the film , at times , wants to appeal to the xxunk common xxunk in the audience xxup plus they can ' t even do this xxunk some of the worst acting i ' ve seen in a very long time . \n", + " \n", + " still , if you can look past a xxunk production in just about every way ( with xxunk characters , bad acting and direction and poor writing ), this one might be worth a xxunk so you can see excellent singing and tap xxunk well as to catch a xxunk of xxunk black culture . just don ' t say i didn ' t xxunk you about the xxunk ' s really , really bad !\n", + "y: LMLabelList\n", + ",,,,\n", + "Path: /root/.fastai/data/imdb_sample;\n", + "\n", + "Test: None, model=SequentialRNN(\n", + " (0): AWD_LSTM(\n", + " (encoder): Embedding(60005, 400, padding_idx=1)\n", + " (encoder_dp): EmbeddingDropout(\n", + " (emb): Embedding(60005, 400, padding_idx=1)\n", + " )\n", + " (rnns): ModuleList(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (2): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (3): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " )\n", + " (input_dp): RNNDropout()\n", + " (hidden_dps): ModuleList(\n", + " (0): RNNDropout()\n", + " (1): RNNDropout()\n", + " (2): RNNDropout()\n", + " (3): RNNDropout()\n", + " )\n", + " )\n", + " (1): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + "), opt_func=functools.partial(, betas=(0.9, 0.99)), loss_func=FlattenedLoss of CrossEntropyLoss(), metrics=[], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('/root/.fastai/data/imdb_sample'), model_dir='models', callback_fns=[functools.partial(, add_time=True, silent=False), functools.partial(, clip=0.12)], callbacks=[...], layer_groups=[Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): Embedding(60005, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(60005, 400, padding_idx=1)\n", + " )\n", + " (2): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)\n", + "alpha: 2\n", + "beta: 1], layer_groups=[Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(400, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 1550, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): WeightDropout(\n", + " (module): LSTM(1550, 400, batch_first=True)\n", + " )\n", + " (1): RNNDropout()\n", + "), Sequential(\n", + " (0): Embedding(60005, 400, padding_idx=1)\n", + " (1): EmbeddingDropout(\n", + " (emb): Embedding(60005, 400, padding_idx=1)\n", + " )\n", + " (2): LinearDecoder(\n", + " (decoder): Linear(in_features=400, out_features=60005, bias=True)\n", + " (output_dp): RNNDropout()\n", + " )\n", + ")], add_time=True, silent=False, cb_fns_registered=False)" ] + }, + "execution_count": 7, + "metadata": { + "tags": [] + }, + "output_type": "execute_result" + } + ], + "source": [ + "config = dict(emb_sz=400, n_hid=1550, n_layers=4, pad_token=1, qrnn=False, tie_weights=True, out_bias=True,\n", + " output_p=0.25, hidden_p=0.1, input_p=0.2, embed_p=0.02, weight_p=0.15)\n", + "trn_args = dict(drop_mult=0.9, clip=0.12, alpha=2, beta=1)\n", + "\n", + "learn = language_model_learner(data_lm, AWD_LSTM, config=config, pretrained=False, **trn_args)\n", + "\n", + "#load pretrained models\n", + "learn.load_pretrained(**_THWIKI_LSTM)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 122 }, + "colab_type": "code", + "id": "SwJK_G80KROl", + "outputId": "2d1fdff0-66e7-4f96-93fc-7e112c4306c8" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "id": "MyKkpWZbMOzt", - "colab_type": "code", - "colab": {} - }, - "source": [ - "" - ], - "execution_count": 0, - "outputs": [] + "name": "stdout", + "output_type": "stream", + "text": [ + "กาลครั้งหนึ่งนานมาแล้ว คุณวันจันทร์ได้รับการอุปการะจากแม่เธอ \n", + " \n", + " วันต่อมา เธอได้พบกับ \"อาเธอร์ โอลด์เดน\" เด็กหนุ่มที่มีบุคลิกคล้ายกับ \"เอมิลี\" ซึ่งเป็นน้องสาวของนาง เขาจึงได้รับการเลี้ยงดูจาก \"อาเธอร์ ดีอา\" และเป็นผู้ที่คอยดูแลเธออยู่เสมอ เธอได้แนะนำให้เธอเป็นผู้หญิง \n", + " \n", + " โดยมี \"เอลซ่า\" ซึ่งเป็นทายาทของ \"อาเธอร์ ยูจีน\" ผู้เป็นสามีของเขา และเคยช่วยยูนิตที่ถูกส่งตัวไปประจำอยู่ที่ดินแดนแห่งนี้ เธอได้พบกับ \"ยูลิสซิส เกรย์ เอลิซาเบธ เอลลิส \" (เอมิลี่ ไอเซนฮา) ซึ่งเป็นชาว \"เผ่าเอลฟ์ \" และเธอก็ไม่ค่อยมีบุตร แต่เธอก็ได้รับความช่วยเหลือจาก \"\n" + ] } - ] -} \ No newline at end of file + ], + "source": [ + "print(learn.predict('กาลครั้งหนึ่งนานมาแล้ว ', 200, temperature=0.8, min_p=0.005, sep = ''))" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "MyKkpWZbMOzt" + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "name": "text_generation.ipynb", + "provenance": [], + "version": "0.3.2" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/visualize.py b/notebooks/visualize.py new file mode 100644 index 000000000..5cfda4824 --- /dev/null +++ b/notebooks/visualize.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +""" +Visualization of text data +""" + +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from typing import Collection, Callable, Tuple + +__all__ = ['top_feats_label', 'top_feats_all', 'plot_top_feats'] + +def top_feats_label(X: np.ndarray, features: Collection[str], label_idx: Collection[bool] = None, + min_val: float = 0.1, agg_func: Callable = np.mean)->pd.DataFrame: + ''' + original code (Thomas Buhrman)[from https://buhrmann.github.io/tfidf-analysis.html] + rank features of each label by their encoded values (CountVectorizer, TfidfVectorizer, etc.) + aggregated with `agg_func` + :param X np.ndarray: document-value matrix + :param features Collection[str]: feature names + :param label_idx Collection[int]: position of rows with specified label + :param min_val float: minimum value to take into account for each feature + :param agg_func Callable: how to aggregate features such as `np.mean` or `np.sum` + :return: a dataframe with `feature`, `score` and `ngram` + ''' + res = X[label_idx] if label_idx is not None else X + res[res < min_val] = 0 + res_agg = agg_func(res, axis=0) + df = pd.DataFrame([(features[i], res_agg[i]) for i in np.argsort(res_agg)[::-1]]) + df.columns = ['feature','score'] + df['ngram'] = df.feature.map(lambda x: len(set(x.split(' ')))) + return df + +def top_feats_all(X: np.ndarray, y: np.ndarray, features: Collection[str], min_val: float = 0.1, + agg_func: Callable = np.mean)->Collection[pd.DataFrame]: + ''' + original code (Thomas Buhrman)[from https://buhrmann.github.io/tfidf-analysis.html] + for all labels, rank features of each label by their encoded values (CountVectorizer, TfidfVectorizer, etc.) + aggregated with `agg_func` + :param X np.ndarray: document-value matrix + :param y np.ndarray: labels + :param features Collection[str]: feature names + :param min_val float: minimum value to take into account for each feature + :param agg_func Callable: how to aggregate features such as `np.mean` or `np.sum` + :return: a list of dataframes with `rank` (rank within label), `feature`, `score`, `ngram` and `label` + ''' + labels = np.unique(y) + dfs = [] + for l in labels: + label_idx = (y==l) + df = top_feats_label(X,features,label_idx,min_val,agg_func).reset_index() + df['label'] = l + df.columns = ['rank','feature','score','ngram','label'] + dfs.append(df) + return dfs + +def plot_top_feats(dfs: Collection[pd.DataFrame], top_n: int = 25, ngram_range: Tuple[int,int]=(1,2),)-> None: + ''' + original code (Thomas Buhrman)[from https://buhrmann.github.io/tfidf-analysis.html] + plot top features from a collection of `top_feats_all` dataframes + :param dfs Collection[pd.DataFrame]: `top_feats_all` dataframes + :param top_n int: number of top features to show + :param ngram_range Tuple[int,int]: range of ngrams for features to show + :return: nothing + ''' + fig = plt.figure(figsize=(12, 9), facecolor="w") + x = np.arange(top_n) + for i, df in enumerate(dfs): + df = df[(df.ngram>=ngram_range[0])&(df.ngram<=ngram_range[1])][:top_n] + ax = fig.add_subplot(1, len(dfs), i+1) + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.set_frame_on(False) + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + ax.set_xlabel("score", labelpad=16, fontsize=14) + ax.set_title(f"label = {str(df.label[0])}", fontsize=16) + ax.ticklabel_format(axis='x', style='sci', scilimits=(-2,2)) + ax.barh(x, df.score, align='center', color='#3F5D7D') + ax.set_yticks(x) + ax.set_ylim([-1, x[-1]+1]) + ax.invert_yaxis() + yticks = ax.set_yticklabels(df.feature) + plt.subplots_adjust(bottom=0.09, right=0.97, left=0.15, top=0.95, wspace=0.52) + plt.show() diff --git a/notebooks/wongnai_classification.ipynb b/notebooks/wongnai_classification.ipynb index 59d1ae760..e9196f29f 100644 --- a/notebooks/wongnai_classification.ipynb +++ b/notebooks/wongnai_classification.ipynb @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -53,10 +53,11 @@ "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", - "from fastai.text import *\n", - "from fastai.callbacks import CSVLogger\n", + "# from fastai.text import *\n", + "# from fastai.callbacks import CSVLogger\n", "\n", "from pythainlp import word_tokenize\n", + "from pythainlp.ulmfit import process_thai\n", "\n", "ft_data = 'ft_data/'" ] @@ -77,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -91,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -105,7 +106,7 @@ "Name: rating, dtype: float64" ] }, - "execution_count": 5, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -116,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -130,7 +131,7 @@ "Name: rating, dtype: float64" ] }, - "execution_count": 6, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -285,7 +286,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Code for LinearSVC is provided by [@lukkiddd](https://github.com/lukkiddd).\n", + "Code for LinearSVC is initially provided by [@lukkiddd](https://github.com/lukkiddd). `pythainlp.ulmfit.process_thai` contains text cleaning rules with the default aimed for sparse models like bag of words. It contains `pre_rules` applied before tokenization and `post_rules` applied after.\n", "\n", "| model | micro_f1_public | micro_f1_private | \n", "|-----------|-----------------|------------------|\n", @@ -294,7 +295,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -304,13 +305,13 @@ }, { "cell_type": "code", - "execution_count": 93, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e941bc57e041489ea16998e1c3f9cddd", + "model_id": "01cf5b2e041d4ce0a482073127c67c8b", "version_major": 2, "version_minor": 0 }, @@ -331,7 +332,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6672a556b6f44e829982f95efd89aa95", + "model_id": "097725d69a834eb5bda2b6d4b6c0c1e3", "version_major": 2, "version_minor": 0 }, @@ -351,25 +352,17 @@ } ], "source": [ - "import string\n", - "def process_text(text):\n", - " nopunc = [char for char in text if char not in string.punctuation]\n", - " nopunc = ''.join(nopunc)\n", - " return [word for word in word_tokenize(nopunc, engine='ulmfit') if word and not re.search(pattern=r\"\\s+\", string=word)]\n", - "def split_text(text):\n", - " return text.split()\n", - "\n", "train_splits = []\n", "test_splits = []\n", "for i in tqdm_notebook(range(train_bal.shape[0])):\n", - " train_splits.append(' '.join(process_text(train_bal['review'][i])))\n", + " train_splits.append(' '.join(process_thai(train_bal['review'][i])))\n", "for i in tqdm_notebook(range(test_df.shape[0])):\n", - " test_splits.append(' '.join(process_text(test_df['review'][i])))" + " test_splits.append(' '.join(process_thai(test_df['review'][i])))" ] }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -385,7 +378,7 @@ " verbose=0))])" ] }, - "execution_count": 94, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -396,7 +389,7 @@ "from sklearn.svm import LinearSVC\n", "\n", "text_clf = Pipeline([\n", - " ('vect', CountVectorizer(tokenizer=split_text, ngram_range=(1,2))),\n", + " ('vect', CountVectorizer(tokenizer=process_thai, ngram_range=(1,2))),\n", " ('tfidf', TfidfTransformer()),\n", " ('clf', LinearSVC()),\n", "])\n", @@ -406,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -415,7 +408,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ diff --git a/notebooks/word2vec_examples.ipynb b/notebooks/word2vec_examples.ipynb new file mode 100644 index 000000000..8d0243f3f --- /dev/null +++ b/notebooks/word2vec_examples.ipynb @@ -0,0 +1,1195 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Thai2Vec Embeddings Examples\n", + "\n", + "We use the embeddings from `v0.1` since it was trained specifically for word2vec as opposed to latter versions which garner to classification. The `thai2vec.bin` 51,556 word embeddings of 300 dimensions, in descending order by their frequencies (See `thai2vec.vocab`). The files are in word2vec format readable by `gensim`. Most common applications include word vector visualization, word arithmetic, word grouping, cosine similarity and sentence or document vectors. For sample code, see `thwiki_lm/word2vec_examples.ipynb`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# #uncomment if you are running from google colab\n", + "# !pip install sklearn_crfsuite\n", + "# !pip install https://github.com/PyThaiNLP/pythainlp/archive/dev.zip\n", + "# !pip install fastai==1.0.46\n", + "# !pip install emoji" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-28T04:55:05.294165Z", + "start_time": "2018-01-28T04:55:05.203078Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Download: thai2fit_wv\n", + "thai2fit_wv 0.1\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "thai2vec.bin?dl=1: 62.5MB [00:15, 4.09MB/s] \n" + ] + } + ], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2\n", + "%matplotlib inline\n", + "\n", + "from pythainlp.tokenize import word_tokenize\n", + "from gensim.models import KeyedVectors\n", + "import numpy as np\n", + "\n", + "from sklearn.manifold import TSNE\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.font_manager as fm\n", + "\n", + "import dill as pickle\n", + "import pandas as pd\n", + "\n", + "model_path = 'thwiki_data/models/'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "#load into gensim\n", + "# model = KeyedVectors.load_word2vec_format(f'{model_path}thai2vec.bin',binary=True)\n", + "from pythainlp import word_vector\n", + "model = word_vector.get_model()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-28T04:58:27.057401Z", + "start_time": "2018-01-28T04:58:09.721798Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
0123456789...290291292293294295296297298299
ที่0.308956-0.0976990.1167450.2156120.015768-0.0641630.0621680.0396490.8649400.846904...-0.1424180.0332410.171581-0.624864-0.0093580.4491310.120130-0.122195-0.450617-0.071318
และ0.010751-0.6189710.1296650.035460-0.0075600.0276070.3978240.0265430.2540750.168328...-0.1057860.180930-0.1016300.070885-0.0372630.183606-0.049088-0.672288-1.2930440.592576
เป็น-0.015736-0.2589260.0529530.153728-0.005985-0.0210810.0410880.0573121.6332300.442729...-0.009408-0.252576-0.3055120.3725420.0491510.5684700.2665860.400800-0.7846500.197369
ของ-0.189711-0.1747740.171124-0.1867710.054294-0.114150-1.109456-0.094466-0.4470150.042377...-0.168676-0.1487380.6804040.0977020.0202700.182967-0.0839490.006287-0.707434-0.070234
มี-0.156962-0.2318630.0803120.3231570.2156950.0551450.4207940.0168420.2567590.832864...-0.044267-0.147186-0.1054240.9070780.0092990.5509530.1393370.031696-0.670379-0.008048
ได้-0.428813-0.0311940.041922-0.036608-0.0081060.076470-0.7822700.0333610.6068640.440520...0.024458-0.0250310.103389-0.0782550.0343230.459774-0.7486430.337775-0.487408-0.511535
\"\"\"\"-0.2877100.0641930.2050760.146356-0.071343-0.039451-1.8454610.1637631.0180960.272786...0.051024-0.532856-0.131856-0.090323-0.0588950.151262-0.4203580.055971-0.9308140.163908
การ0.239587-0.3036200.079953-0.453045-0.528826-0.1616920.235725-0.0996730.6916680.536159...-0.110436-0.297495-0.2174140.0451580.0666470.190095-0.304333-0.724927-0.995488-0.716609
(-0.120522-0.3557830.168180-0.377733-0.158624-0.0472490.3611400.1614600.9133140.345037...0.116285-0.318218-0.3566640.5198890.1304750.1257720.101328-0.382658-1.2053590.340139
)-0.086848-0.1552310.133015-0.0399130.1837610.115142-1.940854-0.066565-2.3997440.146722...0.019406-0.1814740.0998630.5160920.2016970.2491390.2529571.138815-0.0182090.232265
\n", + "

10 rows × 300 columns

\n", + "
" + ], + "text/plain": [ + " 0 1 2 3 4 5 6 \\\n", + "ที่ 0.308956 -0.097699 0.116745 0.215612 0.015768 -0.064163 0.062168 \n", + "และ 0.010751 -0.618971 0.129665 0.035460 -0.007560 0.027607 0.397824 \n", + "เป็น -0.015736 -0.258926 0.052953 0.153728 -0.005985 -0.021081 0.041088 \n", + "ของ -0.189711 -0.174774 0.171124 -0.186771 0.054294 -0.114150 -1.109456 \n", + "มี -0.156962 -0.231863 0.080312 0.323157 0.215695 0.055145 0.420794 \n", + "ได้ -0.428813 -0.031194 0.041922 -0.036608 -0.008106 0.076470 -0.782270 \n", + "\"\"\"\" -0.287710 0.064193 0.205076 0.146356 -0.071343 -0.039451 -1.845461 \n", + "การ 0.239587 -0.303620 0.079953 -0.453045 -0.528826 -0.161692 0.235725 \n", + "( -0.120522 -0.355783 0.168180 -0.377733 -0.158624 -0.047249 0.361140 \n", + ") -0.086848 -0.155231 0.133015 -0.039913 0.183761 0.115142 -1.940854 \n", + "\n", + " 7 8 9 ... 290 291 292 \\\n", + "ที่ 0.039649 0.864940 0.846904 ... -0.142418 0.033241 0.171581 \n", + "และ 0.026543 0.254075 0.168328 ... -0.105786 0.180930 -0.101630 \n", + "เป็น 0.057312 1.633230 0.442729 ... -0.009408 -0.252576 -0.305512 \n", + "ของ -0.094466 -0.447015 0.042377 ... -0.168676 -0.148738 0.680404 \n", + "มี 0.016842 0.256759 0.832864 ... -0.044267 -0.147186 -0.105424 \n", + "ได้ 0.033361 0.606864 0.440520 ... 0.024458 -0.025031 0.103389 \n", + "\"\"\"\" 0.163763 1.018096 0.272786 ... 0.051024 -0.532856 -0.131856 \n", + "การ -0.099673 0.691668 0.536159 ... -0.110436 -0.297495 -0.217414 \n", + "( 0.161460 0.913314 0.345037 ... 0.116285 -0.318218 -0.356664 \n", + ") -0.066565 -2.399744 0.146722 ... 0.019406 -0.181474 0.099863 \n", + "\n", + " 293 294 295 296 297 298 299 \n", + "ที่ -0.624864 -0.009358 0.449131 0.120130 -0.122195 -0.450617 -0.071318 \n", + "และ 0.070885 -0.037263 0.183606 -0.049088 -0.672288 -1.293044 0.592576 \n", + "เป็น 0.372542 0.049151 0.568470 0.266586 0.400800 -0.784650 0.197369 \n", + "ของ 0.097702 0.020270 0.182967 -0.083949 0.006287 -0.707434 -0.070234 \n", + "มี 0.907078 0.009299 0.550953 0.139337 0.031696 -0.670379 -0.008048 \n", + "ได้ -0.078255 0.034323 0.459774 -0.748643 0.337775 -0.487408 -0.511535 \n", + "\"\"\"\" -0.090323 -0.058895 0.151262 -0.420358 0.055971 -0.930814 0.163908 \n", + "การ 0.045158 0.066647 0.190095 -0.304333 -0.724927 -0.995488 -0.716609 \n", + "( 0.519889 0.130475 0.125772 0.101328 -0.382658 -1.205359 0.340139 \n", + ") 0.516092 0.201697 0.249139 0.252957 1.138815 -0.018209 0.232265 \n", + "\n", + "[10 rows x 300 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#create dataframe\n", + "thai2dict = {}\n", + "for word in model.index2word:\n", + " thai2dict[word] = model[word]\n", + "thai2vec = pd.DataFrame.from_dict(thai2dict,orient='index')\n", + "thai2vec.head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using t-SNE, we can compress the 300 dimensions of each word into a 2D plane and plot their relationships." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-26T02:35:36.291285Z", + "start_time": "2018-01-26T02:35:36.264520Z" + } + }, + "outputs": [], + "source": [ + "labels = model.index2word\n", + "\n", + "# #tnse\n", + "# tsne = TSNE(n_components=2, init='pca', n_iter=1000)\n", + "# thai2plot = tsne.fit_transform(thai2vec)\n", + "# pickle.dump(thai2plot,open(f'{model_path}thai2plot.pkl','wb'))\n", + "\n", + "thai2plot = pickle.load(open(f'{model_path}thai2plot.pkl','rb'))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "labels[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-26T02:35:39.610920Z", + "start_time": "2018-01-26T02:35:38.469383Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABCAAAAYICAYAAABLjLsXAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3XmclmWh//HvwyIoKqgpoKm45JInE7IAR2QTRRNUMn9KmaLmcUvKpVxK8RxLUistLLM8qajHoymiFqKCmICmGEGZuBG5gbt4kH3m+f2BznESEpSLAXy/X69eMfdzL9fzvKBmPnPd112pVqsBAAAAKKlJYw8AAAAAWPsJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgQAAABQnAABAAAAFCdAAAAAAMUJEAAAAEBxAgSsJiqVSpNKpXJVpVIZW6lUdnxn2wGVSuWQxh4bAADAR9WssQcA1Fs/ybZJXkuyeaVSaZLktCSHN+qoAAAAVoJKtVpt7DEA76hUKvsnOSFJqyTTkwytVqtPN+6oAAAAPjoBAlZjlUqlWbVaXdzY4wAAAPio3IIBq4lKpbJpkpuSVN7ZVJvk50luqVQqX01yTJas2zIvyTer1eq0RhkoAADAhyBAwOqjJksCw91JRlar1b8mSaVS2S/Jjkl6V6vVukqlsmuSq5N0aayBAgAArChPwYDVRLVavS1JzyR3JDmkUqlcX6lUKkm2StI2yR7v7Dc1yYxKpfKJRhssAADAChIgYDVSrVbrqtXq1Gq1OiRJXZJNk/x3ki2S/O09u76ZJU/NAAAAWCMIELD6qs2Sf6OfTfJgtVp9vZHHAwAA8KEJELCaqVQq21cqlfuS7PfOpqZJPAkDAABYowkQsPr5apJvJXkgS2ZBAAAArPE+MEBUKpWWlUrl4UqlMqVSqTxWqVTOf2f7NpVK5Y+VSuXpSqXyP5VKZZ3yw4WPhTuSXJmkWbVafaWxBwMAALAyVKrV6r/eYckq/K2q1eqcSqXSPMn4JIOTnJrk1mq1emOlUrkiyZRqtfqL4iMGAAAA1jgfOAOiusScd75s/s5/qkl6JfntO9uvSXJQkRECAAAAa7zlWgOiUqk0rVQqf07ycpJ7kjyT5M1qtfruwnjPZ8ljAgEAAADep9ny7FStVmuT7FapVNokGZFkp+W9QKVSOS7JcUnSqlWrz+2003IfCiSpm7s4tW/Oz3vvlqpUkqZtWqbJesv1TxiAD+HRRx99tVqtbtrY4wCAtcUK/fRSrVbffOfxgF2TtKlUKs3emQXxySQvLOOYK7NkQb3svvvu1UmTJn3EIcPHy8yhD6f2zQXv2960TYu0P/MLjTAigI+HSqXyj8YeAwCsTZbnKRibvjPzIZVKZd0kfZI8nuS+JIe8s9uRSUaWGiR8nC0tPvyr7QAAAKuj5ZkB0T7JNZVKpWmWBIubqtXqnZVK5W9JbqxUKhckmZzkqoLjhI+tpm1aLHMGBAAAwJriAwNEtVqdmqTjUrZPT2L+NxS24b4d8uatT6W6qK5+W6V5k2y4b4fGGxQAAMAKWq6nYMCq8Pzzz6d///7p3r17evfunZdffjlz587NPvvsk0GDBqVTp0659957GxzTt2/fJMnMmTPTp0+fHHXUUfWv7b///qty+MW06rhZ2gz4VP2Mh6ZtWqTNgE+lVcfNGnlkAAAAy88S+qw2zjvvvDz99NP54Q9/mBdffDH/8z//k6eeeipnnHFGLr300tx000358Y9/nL333vt9x/7ud7/Lj370o5x99tl5880306xZszRrtvb89W7VcTPBAQAAWKOZAcFq4/XXX88f//jHjBs3Lm+//XZ22223vPTSS2nTpk122223HH744amrq1vqsZ/5zGdy+umnZ+bMmVlvvfVy5plnZtCgQav4HQAAALAsAgSrjRNPPDH77LNPunbtmkceeSTdunXL17/+9YwbNy7f//73c/PNNy/z2M6dO+eoo45K69at061bt+ywww45+OCDV+HoAQAA+FfWnjnqrPH69OmTPn36ZOLEidlll12SJM2aNUttbe1S93/77bcze/bs+q8HDhyYgQMHrpKxAgAAsGLMgGC1s3Dhwg9cv+Gxxx7L/vvvny233DJJ8uKLL+aoo47KN7/5zfp9Tj755KLjBAAAYPmZAcFqZ7311surr76aZMm6EK1atap/7bXXXstXv/rVPPPMMzn44IOzYMGCPPjgg3n66afTs2fP/OpXv8rbb7+dhx9+OPPmzWustwDwoS1atCivv/562rZt29hDAQBYqSrVanWVXWz33XevTpo0aZVdjzXT4sWL8+UvfzlvvPFGqtVqbrjhhmyxxRaZMWNGdt5559x2223p2LFjBgwYkGq1mhEjRqRVq1YZPHhwxo8fn8022yxbb711fvrTn2ajjTZq7LcDsEJmzJiRoUOH5oorrmjsoXzsVSqVR6vV6u6NPQ4AWFuYAcFqp1mzZhkxYsT7tnfo0KHBrIbx48c3eP3Xv/518bEBAADw4VgDAgBWIx06dDD7AQBYK5kBwVpj5qyRmf7MJZm/YGZatmifbbc7Pe3bHdjYwwIAACACBGuJmbNGZtq0c1JXt+QWjfkLXsy0aeckiQgBAACwGnALBmuF6c9cUh8f3lVXNy/Tn7mkkUYEAADAewkQrBXmL5i5QtsBAABYtQQI1gotW7Rfoe0AAACsWgIEa4Vttzs9TZqs22BbkybrZtvtTm+kEQEsnzlz5mTPPfdMt27d8vzzzydJxo0bl6FDh+bZZ5/N/vvvnx49eqR79+6ZMmVKkuT2229Pp06dcvLJJzc419ChQzNu3LhV/RYAAJaLAMFaoX27A7PTTt9PyxabJ6mkZYvNs9NO37cAJbDamzx5cjp16pRzzjnnffHg1FNPrY8Kv/nNb3LOOUsW173pppty11135cknn2yEEQMAfDiegsFao327AwUHoNE8//zz+eQnP7nCx9XW1ub222/P9OnTc9111zV47T//8z+z8847J0m23XbbLF68OElywgkn5OCDD8706dM/+sABAFYRMyAAYCU49thjP/Sxxx9/fO688860adOmwfZ348M/q6mpyYQJE/LZz372Q18TAGBVEyAAYDWwcOHCHHbYYXnxxRc/9DmmTZuWDTfccCWOCgBg5REgAGAluOaaaz7S8UOGDMn++++fU089NdVqdYWOnTNnTs4777zccsstH+o2EACAVUGAAICV4Mgjj/zQxz744IOZN29evva1r6Vfv365/PLLl/vYyy+/PAcddFDuvvvuTJ48Oeeee+6HHgcAQEkCBACsoD/96U85/PDD07t37+y3334ZMWLERzrftGnT8v3vfz9J8pWvfCVPPfVUfvnLX9af99VXX83pp7//scLz58/Pn//854wePTpdunTJYYcdlu7du3+ksawKl112Wbp16/aB7w8AWLtUVnSa50ex++67VydNmrTKrgcAK9vChQuzww47ZMstt0xdXV1at26df/zjH9lyyy1z1113rZRrfOlLX8pWW22VjTfeOCeeeGJOPPHEHHvssenTp89KOX9jW1PeX6VSebRare7e2OMAgLWFAAEAH8FLL72U+++/Py+88EK+9a1vrZRzPv744/nBD36Q5557LptssklOOumk9OrVa6Wce3Wwprw/AQIAVi4BAgDWQG9PfjlvjZ6R2jcXpGmbFtlw3w5p1XGzxh7WWkWAAICVyxoQAPAB+vbt2+DrWbNmZeDAgdl7773TuXPnXHjhhfWvvfXWW+nbt2/22muvjBs3Lkly/PHHZ8aMGUmSc845J926dUuvXr1yyCGHZObMmct13nPOOSedOnXKtddem7cnv5w3b30qtW8uyI/H/1ceeexPefPWp/L25JfLfQgryWWXXZZevXqlV69e6dq1a/17fO/7e69//uwBgDWXAAEAK+iUU07Jf/zHf+Tee+/NhAkT8tRTT+W3v/1tkmT06NHZaKONss4662SDDTZocNxNN92Upk2b5oEHHsjYsWMzZMiQnHrqqct13kceeSTjx4/PrbfemrdGz0h1UV2Dc1cX1eWt0TPKvvGPaMyYMalUKhk7dmzGjh2bCRMm5LXXXsvVV1/d4P0BAGsnAQIAVsArr7ySjTbaKFdeeWUWL16cZs2a5dvf/nb9bIetttoqG220Ue6999587nOfa3DsQQcdlCFDhtR//W//9m95/fXXl+u8Bx54YPr06ZP58+en9s0FSx3bsravLnr37p1PfepT6dKlS375y1+mSZMmOe644/Lwww83eH8AwNpJgADWaNdff30eeuihxh4GHyObbrppdtxxx+ywww5p1qxZkqRNmzaZM2dOkqRz5855+eWX06lTp/pHa75rnXXWSZMmDf+vt1KpLNd5TzrppEyYMCFJ0rRNi6WObVnbVyc//elPM2rUqIwePTrJks+krq6uwfsDANZOzRp7AAArYsGCBRk0aFBmzpyZurq6tG/fPldffXVjD4uPmbvvvjujRo1a6mvPPPNM1l9//fzpT39aqed9rw337ZA3b32qwW0YleZNsuG+HVb4mqvawoUL069fv/y///f/PnDf2travPTSS6tgVADAqmAGBLBGueuuu7Lrrrvmvvvuy/33358bb7wxLVu2/MDjxo0bl6FDh66CEbK2uPfeezNy5MgkyaRJk1JTU9PgN/Tvzlz4Z88991x22mmnDzz/iBEj0rVr1/f9gL2s875Xq46bpc2AT9XPeGiyQfO0GfCpNeIpGM2bN8/48ePzjW9841/u9+yzz+bQQw9Ny5Yts3jx4lU0OgCgJAECWKO0atUqyZIf8m6//fbsu+++mTp1aiOPirXFSSedlJ49e6ZHjx659NJLs8ceeyRJ2rZtm3vuuSdXXXXVB56jffv2mTRpUt59zPXixYszderUfOITn2iw329+85v84Q9/SOvWrVdojK+++mrmz5+fVh03S/szv5B/tH0rO53afY2ID0nSunXrBrNDJk+enE022aT+67lz5+Yb3/hGvvrVr6Zdu3Y58cQTc/PNNzfGUAGAlcwtGMAapXv37rn//vtTW1ub8ePHZ7311quPEh/G4sWL07Rp0+X6rTNrtylTpqS2tjb33Xff+16rqalJ9+7dc+65537geXbcccfsvvvu2WOPPdKyZcvMnz8/xxxzTNZff/0G++23337p0qVLDjnkkBUa5+DBg9OjR4+0bNkyCxYsyH777Zftt99+hc7RmP7jP/4jJ554Ympra1OtVrPBBhs0CDvjx4/PoEGDcskll6R///555JFHcs011zTiiAGAlaXy7m9oVoXdd9+9OmnSpFV2PWDtM2XKlJxzzjmZO3duFi1alG7duuWCCy6oX9jv9ttvz5AhQ7LHHntk2LBh9ceNGzcuDz30UD71qU/loosuynrrrZdqtZqNNtooP//5z9O+fftcdtllufnmm1NbW5u99torP/zhD+uPv+6663LVVVelrq4u6667bi699NIG0+ynT5+e008/PbNnz868efNy0EEH5dvf/vaq+2D4yJ5++un8+Mc/zllnnZXnnnsu559/fk4//fT06dOnsYdGI6lUKo9Wq9XdG3scALC2cAsGsNrq27dv/Z9vv/327Lrrrtlvv/0ybNiwjB07Nn369Mk111yTo48+OosXL84BBxyQQYMG5cc//nGefPLJpZ7nt7/9bXbeeecceeSRGTFiREaMGJH27dvnz3/+cyZOnJgHHnggDz74YF5//fVMnDgxSTJq1Kg88cQTGTNmTO6///5cdNFFOeqooxqM9Zvf/GYuueSSjBkzJg888ED+/ve/mza+htl+++3Trl27LFq0KGPHjk2LFi1W+PYIAACWTYAA1gg33XRTvvOd76R169Z54YUX0rt37wwfPjyTJ0/OmDFjMmPGjGy11Vb53ve+l6OOOip/+ctflnqe//7v/87ll1+etm3b5oQTTsgNN9yQJNlyyy0zbNiw+lsxampq8txzzyVZshjeSy+9VB8kdt1113To0CGvvvpqkmT+/Pn59Kc/nbPPPjuLFi1K06ZN861vfSvjxo0r/Kmwsp177rnZdttt893vfje33357vvCFLzT2kN7nllmvZ/eJj6X9fX/O7hMfyy2zXm/sIa1Ut01+ITVDx2abM3+XmqFjc9vkFxp7SADASiJAAGuEE044IRdccEFeeGHJDyNz5szJK6+8kh133DGbbbZZtttuuyxYsCC/+c1vcvzxx+ezn/3sMs/VqlWr7Lfffrn++utz3XXXJUk22WSTbLrppg32e/cWtcMPPzwvvPBCPv3pT9e/1qZNm8yZMydJ0rJly7Rr1y4DBgxI8+bNkyQbbrhh3n777ZX3AbDSvXdmTJL87Gc/S48ePdKrV6907949V155ZYPXR48enb333js9evRIjx498uCDD67K4SZZEh9Of+K5PL9gUapJnl+wKKc/8dxaEyFum/xCzrr1L3nhzXmpJnnhzXk569a/iBAAsJYQIIA1wruPQGzZsmU6deqU2bNnZ4899sjQoUNTW1ubSqWSq666Kpdddtlyn7Np06apq6v7wP2mTJmSrl27ZuONN17mPs8++2x23XXX5b42q5c777wz8+bNy3333ZexY8fmvvvuy7Rp03L33XcnSaZOnZpbb701v//97zNu3LgMHz48J554YubOnbtKx3nh9JmZV9dw7aZ5ddVcOH3mKh1HKRePfiLzFtU22DZvUW0uHv1EI40IAFiZBAhgjbHxxhuntrY2p5xyShYuXJhbbrklrVu3Tm1t7TKPmTFjRtZZZ533bb/iiivqH7H4QWpra9Os2dIfGrR48eIcdthhufnmm+tnZ7D6O/744/PII4/kkksuSbJkRk2LFi1y0EEHZaONNkrbtm3zu9/9LqNHj06SPPjgg7nrrrvyuc99Lt27d8/w4cOz77775m9/+9sKX3vx4sUfetwvLFi0QtvXNC++OW+FtgMAaxYBAlhtTZo0qX7mw7uaNm2ayZMn5wc/+EHWXXfdZR7bsmXL3HTTTenXr1923HHHPPbYY9loo43qX7/rrrsyatSopcaJFTF58uTsuuuuOe+88+rXhGD19sorr+Tpp59OkyZNGvyduPbaa/PCCy/kr3/9a6ZPn54tttiifh2PUaNGZZtttsmdd96Z+++/P7Nnz85LL71UfxvOv7pWz54962/b6N27d0aOHJmbbrop3bp1S8+ePbPPPvvUry8ya9as7LXXXtlrr73yv//7v/XnOf744zNjxoxs0aL5Uq+zrO1rms3bLP3f9LK2AwBrFgGC4p566qkceeSR6d27d3r37p2rr766sYfEGqJt27a55557ctVVV9Vvq1Qq2XzzzXPYYYct87gZM2bkjTfeyDHHHJO6urpcd911ueuuuzJw4MD6fXbbbbf07NkzhxxyyEca4y677JKxY8fmqquuyp577vmRzsWq0bp169TV1aVjx4455phj6rcvWrQow4cPzxZbbJENNtgg559/fmbPnp0kufjii7P99ttn6623TpLss88+mTVr1gdea8KECamrq0ufPn0ybNiwjBkzJl26dMl//dd/1d/qccstt+SMM85ItVrN+PHjc/LJJ2evvfbK5MmT33e+s7Ztn3WbVBpsW7dJJWdt2/6jfCSrjTP23THrNm/aYNu6zZvmjH13bKQRAQAr09LnFMNKdNhhh6VFixZJkg022CDDhg1LkyZN8rWvfa2RR8bqrqamJt27d8+5555bv22XXXbJeeed12C/0047rcHXN998c+699960bNkygwYNyuabb57f/va39X/S5LPSAAAgAElEQVQPk2TIkCEZMmTIMq/93sdsvvvb6/e64oor6v987733JkkeffTRvPbaa9aCWM2ts846GTBgQAYPHpxPfOITGTlyZJJk+vTpOfroo3PRRRelW7du9QuKJknz5s3z+OOPp1evXkmSl156KYsWLbntYc6cOTn77LPzl7/8JdVqNXV1dTnttNNy4IEH5qCDDkr//v0zdOjQ9OvXL3Pnzs1uu+2WSy65JM2bN8+sWbNy6KGH5umnn87f//737LPPPvnKV76ScePG5d/+7d+SLHkCzG233ZZHH300u+yyS354wUW56NlX8sKCRdmiRfOctW37fKndstcnWZMc1HGLJEvWgnjxzXnZvM26OWPfHeu3AwBrNgGC4h599NH6P7/66qv5wx/+kJkz144F0yjrn59CkCQXXXRRvvOd7+TQQw/Ncccdl1GjRuWaa66pf71Hjx557bXX6r9+6KGHio/zd7/7XS688MI8++yzeeqpp3LffffV/6ac1dOIESOy4447ZtKkSTn55JOzzz77ZMstt8zNN9+cM888M926dWuw/7u3AY0dO7b+v4855pjcddddeeSRR/LlL385P/3pT5MsCRL9+/fPLrvsku233z6jR4/OvHnz8swzz+TII4/M0Ucfna9//et56KGH6mc8XHDBBZkyZUoOPvjg3HHHHencuXOS5OWXX84VV1yRfv365Zxzzsn111+fxX+4N5PeM5tnbXNQxy0EBwBYS7kFg1XqE5/4RAYMGJCTTjqpsYfCGqparaZJkya57bbbkiz5TfR7zZw1MhMmdMuYsdtnwoRumTlrZPExXXPNNbn//vuzzTbb5MQTT8x5552X448/vvh1+fCaN2+ePffcM927d8/BBx+cJGnfvn369++fQw899H3719TUpHXr1unSpUv23HPPDB48OJ/85Cfz+OOP54wzzsgf/vCH1NTU5KGHHsr666+fww47LH/605+SLHlCyksvvZSJEyemadOm2XnnndOhQ4e8+uqr2WeffTJ8+PBMnz69/rGv77Xeeuvl2muvTdOmTevH8dxzzxX8ZBqaOHFiunXrlj333DP//u//vlxPjQEAWBYBgpWub9++Db6eMmVKDjjggPTq1SvdunXL2WefXf9N7C9+8Yt06tQpP/jBDxoc8+6Ca3//+9/TpUuX9OnTJ/PmLVkFfejQofnMZz6TX//610mW3Ld99NFHp0ePHuncuXNuvPHGBue67bbb0rFjRz8QrgWe/OOs/G3Ewhy47ZmZ8beXM+3BFxs8UWDmrJGZNu2czF/wYpJq5i94MdOmnVM8QvTq1St77LFHdvrigbm71Sb525HfyNS2W+Uf8xYUvS4f3ptvvpkf/ehHeeSRR9KvX788/PDDOeOMM/KnP/0p/fv3T5J06dIl22+/fZKkQ4cOqVarufzyyzNr1qxceOGF2XPPPdO+/ZK1F+64446MHDmyfr2SddZZp/5/5w4//PA8+eSTOfPMMzNq1KgkSZs2bTJnzpzMnDmzwWKTtbW1+epXv5rHHnssd999d+bPn59PfvKTDca+tFBRytChQ7P11lvnyiuvzKJFizJt2rRVdm0AYO0jQFDUG2+8kRNPPDHDhg3L2LFj88ADD2T99dfPL37xiyTJ7bffnj/+8Y+5//77l3r8mDFjcuqpp6Zz587561//mtmzZ2fChAl56KGHcvvttydJfv7zn+dzn/tcxo0bl/vvvz8/+clPGvxQ+tvf/jajRo3K9OnTy79hinnyj7Ny3/XTMuf1JT/Ub73Jzun3pb7p+YX96veZ/swlqatr+Li+urp5mf7MJUXHdvzxx+fbI0fl7s69s+jggWm27aeSo0/OjBPPzC2zXi96bT6c733ve9lvv/3Ss2fP1NTUZPHixdl3333/5TELFy7MKaecknXXXTfnn39+unfvXv/aU089lQMPPDBHHnnk+46bMmVKmjRpkmHDhqVbt271sxmSZPjw4bn00kuzzTbbpEmTJpk8eXJ22GGH9OrVK88880yOPfbYnHXWWfUBdlXr3bt3Xn755SxYsCALFizIdttt95HO98+BGgD4eLEGBEVNnDgxAwcOzAsvvJBjjjkmvXv3zkknnZRjjjkmJ510Ur7+9a9nr732yvz585d6fP/+/XPEEUdk2rRpOeCAA3LTTTdl4MCBadWqVRYuXFi/z+abb55kyaMXd95557z22mtp27ZtkuSEE07IgAEDBIg13IMjn8nihf83/fuAzw9Kkqyf/1tYcv6Cpa8tsqztK9OF02dmXl3D30zPq6vmwukz15oFAtcmX/ziF/PFL37xA/e76667kiRvT345dc/Nzf8MuChN27TIhvt2yCsbza3f7/Of/3z9vv+strY2u+yyS4477rhsvvnm2XTTTRuMo3fv3pk3b17GjRuX0047LRMmTMijjz6aX/ziF/nyl7+c4cOH52c/+1nOP//8j/iuV9zgwYMzePDgvPXWW2natGmDhVwBAFaUGRAU924omDNnTm666aa0bt06c+bMSZIMGDAgDz74YH0s+GebbbZZRo8enUGDlvywOXLkyPr7td+1zTbbvO+b4mq1mhdffDGzZ89OTU1NJk6cmN12221lvzVWoXdnPvyr7S1bLP1RhMvavjK9sGDRCm1nzfH25Jfz5q1PZf2m6+Yvs55I7ZsL8uatT+XBW8Zlk002SbJkgd233nqr/pjJkyfXv5YkW2yxRR5++OH6tUve1bx58wwePDijRo3KtGnT8o1vfCOdOnXKF7/4xXz+859PkhxxxBGZM2dOOnToUP7NLsPrr7+e9dZbr9j56+rqUltbW+z871VbW5uf/OQn1rMAgEYgQFBU165dc99996VTp06pVqs5+eSTl+u4adOmZcMNN2yw7emnn86WW26Zli1bLtc5FixYkGOPPbY+drBmW3/jpf/m9b3bt93u9DRpsm6D15s0WTfbbnd60bElyRYtmq/QdtYcs34/PdVFdTl9z2Py/XG/yJdvOCVfuuak/Nevfp1TTjklSXLuueemb9++6dmzZ/bYY4/U1dXVP7LzX9lll10yYcKEfOtb38p3v/vd3Hbbbfn0pz+dW265pfTb+tCWd+2e3r17Z+7cuUs9xxNPPJGampr07NkzPXr0SN++fTN+/Pgkyemnn54uXbrkH//4R5Lkpz/9aUaPHp1kyeNz332yzeLFi3PAAQfkC1/4Qh577LEkS27b69ixY44++uj6a/3973/Pl770pfTs2TOdOnVK165d06ZNmzRp4lsgAFjV3ILBSjdp0qTU1NTkoosuSk1NTebMmZPBgwena9euOfbYY//lsa+++mq+973vZcaMGe8LDTfccEPOPffc5R7HNttskyFDhmTQoEEZPnz4h3ovrD66Hrhd7rt+WoPbMJqt0yRdD/y/e9LbtzswyZK1IOYvmJmWLdpn2+1Or99e0lnbts/pTzzX4DaMdZtUcta25WdfUM4ts17P5/93ySyW7TbZKjcedmmD19+dvdW/f//6xSv/WY8ePdKjR48G26644or6P7/7w/W7jjjiiHz2s5/NiBEjMnv27LRu3Tq9e/fOrrvuutRzrWrvrt1zwAEH5Oyzz37f6++u3TN16tT89a9/zRe+8IX37XPPPfdkww03TJ8+fXLwwQdnm222SbJkUeFqtZrTTz89I0aMyDe/+c1Mnjw5Bx74/n/DM2bMyFZbbZVvfvOb+f3vf59ddtklP/rRjzJ+/Pj069cvyZJIMXDgwFx++eVp27ZtLrzwwmy//fZ5+umnV/KnAgAsD/mfla5t27a555576leDX3fddfP666/n0ksvXeYxtbW1GTJkSA4//PA8//zzueaaa3LZZZc12Oell15Kly5dVmgsu+yyS7797W/nyCOPrL8VhDXTDp3bpedXdqqf8bD+xi3S8ys7ZYfO7Rrs177dgampeSC9ez2dmpoHVkl8SJIvtds4l+y4ZT7ZonkqST7Zonku2XFL6z+s4S6cPjMvtaws9bWmbcqshzB16tTccccdmT17dpJk9uzZueOOOzJ16tQi11tR767d8/LLLy/19f79++eqq67K8OHDl3mbw8knn5w77rgjNTU1GTZsWL71rW8lWXJLymOPPZaLL744HTt2zNixYzNv3rxsvfXW7zvHdtttlwULFuS0005LbW1tnnzyyWy11VZp1apV1llnnSRLZtN17do1rVu3znXXXZe5c+fmuOOOy6OPPrqSPg0AYEWYAcFKV1NTk+7du9fPVqitrc0ll1ySSmXp38QnS1aQ79atW+65554cdthhOe2003LJJQ2fXPDlL3/5Q43n85//fE444YT3rR3BmmeHzu3eFxxWJ19qt7HgsJZ5YcGiDPvUOvnuYwuy7nt+lp7XJNl83w5FrjlmzJgsWrRk1kWLuZum1Zxt0qSuRf5w5YtpecRmjf5vYMCAARkwYMAyn2jx7to9Q4YM+ZfnadasWTp37pzOnTs3eALJsGHD8p3v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jY2//vqrWVvbtm3N/rwmNjbWOGnSJNPxL7/8Yhw6dKhZn+nTpxujoqJuuk9BfUWkaNq1a2d2vH37duOkSZOMp06dMg4cONDs3I1/F7/88kvjihUrjLt37zYGBgYaW7RoYbSysjJ6eXkZW7ZsaXRycjKGhoYaO3ToYHRzczMOGzbMGBsbazQajcb09HRjpUqVTGNd//+Ga+Ne069fP2OTJk2MmzdvNosnODjYmJSUZDxx4oTR3d3d6OfnZ0xPTzfrc+P/c24HiDeW4vskfelLX/rSl74e9C8twRCREnf9koyicnR05OTJk2ZtJ06coEqVKsUQmYjcKC4uDg8PD1Mth2uzFe5Um+R6zz77LGFhYbz22ms89NBDtGvXjk8++YQmTZrw+eefk5OTw/Tp003LOhISEujYsSOQX9vlzJkzHDx40DRrCODLL78EoG3btpw7d46VK1cyYcIE4uLiAMjJySEyMpKAgACWLFnCmDFj8PDw4NChQ6bilqdOnWLfvn2mApvTpk0rhldMRERECksJCBEpFdeWZED+h42TJ08SEhLCyZMnSUhIuOV1FStWJCAggMDAQHr27EmXLl2oUaMGTz31VGmEfd86uiuZJRNj+HTYVpZMjOHoruQ7XyQCNGrUiG+//ZYFCxYU+doKFSrwyy+/mI47duzIU089RadOnVi1ahU//vgjixYt4tChQ7z++usYjUZmzpxJjx496NKlCw8//DAHDx4kMjISJycn4uPjSU9P58iRI2RlZQH5yzQaN25Mz549MRr/V/Pl5MmT2NvbM3HiRPLy8li4cCFff/212e4zo0ePpm7dumzdupVt27aRlpbGxo0b/8KrJSIiIkWhGhAiUuLCw8NN3yckJLBu3TpefPFFAF588UXWrVsHQMOGDWnevDnNmzc3u/7VV181+03orTz22GN89tlnxRj5/enormSiliWSk5X/wetySiZRyxIBqOvuUpahyX3A1dWVwMBAQkJCinxt+/bt2bhxI926dcPKyorLly8zZswYGjZsSMOGDQkPD6dTp04EBwfTunVrpkyZQl5eHps2baJbt26kpqZSu3Zt6tSpw4QJE8jOzqZdu3bk5OQwYMAA032mTp3K4MGD6datm6mtdu3a5ObmMnnyZPr06UNERMRNz7BixQo6d+5sOm7Tpg179+6lXbt2RX5WERERKTolIESkVEVG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qGDYggGgXIiMjJSvr69Gjx5d5PWUlBQNGjRIQUFBCgkJUdeuXXXgwAHr9RUrVsjf318BAQEaNGiQ8vLybFU6AAAAABFAACgnVqxYoaioKCUnJxd5ffLkyRo/frxiYmK0detWLV68WE8//bRM09S5c+f09ttvKzo6Wjt27FDDhg21YsUKGz8BAAAAcGdjCwaAcmHkyJHq3r27jh49WuT1BQsWaNOmTXr22WdlmqaaNGmimjVr6sSJE6pWrZo+/vhjOTs7S5L8/f0VHx9vy/IBAACAOx4BBIBywd/fX7GxserUqVOR148cOaKFCxdq1apVcnd31969exUaGqr8/HxVqVJFVapUKdTfNE1blA0AAADgf9iCAaBC2LVrl3r27Cl3d3dJUtOmTdWlSxc7VwUAAADgKgIIABVCbm6upk2bpvDwcGVmZkqSnJyc7FwVAAAAgKsIIACUK66urjp06JD188GDB1WtWjU5Ojrqueee06OPPqrY2Fg7VggAwP/X3v2FWnrdZRx/fjlpiUShLZWkJBEbKUopoYahIBQpgqE1F1GQ0IBQIRAvLIx4YxGCoyCIqDgXUok4EEGNJa0amIL2oqBSqE1iav+EajpEmpA/SCkxgbR0urw4OzIpmWByzrM32efzgWH2fs85vIvFgtnnO++7XgBeiT0ggDeUu+++O3feeWcODg5y8eLFXHPNNTl37lyee+653H777bniiisu+6hOAABgd2abG7GdOnVqPfjgg1s7HwDA6zUzD621Tu16HACwL9yCAZwI5y+czy3335Kb7r0pt9x/S85fOL/rIQEAwIniFgxg752/cD5nPncmL158MUny1AtP5cznziRJbr3RkzIAAGAbXAEB7L2zD5/9v/jwkhcvvpizD5/d0YgAAODkESCAvff0C0+/puMAAMDxEyCAvXft1de+puMAAMDxEyCAvXf65tO56uCqlx276uCqnL759I5GBAAAJ49NKIG999JGk2cfPpunX3g61159bU7ffNoGlAAAsEUCBHAi3HrjrYIDAADskFswAAAAgDoBAgAAAKgTIAAAAIA6AQIAAACoEyAAAACAOgECAAAAqBMgAAAAgDoBAgAAAKgTIAAAAIA6AQIAAACoEyAAAACAOgECAAAAqBMgAAAAgDoBAgAAAKgTIAAAAIA6AQIAAACoEyAAAACAOgECAAAAqDtSgJiZ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AOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoJALZC0AAAV2SURBVE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACgToAAAAAA6gQIAAAAoE6AAAAAAOoECAAAAKBOgAAAAADqBAgAAACg7n8BqIDvGC/cL84AAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "#stolen from https://blog.manash.me/how-to-use-pre-trained-word-vectors-from-facebooks-fasttext-a71e6d55f27\n", + "def plot_with_labels(low_dim_embs, labels, filename=None, figsize=(10,10),\n", + " axis_lims = None):\n", + " assert low_dim_embs.shape[0] >= len(labels), \"More labels than embeddings\"\n", + " plt.figure(figsize=figsize) # in inches\n", + " for i, label in enumerate(labels):\n", + " x, y = low_dim_embs[i, :]\n", + " plt.scatter(x, y)\n", + " prop = fm.FontProperties(fname=f'THSarabunNew.ttf',size=20)\n", + " plt.annotate(label,\n", + " fontproperties=prop,\n", + " xy=(x, y),\n", + " xytext=(5, 2),\n", + " textcoords='offset points',\n", + " ha='right',\n", + " va='bottom')\n", + " if axis_lims is not None: plt.axis(axis_lims)\n", + " if filename: plt.savefig(filename)\n", + " \n", + "plot_with_labels(thai2plot[200:500],labels[200:500],axis_lims = [0,30,0,30])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Word Arithmetic" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can do simple \"arithmetic\" with words based on the word vectors such as:\n", + "* ผู้หญิง + พระราชา - ผู้ชาย = พระราชินี\n", + "* นายกรัฐมนตรี - อำนาจ = ประธานาธิบดี\n", + "* กิ้งก่า + โบราณ = ไดโนเสาร์" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:48:16.434798Z", + "start_time": "2018-01-25T08:48:16.312043Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('พระราชินี', 0.7954867482185364),\n", + " ('กษัตริย์', 0.7382755279541016),\n", + " ('พระเจ้า', 0.7046602368354797),\n", + " ('เจ้าชาย', 0.6979373097419739),\n", + " ('พระมหากษัตริย์', 0.6972416639328003),\n", + " ('เจ้าฟ้าหญิง', 0.6871017217636108),\n", + " ('พระเจ้าแผ่นดิน', 0.6827988624572754),\n", + " ('พระพุทธเจ้า', 0.671796977519989),\n", + " ('มกุฎราชกุมาร', 0.6711805462837219),\n", + " ('นายพล', 0.6694187521934509)]" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#word arithmetic\n", + "model.most_similar_cosmul(positive=['พระราชา','ผู้หญิง'], negative=['ผู้ชาย'])" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:48:18.493511Z", + "start_time": "2018-01-25T08:48:18.104736Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAAJCCAYAAADky0LWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XuUnXV97/HPLxdMuCjFBAFRqbfgKUakowRILAGxQQviElGLHlxis8B1rLJcoGCB1h48UGwRBLlUEQUKplEqF0nDtSKXSBAb5ZgiokgknkQuQaIhmeR3/phhTNIkk+Q3M3tCXq+1WGQ/+5m9v/NjEt48z7MfSq01AABsnhGdHgAAYEsmpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaDBqKN9s3LhxdY899hjKtwQA2Cz33Xffb2qt4/vbb0hjao899sjcuXOH8i0BADZLKeWRjdnPaT4AgAZiCgCggZgCAGggpgCAAfXss8/miCOOyN/93d8lSW677bbMmzevw1MNniG9AB0AeP569tln8973vjd77bVXli1bllmzZuXQQw/N5z//+cyYMaPT4w0aR6YAgAFRa82yZcty//33Z+XKlXn00Ufz1a9+Needd1622267To83aByZAgAGxMiRI5Mk48aNyw477JCLLroor3rVqzo81eATUwDAgBg9enRuuOGGvqjaWjjNBwAMmNaQuuqqq3LYYYflwAMPzHvf+9488MADAzTZ4BFTAMCwMGfOnJx00klZsmRJuru7s3Tp0rzvfe/Lb37zm06PtkFO8wEAw8K+++6bRx99NEnS3d2dn/3sZ5k9e3YefPDBjBs3rsPTrZ8jUwDAgHjmmWcyefLkTJkyJQsWLEiS3H777TnzzDPzjW98I1OnTk1XV1dOP/30JMnFF1+cyy+/PEkyY8aMHHDAAZkyZUo+9KEPJUkmTJiQww8/PJ/5zGcyZcqUzJ8/P0kybdq0of/mNsCRKQCgyTPPPJNp06bl6aefTldXV4466qhceOGF2WGHHXL77bdn3rx5efrppzN58uRcdtllmThxYq699trsvvvumTFjRu6888589KMfzV577ZXu7u6sWrUqM2bMyF/+5V/mlFNOycqVKzN27NiMHTs2Dz/8cO6+++4ceOCB+c53vpNtt92209++I1MAQJv7778/++yzTz7wgQ/kuuuuy/nnn5/99tsvK1asyFNPPZX3v//92WWXXXLiiSfmX//1X/Pyl7887373u7Nw4cKMHDkyp556am666abcfvvtmTVrVubOnZuHHnooSc9tFnbZZZfMnj07r3jFK3Lrrbdmjz32yOTJk4fNxeliCgBosnLlylx77bW55ppr8tGPfjTXX399tt9++4wePTqvfvWr841vfCNjx47N2WefnTFjxuTnP/95Lr/88rzqVa/Kf/3Xf2X//ffPWWedlRUrVmT77bfPxIkT+y46nzRpUubOnZtJkyblK1/5Sg4//PD86le/yuWXX56VK1d2+Dvv4TQfANDsuOOOy6RJk3LPPfdk+fLl+exnP5tJkyblIx/5SF760pdmyZIlueiiizJhwoRcc801OeusszJ27NiMHz8+y5cvz4knnpjRo0cnScaMGZPu7u4kyQMPPJDXv/71mTlzZh555JHsvPPO6erqyqRJkzr57a7BkSkAYECsWLEiV111VT75yU9m3333zQ033JBaa9/zc+fOzTbbbJPXv/71GTXqD8dzfvSjH+VP//RP1/majz/+eHbbbbesXLkyf/M3f9N3EfpwIqYAgAFx2WWXZeTIkZk9e3be9ra3Zc8998wFF1yQJCml5Oyzz86+++7bdwrviSeeyLbbbpvly5dnv/32y8UXX/zfXnPHHXfMz3/+84wZMyb//M//nBNPPDELFy4c0u+rP2IKAGh2991359lnn83SpUvzqU99KhdccEHe+MY39j1/11135ZBDDslxxx2XY489NnPmzMkee+yRF77whRk1alRuvvnmXHfddUmSsWPHZunSpUmSnXfeOaNGjcoBBxyQww8/PIsWLco222zTdz+q4cA1UwBAs/nz5+f+++/vu1XBd77znSTJzJkz84tf/CKzZ8/Ohz/84YwYMSJz5szJtGnTct555yVJ3vWud2Xy5Mn58z//8yTJKaeckqOPPjpTp07NC17wgsycOTPbb79933s99thjmTJlSv7qr/5qiL/LdSurn8scbF1dXXXu3LlD9n4AwNC69NJLc8UVV+TMM8/MbrvtlgsvvDBnnHHGJr3G5z73udx666254oorsmzZsnz961/PaaedNkgTr18p5b5aa1d/+znNBwA0u/TSS3PQQQfl4YcfzuOPP55Pf/rT6e7uzuOPP77JrzV//vzst99+WbhwYWbOnJnXvOY1gzDxwBFTAECzWmt++9vfZocddsipp56aJUuW5He/+90an9rbWNOnT8+sWbNywgkn5Gc/+1mOOuqoQZh44LhmCgBoduyxx2bPPffM7Nmz88pXvjJLlizJxz72sU0+xZckkydPzr333tv3+IaHb8j/ueefsmT5oqxasWO2XXpYPvNnR+eIN750IL+FzSamAIABsc8+++Tcc8/N9773vVxxxRUDcmPNGx6+Iad+7/SsqM8mJRmxzVP5/airc8rs7iTHDIugElMAwIAYO3ZsZsyYMaCvee4Pzu0JqdWUEStSdroxZ//7pGERU66ZAgCGrV8v/fU6t5fRT+Wxp34/xNOsm5gCAIatXbbbZZ3b64ods9uOY4d4mnUTUwDAsPXxfT6e0eUFa2yrq0anPnFoTvzzCR2aak2umQIAhq13vPIdSfLfP833Np/mAwDYKO945Tv6omo4cpoPAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoEG/MVVKubSUsqiU8uO1tn+slDK/lPJAKeUfBm9EAIDha2OOTF2WZNrqG0opU5O8M8kbaq1/kuTzAz8aAMDw129M1Vq/m+SJtTYfn+TMWuuzvfssGoTZAACGvc29Zuq1SaaUUuaUUv6jlPKmgRwKAGBLMarh63ZKMinJm5LMKKW8stZa196xlDI9yfQkefnLX765cwIADEube2RqQZJv1R7fT7Iqybh17VhrvaTW2lVr7Ro/fvzmzgkAMCxtbkz9W5KpSVJKeW2SbZL8ZqCGAgDYUvR7mq+UclWSA5OMK6UsSHJ6kkuTXNp7u4TlSY5Z1yk+AIDnu35jqtb6/vU89YEBngUAYIvjDugAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQoN+YKqVcWkpZVEr58Tqe+2QppZZSxg3OeAAAw9vGHJm6LMm0tTeWUl6W5G1JfjnAMwEAbDH6jala63eTPLGOp85JclKSOtBDAQBsKTbrmqlSyjuT/KrW+p8bse/0UsrcUsrcxYsXb87bAQAMW5scU6WUbZOckuS0jdm/1npJrbWr1to1fvz4TX07AIBhbXOOTL0qyR8n+c9Syi+S7J7kB6WUXQZyMACALcGoTf2CWuuPkuz83OPeoOqqtf5mAOcCANgibMytEa5KcneSCaWUBaWUYwd/LACALUO/R6Zqre/v5/k9BmwaAIAtjDugAwA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3E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U045JWPHju3bZ8aMGbnyyivz9NNPZ9y4cXnLW97SwYkBgOFoqz0ydfLJJ+e2227LM888kyS566678olPfKLv+XvvvTef/OQn8+STT2bFihX5/e9/nzPOOKNT4wIAw9RWe2TqvPPO6/v10qVLc++99+bWW2/NihUrMnr06LzpTW/Ko48+miRZuXJlfvGLX+Tmm2/OS17ykk6NDAAMQ6XWOmRv1tXVVefOnbtJX9Pd3Z1Rozat+bq7uzNy5MiUUjbp6wAAnlNKua/W2tXffkN6mu+pp57KPvvsk49//ONJknPPPTennHJKkmTatGlZvHhxpk6dmgMPPDAHHnhgDj744Hz7299Okpx99tl585vfnOdi7Nprr83FF1+cJPnmN7+Zfffdt+9r3/Oe9+TXv/5133tMnjw5++23Xz71qU/1zfKFL3whBx10UPbZZ5++1zn55JNzxx135Pvf/366urry7ne/e435r7766lx22WWDt0AAwBZnSGPqySefzKxZszJ//vwkPdclPfTQQ33P33nnnVm1alUOOeSQnH/++bnlllv6guaXv/xlvvSlL+WKK65IkvzgBz/I6173uiTJzJkz87rXvS7HHHNMrrnmmlxzzTXZdddd88Mf/jB33XVX7rjjjtx999154oknctddd+WRRx7J6aefnhe/+MX5j//4j3z1q1/NfffdlwULFmTy5Mm59tpr86UvfSljx47NokWLhnKJAIAtzJDG1Pjx4/Oud70r8+bNy4oVKzJq1KjssssueeKJJ5IkRxxxRG677bYcdthhmTlzZo4++ug8dxryqaeeykknnZQ3vvGNmTdvXu68886+T9ddddVVueCCC/KSl7wkxx9/fP7lX/4lSfKyl70s559/ft/pvgMOOCCPPvpoHn/88Rx33HGZNm1afvrTn2bPPffMk08+mVJKSin54Ac/mJNOOik333xzVq1aNZRLBABsYYY0prbffvvceeedecMb3pC77747BxxwQA455JDccsstfxhoxIhMnDgxf/u3f5sRI0Zk8eLFSZJ//Md/zO67754vf/nL+cxnPpNLLrlkjdfebrvtcuihh+bKK6/sO3r14he/OOPHj19jv1pr9t577zzyyCOZNWtWbr/99hxzzDF561vf2ndqcMKECbn99tszbdq0wVwOAOB5oGOf5rvpppsyffr07LTTTvn0pz+9zn1G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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = ['ผู้หญิง','พระราชา','ผู้ชาย','พระราชินี']\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:48:50.851735Z", + "start_time": "2018-01-25T08:48:50.731913Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('รองนายกรัฐมนตรี', 1.4945054054260254),\n", + " ('รัฐมนตรี', 1.400755763053894),\n", + " ('ประธานาธิบดี', 1.3626699447631836),\n", + " ('พันเอก', 1.3437265157699585),\n", + " ('ผู้บัญชาการทหารบก', 1.3405414819717407),\n", + " ('ผู้กำกับภาพยนตร์', 1.3339321613311768),\n", + " ('นักฟุตบอล', 1.331659197807312),\n", + " ('เอกอัครราชทูต', 1.3306005001068115),\n", + " ('แห้ง', 1.3243674039840698),\n", + " ('สุภาพสตรี', 1.3231494426727295)]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.most_similar_cosmul(positive=['นายกรัฐมนตรี'],negative=['อำนาจ'])" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:48:51.481402Z", + "start_time": "2018-01-25T08:48:51.158689Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlQAAAJCCAYAAAAGF1mvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XmUnnV9///XJwn7YoSELYIsBQQpCkRlUUnAbwyGEPy2aDkoYMGg1BorQoP9HrRqW4lYESoKHCNUEMoPUVHZBANUhcYREKKNgDRiNJCwBAxLIMzn98cMaUJW8pkt5PE4Z05mrvu653rnM5PJc677mntKrTUAAKy5Qf09AADA2k5QAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQaEhfHmzYsGF1xx137MtDAgCskV/84heP1FqHr86+fRpUO+64Yzo6OvrykAAAa6SU8rvV3ddDfgAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAoz4JqlLKiFLKtffee29mzpzZF4cEAOgzfXWG6r1Jpm677baZOnVqHx0SAKBv9FVQXZHkhDlz5uQDH/hAHx0SAKBv9ElQ1Vpn11rH7rbbbtljjz364pAAAH2mV4OqlDKplPLj7pfb5syZkySZP39+jjrqqIwaNSoHHnhgfvzjHydJpk+fnpEjR+Yv/uIvlno/l19+eS666KIkyd13351DDz00o0aNypgxY/Lggw8mSZ566qn8zd/8TUaPHp3Ro0fngAMOyFVXXdWbfz0AgCS9+Lv8SimHJqm11kO63x70wgsvvHDRRRfl7rvvznHHHZfDDz88jz32WCZMmJBDDjkkV199dc4777ycc845mTt3brbaaqtl3u+kSZNyySWXZMSIEfnpT3+az33uc7ngggty+eWXZ+zYsfnKV76SJFmwYEEOOeSQHHHEERkypE9/ZSEAsI7ptTNUtdabktxXSrm9lHJSrbVz2LBhmT59eiZOnJhx48YlSbbYYotssskmSZL3v//9Oe2003LjjTems7Nzue/3vPPOy4gRI5IkBx10UH7/+98nSU444YQ8/vjjOfDAA9PR0ZFNN900e+65Zx599NHe+isCACTp/WuoPprksCTvTJJSSjo7O/O6170upZRldt59991z8803Z+zYsSt8hy+9BqvWuvj173//+/n2t7+d8847b7m3AwD0ht4OqvWTfD/JtJZ3MnPmzGy++ear3G/cuHH5q7/6q9x3330thwMAeFl6O6ier7W+tdZ67prc+bnnnsu5556bM888M7vtttsq9z/++ONzyy23rPDhQgCA3tDbQfVEKWXfF994+umns+WWW67WHa+44oqMGTMm559/fh544IF89rOfXe2DjhgxIrNmzcrChQtdkA4A9LreDqozknyhlHJzKeWWRx99NB/96EdX647XXXddrrvuuhx33HE54ogjMnLkyNU+6Hvf+94cccQRWbBgQYYNG7aGowMArJ7Slxdtjxw5snZ0dPTZ8QAA1lQp5Re11tU6o9NXv3oGAOAV65UTVHdfkXxpr+TTQ7v+vPuK/p4IAFhHvDKu2L77iuT7H02ef6br7Sd+3/V2kuz9nv6bCwBYJ7wyzlDd9Jn/jakXPf9M13YAgF72ygiqJ2a/vO0AAD3olRFUr3rNy9sOANCDXhlBdegZyXobLb1tvY26tgMA9LJXRlDt/Z5k/DnJq7ZPUrr+HH+OC9IBgD7xyvgpv6QrngQUANAPXhlnqAAA+pGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGi0yqAqpUwtpcwtpcxYYtt/lFLu6n6ZVUq5q3fHBAAYuIasxj4XJfm3JP/+4oZa63tffL2U8sUkT/T4ZAAAa4lVBlWt9dZSyo7Lu62UUpK8J8khPTsWAMDao/UaqrclebjWel9PDAMAsDZqDaqjk1y2sh1KKRNLKR2llI558+Y1Hg4AYOBZ46AqpQxJ8n+T/MfK9qu1XlBrHVlrHTl8+PA1PRwAwIDVcobqHUlm1lpn99QwAABro9V52oTLktyWZPdSyuxSygndN/1VVvFwHwDAumB1fsrv6BVsP77HpwEAWAt5pnQAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGq0yqEopU0spc0spM16y/W9LKTNLKb8qpUzpvREBAAa21TlDdVGSsUtuKKWMTjIhyRtqra9PclbPjwYAsHZYZVDVWm9N8thLNn84yedrrQu795nbC7MBAKwV1vQaqt2SvK2U8l+llFtKKW/qyaEAANYmQxrut0WS/ZO8KckVpZSda631pTuWUiYmmZgkO+yww5rOCQAwYK3pGarZSa6qXaYn6UwybHk71lovqLWOrLWOHD58+JrOCQAwYK1pUH03yegkKaXslmT9JI/01FAAAGuTVT7kV0q5LMmoJMNKKbOTfCrJ1CRTu59K4bkkxy3v4T4AgHXBKoOq1nr0Cm56Xw/PAgCwVvJM6QAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI1WGVSllKmllLmllBlLbPt0KeUPpZS7ul/e1btjAgAMXKtzhuqiJGOXs/1LtdY3dr9c07NjAQCsPVYZVLXWW5M81gezAACslVquofpIKeXu7ocEX72inUopE0spHaWUjnnz5jUcDgBgYFrToPpqkl2SvDHJnCRfXNGOtdYLaq0ja60jhw8fvoaHAwAYuNYoqGqtD9daX6i1dia5MMmbe3YsAIC1xxoFVSll2yXefHeSGSvaFwDglW7IqnYopVyWZFSSYaWU2Uk+lWRUKeWNSWqSWUlO6sUZAQAGtFUGVa316OVs/novzAIAsFbyTOkAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANBJUAACNBBUAQCNBBQDQSFABADQSVAAAjQQVAEAjQQUA0EhQAQA0ElQAAI0EFQBAI0EFANBIUAEANFplUJVSppZS5pZSZizntlNKKbWUMqx3xgMAGPhW5wzVRUnGvnRjKWX7JGOSPNjDMwEArFVWGVS11luTPLacm76U5LQktaeHAgBYm6zRNVSllAlJ/lBr/eVq7DuxlNJRSumYN2/emhwOAGBAe9lBVUrZOMknk5yxOvvXWi+otY6stY4cPnz4yz0cAMCAtyZnqHZJslOSX5ZSZiV5TZI7Sinb9ORgAABriyEv9w611nuSbPXi291RNbLW+kgPzgUAsNZYnadNuCzJbUl2L6XMLqWc0PtjAQCsPVZ5hqrWevQqbt+xx6YBAFgLeaZ0AIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABqtMqhKKVNLKXNLKTOW2PbZUsrdpZS7Sik3lFK2690xAQAGrtU5Q3VRkrEv2faFWuvetdY3JvlBkjN6ejAAgLXFKoOq1nprksdesu3JJd7cJEnt4bkAANYaQ9b0jqWUf0pybJInkozusYkAANYya3xReq31H2qt2ye5NMlHVrRfKWViKaWjlNIxb968NT0cAMCA1RM/5Xdpkr9Y0Y211gtqrSNrrSOHDx/eA4cDABhY1iioSim7LvHmhCQze2YcAIC1zyqvoSqlXJZkVJJhpZTZST6V5F2llN2TdCb5XZIP9eaQAAAD2SqDqtZ69HI2f70XZgEAWCt5pnQAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAAAaCSoAgEaCCgCgkaACAGgkqAAAGq0yqEopU0spc0spM5bY9oVSysxSyt2llO+UUob27pgAAAPX6pyhuijJ2Jds+1GSvWqteye5N8npPTwXAMBaY5VBVWu9NcljL9l2Q611Ufebtyd5TS/MBgCwVuiJa6j+Osm1PfB+AADWSk1BVUr5hySLkly6kn0mllI6Sikd8+bNazkcAMCAtMZBVUo5PsnhSY6ptdYV7VdrvaDWOrLWOnL48OFrejgAgAFryJrcqZQyNslpSQ6utT7dsyMBAKxdVudpEy5LcluS3Usps0spJyT5tySbJflRKeWuUsrXenlOAIABa5VnqGqtRy9n89d7YRYAgLWSZ0oHAGgkqAAAGgkqAIBGggoAoJGgAgBoJKgAABoJKgCARoIKAKCRoAIAaCSoAIAB65FHHskLL7zQ32OskqACAAasT3ziE5k3b95S2+bPn5+FCxf200TLJ6gAYB3V2dmZE044IYccckh+85vfJEl+8IMf5Morr+yXeZ5++umcdtppGTNmTA499NCcfvrpeeqpp5bZ7+yzz86dd97ZDxOu2Cp/OTIA8Mq0YMGCPPDAA9lyyy3zxz/+MZ2dnfniF7+YvfbaK+ecc07+5V/+JQcddFDuuuuu3HzzzfnYxz7Wq/N88pOfzC233JKNN94466+/fn7+85/nlltuyS677JI777wzzz33XPbcc8+UUnp1jjVRaq19drCRI0fWjo6OPjseALBy11xzTb761a/mqaeeys4775zJkydn4sSJ2XHHHTNq1KiMHj06H/zgB3PWWWdlr7326rO5nnnmmdxxxx35x3/8x8yaNStbbbVVhgwZkg033DD/+Z//mZtuuin7779/r85QSvlFrXXkau0rqACAJFm0aFGGDBmS22+/PWeddVYeffTRbLvttjn11FOzzz779Nhxnn/++Tz55JPZcsst89BDD2WrrbbKoEHLvwpp0aJFGTx4cEopWbhwYX71q1/l+uuvz/jx43s98F5OULmGCgB6yaJFi1Zrv6uvvjr77rtvPvKRjyy1/fOf/3xuvvnmTJs2LW9/+9tz8MEHZ8KECXniiSeSJE8++WTGjh2bt7/97bn55puTJB/60Icya9asxcefPHlyDj300Lz1rW/N8ccfnyeffDJJMm/evIwePTqjRo3KqFGjcuihh+Z73/ve4mM/+eSTKaVk9uzZ+cQnPpGvf/3reeaZZzJ27Ni8+c1vzoMPPrjMnPPnz8/BBx+cAw88MHPmzFl8+0MPPZTjjz8+SdeZp8MPPzwf+MAHMnXq1Hzwgx/MuHHjsmjRojz88MP59re/nX333TcHH3xwRo0alaOOOioPPfRQkmSDDTbIvvvum9NOOy177rnn6n8g+oAzVADQA+bNm5f3vOc9efH/1cGDB+fkk0/OG97whpx++ul5/PHHs2jRomy88cY566yzlgqCgw8+OI899lgef/zxzJ49O9OnT8/JJ5+cZ599Nl/+8pfzyU9+Mj/60Y9yzTXXZNq0aXnta1+bww8/PMccc0wefvjhvPDCC/n3f//3jBs3LhMnTszs2bPz9NNPZ+jQoZk4cWLuvvvu7L///nnggQdyxx13ZKeddspFF12UBx98MK95zWty7rnn5pBDDsmzzz6bo446KtOmTcsmm2ySLbbYIscee2xOP/303HvvvTnhhBMyZ86cDB48OIMGDcqxxx6byZMn541vfGOeeeaZfOxjH8uCBQuyxRZb5J577sk+++yT973vfTnssMNy5513Ztq0abntttuy6aabZsKECdlvv/0yY8aMfPazn81NN92UV7/61Zk7d27mzJmTDTfcMDfeeGN22GGH/OQnP8kpp5ySjTfeOLXWbLLJJpkyZUpe//rX9+rH9OWcoXJROgD0gJ/+9Kfp7OzMmDFjMmHChMUPR334wx/O2WefnREjRiRJ7rvvvhxzzDGZPn364vtuuOGG2XDDDRc/PcDVV1+d8847LyeddFIeffTRfOtb38rmm2+eJNl1113z29/+NpMmTco///M/59prr80xxxyTiy++OOPGjcsjjzyS559/Puuvv34GDRqU733vexk2bFiS5K//+q8zZcqUfPzjH88999yTzs7OXHjhhTn55JOz3377ZdKkSZk3b14+8pGPZLfddsuzzz6bG264Ie973/vypz/9KUOHDs3ChQvzyCOP5Iwzzsjxxx+fRx55JBtttFGOPfbYPPTQQ5kxY0Z+/etfZ8yYMUmSWbNmZcSIESml5Nprr82sWbNyyimn5JprrslDDz2UadOmZf3118/mm2+e73znOznnnHNyzDHHZMqUKXn3u9+dU045Jb/85S+z/fbb59BDD82RRx6Zbbfdts8+rqvLQ34A0AOOPPLITJs2LePHj8+VV16ZY445JrXWnHPOOfn4xz+ed73rXXnkkUey66675s/+7M8yd+7cxfc944wzst566y1++/3vf39OO+203H///RkyZEh22WWXpY5Va815552X8ePHZ+7cufnbv/3bxQ/5bbLJJiml5Lrrrsupp566eNuLOjs709HRkZkzZ2bQoEE56aSTMmLEiAwaNCg77rhjbr/99my55Zb5p3/6p1x44YX51re+le222y5///d/n8985jM56aSTss022+Tss8/O448/nmHDhmXw4MH56le/mkGDBuWqq67K5MmTFx9vl112yXPPPZeOjo50dnbm1a9+dZ544olceeWVedOb3pQf/vCHefDBB7PddtvltttuyxVXXJEbbrghJ554Yg444IBccsklOfPMM3PppZdmjz32yBlnnJEpU6b0xoewiaACgB4yaNCg7L333vn0pz+dQYMGZd68eeno6MiIESNy4okn5rrrrkuSrL/++uns7Mwf//jHPPHEEznooIPys5/9LJtttlmSZPfdd8/NN9+crbfeOptuuulyj7XHHnvkt7/9bTbddNPccccd2XnnnZN0xdNrX/va7LXXXvm7v/u7vP/971/qgu9tttkm8+fPzw477LB423rrrZfBgwens7MzSbL11ltn1113zZ/+9KfMmDEjG2+8cTo6OnLKKafk0UcfzUc/+tHsvffe+dGPfpQkGT9+fD7+8Y8vd85SSiZOnJhRo0YlSd761rfm5z//eSZNmpSf/vSnee9735vNNtsszz77bK688spcccUVue2227LRRhtl0aJFi2faYIMNMmrUqFx44YW56aab1vRD1GsEFQD0ghcDZeHChfnOd76T888/f/HDYC9auHBhTjzxxCxYsGCp7QsWLMinPvWp/O53v8t22223ePvMmTOXCqzf//73ed3rXrfUfZ9//vncf//9mTFjRsaOHZshQ5a+umf+/Pk54ogjsvHGGydJ7r///kyfPj3XXnvt4n2OPfbYxfH3YtB0dnZmgw02yBe/+MX8v//3/3Lvvfcu8wzmy3Pttdfm2GOPzfbbb58kOeigg9LR0ZHvf//72X333XPAAQfkz//8zzN79uycfPLJOfzwwzN69Ohceuml+e53v7vc9zkQn4dKUAFAD7r//vszevTopQLlpJNOyvXXX5+tttpqqX132mmnfPrTn84HPvCBPPvss0mSr3zlKznyyCNzww03ZPz48ZkyZUqee+65nHvuuTnzzDOz0047Lb7/tttum46OjsUXwi9atCh33nlndt555xU+DUGtdanIuuSSS7LHHnvkbW97WwYPHpyk6/fnHXbYYZk9e3aSrp/4O/TQQ/PNb34z6623Xm666abMnTs33/rWt/KhD30o1113XaZMmZKf/OQni59xfdasWTnrrLNy6qmn5vLLL88dd9yRzs7ObL755rnqqqty8cUX5x3veEeS5LWvfW0ee+yxdHR05Oijj85RRx2VW265Je9617uy/vrrL571e9/7Xg444IA8/PDDa/bB6UWCCgB60CWXXJIvfelLiwNl6623zu233744ep5//vnMnDkzr3rVq5Ikr3/963PaaafluOOOywsvvJC77ror119/ffbff//ceuutKaVkzJgxOf/88/PAAw/k3HPPXXys3XffPSNHjsyBBx6Y6dOn521ve1tOOOGEzJw5M88//3ySroDq6OjI1ltvvdx5x48fnxkzZmTRokUZPnx4kq5fP3PSSSdl5MiROfHEE/PAAw/k9a9/fbbccsssWrQoEyZMyKhRozJ58uS8+93vzm233ZYLLrggc+bMyZe+9KV87Wtfy09+8pMcf/zx+bd/+7dMmjQpQ4YMyYMPPpgJEybk6aefzr/+679m/vz5i59e4fHHH88vfvGLnH766UmSPffcM1dffXX+8i//cvGsF198cW699dYMHTq0hz9qPaDW2mcv++23XwWAV7KOjo76pje9qU6YMGHxts9+9rP1LW95Sx01alTdf//96wUXXLDM/aZNm1aHDh261LbjjjuuHnbYYfWZZ56pU6ZMqSNHjqxTpkxZ7nHf+c53Ln596tSp9YADDlh8vM997nOLb/vGN75RL7vsshXet9ZaZ82aVQ888MB68MEH16effnqp26ZOnVr322+/Onr06Prkk0/WWmudNGlS3WefferZZ59da6315z//ed15553rN77xjaX+fltssUW944476q9//ev6lre8pb7jHe+ozz77bK211n333bc+9dRTi/f/n//5n3rSSSctdezzzz+/7rfffkv9fXpTko66mo3jeagAgGVcd911ee655/Lb3/42N954Yy688MKlrudaF3geKgBgjXzta1/Ld7/73dx111352c9+lvvuuy/3339/7r333syZMyd33XVXNtpoo3zzm9/M5z//+bzhDW/o0eN/984/5AvX/yZ/nP9Mthu6UU595+45cp8RPXqM3uAaKgBgsdmzZ2fhwoWLnwR0s802ywsvvJDJkydn3Lhxed3rXpfO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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = ['นายกรัฐมนตรี','อำนาจ','รองนายกรัฐมนตรี']\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:49:11.465639Z", + "start_time": "2018-01-25T08:49:11.336707Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('สิ่งมีชีวิต', 0.537461519241333),\n", + " ('สัตว์เลี้ยงลูกด้วยนม', 0.5080005526542664),\n", + " ('แมลง', 0.5048903226852417),\n", + " ('ผลไม้', 0.4839756190776825),\n", + " ('มนุษย์', 0.47641509771347046),\n", + " ('ผัก', 0.46431201696395874),\n", + " ('สัตว์น้ำ', 0.45941096544265747),\n", + " ('ต้นไม้', 0.45185261964797974),\n", + " ('พันธุ์ไม้', 0.4504697620868683),\n", + " ('ไม้ยืนต้น', 0.44425833225250244)]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#word arithmetic\n", + "model.most_similar_cosmul(positive=['สัตว์','พืช'], negative=[])" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:49:12.202620Z", + "start_time": "2018-01-25T08:49:11.835817Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAAJCCAYAAADky0LWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAHoRJREFUeJzt3X+UX3V95/HXJ5loAkFQE6BozqJ0iz24EDASIBD5ZaBIsbCK4qlHFA3grqXUHyV2z8IutsXibpLWirDlh3X5FUAqiigEJIjEkAnGUAWMuiAhQAKYwAlBwuSzfyRECQk/8pmZb2bm8TgnZ+Z77/3OfX/vmZM8c7937pRaawAA2DLDOj0AAMBAJqYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGjQ1Z87GzNmTN111137c5cAAFtkwYIFj9Vax77cdv0aU7vuumu6u7v7c5cAAFuklPLAK9nO23wAAA3EFABAAzEFALysNWvW5NFHH+30GFslMQUAvKyHHnooZ555ZqfH2CqJKQCABmIKAHhZu+66a7761a++6uc988wzWbly5WbXP/bYY+np6WkZrePEFADQZ370ox/lvPPO2+z6z3zmM1m+fHk/TtT7+vU+UwDAwHHjjTfmvPPOy4oVK/K6170un/vc5zJp0qSXfM6sWbNy6aWX5sknn8yYMWMyefLkDeuefvrpnHXWWVm4cGF6enqy7777ZtWqVUmSxYsX5wtf+EKWLFmSJPnwhz+cE088sc9eW29yZgoAeJElS5bkxBNPzOOPP55nn302PT09+cQnPpF77713s8+ZP39+Pv3pT+c3v/lN1qxZk9WrV+dv//ZvN6z//Oc/n5tuuimrVq3K2rVrM3/+/Hzzm99Mknzwgx/M4sWLs3r16nR1deXLX/5y/vVf/7XPX2dvcGYKAHiRN7/5zVm6dGmSZO3atXnwwQdz00035Re/+EXe9ra3bfI573znO/Pggw8mSXp6enL//fdn9uzZ2WmnnZIkM2bM2LDt6tWrc9ddd+V73/teSilZsGDBhnWPPfZYbrvttjz88MN99fJ6Vam19tvOJkyYUP06GQAYuC677LJ86EMf6vf91lqzbNmy7LTTTlm+fHm23377vOY1r+nTfZZSFtRaJ7zcds5MAQAvUmvN9OnT8+1vfzullIwcOTK77757dttttyTJihUrcvTRR+e5557LNddck1122SUnnHBCFi9enAsuuCDveMc7kiRXXHFFnnnmmZx44omZMWNGrrvuuqxYsSInn3xyTj755EybNi1HHXVUJk6cmE996lO59957M3z48IwbNy7//M//nNGjR2ft2rU5/vjj89vf/jbHHntsvvnNb+aJJ57Id77znWy33XadPExJXDMFAGzCjTfemNGjR+eWW27J7Nmz8773vS8///nPM27cuCRJd3d3jj766Hz84x/PHXfckccffzxveMMb8sUvfjHXX3/9i77eAw88kDPPPDNvfOMbM2fOnFx88cVZsGBBlixZkgMPPDAzZszIxIkTM2fOnNxyyy35wAc+kLPPPjtJMnv27Oyzzz659tprs2LFilx66aX5+Mc/nq9//ev9ekw2R0wBAC9yxBFH5LjjjstJJ52U/fbbLzNmzMjkyZOzcOHCJMmkSZMyb968nHvuuenp6cmYMWMyYsSIfOYzn8natWtf9PUef/zxnHLKKTnyyCOzePHivO1tb8tvfvOblFJSSslpp52Wj33sYy/Y/913350kWbhwYSZOnJi5c+dm1qxZufbaa7Pvvvvmnnvu6Z+D8TLEFACwSaecckqmTp2aefPmZc6cObnjjjuydu3a3HPPPRk1alSuvfbaTJs2bcP2M2fO3OyNPcePH58HHngg3/3ud3PrrbfmIx/5SA4//PA88sgjSZLXvva1L9h++PDhG6Ls9a9/fVauXJmrr746s2bNyty5czNq1KisWbOmj175qyOmAIBNWrVqVSZOnJgk2WGHHXL66advuJbq9ttvf1Vfa9iwYbniiity1VVX5eabb87BBx+8YfnLOfDAAzN//vx88pOfzNFHH51DDjnkVb+WviSmAIBNmjdvXvbff//84Ac/SLLu7FEpJV/5yldy3nnnZf78+S/Y/ktf+lJOOumk3H777bnvvvs2+3V7enpSStns+q985Ss54IADNjz+4z/+4/zqV79Kd3d3TjjhhLz//e9vfGW9S0wBAJs0fvz4XHXVVTn//PNfsLyrqysXXnhhzjnnnCxatGjD8jlz5mTBggV5+OGHM3369HzoQx/acEfz3zdixIg8+eSTSdb97r6Nfec738kNN9yQESNGbFh2//33Z8GCBS94W3FrIaYAgE3aY489cswxx+T4449/0bqRI0fmkksuecHbfbvttlsOOOCATJ06NV/96lfzV3/1V5v8vXynnnpqDj/88BxwwAE56qijXrR+/PjxOeSQQ16w3+eeey5f+MIXeumV9S437QQA2IRXetNOZ6YAgAHh+l9dnylXT8meX9szU66ekut/9eL7WXWCO6ADAFu96391fc6646w807PuGquHVz2cs+44K0nynre+p4OTOTMFAAwAM++auSGknvdMzzOZedfMDk30O2IKANjqPbLqkVe1vD+JKQBgq7fztju/quX9SUwBAFu90/Y5LSOHj3zBspHDR+a0fU7r0ES/4wJ0AGCr9/xF5jPvmplHVj2SnbfdOaftc1rHLz5PxBQAMEC8563v2SriaWPe5gMAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaCCmAAAaiCkAgAZiCgCggZgCAGggpgAAGogpAIAGYgoAoIGYAgBoIKYAABqIKQCABmIKAKCBmAIAaPCyMVVKuaiUsqyU8u+/t+wNpZSbSimL1398fd+OCQCwdXolZ6YuSXLkRsvOSHJzrfU/Jrl5/WMAgCHnZWOq1npbkic2WvzeJF9b//nXkvxZL88FADAgbOk1UzvVWh9e//kjSXba3IallKmllO5SSvfy5cu3cHcAAFun5gvQa601SX2J9RfUWifUWieMHTu2dXcAAFuVLY2pR0spf5Ak6z8u672RAAAGji2NqeuSfGT95x9J8s3eGQcAYGB5JbdGuDzJ3CS7l1KWlFJOSnJOkneXUhYnOXz9YwCAIafr5TaotZ6wmVWH9fIsAAADjjugAwA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQIOmmCqlnF5K+Wkp5d9LKZeXUkb21mAAAAPBFsdUKeVNSf4iyYRa69uTDE/ywd4aDABgIGh9m68ryahSSleSbZIsbR8JAGDg2OKYqrU+lORLSX6d5OEkK2utN268XSllaimlu5TSvXz58i2fFABgK9TyNt/rk7w3yVuS7JJk21LKn2+8Xa31glrrhFrrhLFjx275pAAAW6GWt/kOT/L/aq3La61rknwjyQG9MxYAwMDQElO/TrJfKWWbUkpJcliSe3pnLACAgaHlmql5Sa5OcleSu9d/rQt6aS4AgAGhq+XJtdYzk5zZS7MAAAw47oAOANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADZpiqpSyQynl6lLKvaWUe0op+/fWYAAAA0FX4/NnJvlurfV9pZTXJNmmF2YCABgwtjimSinbJ5mc5MQkqbU+m+TZ3hkLAGBgaHmb7y1Jlie5uJTy41LKv5RStt14o1LK1FJKdymle/ny5Q27AwDY+rTEVFeSfZKcV2vdO8mqJGdsvFGt9YJa64Ra64SxY8c27A4AYOvTElNLkiyptc5b//jqrIsrAIAhY4tjqtb6SJIHSym7r190WJKf9cpUAAADROtP830qyaXrf5LvV0k+2j4SAMDA0RRTtdaFSSb00iwAAAOOO6ADADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAg+aYKqUML6X8uJTy7d4YCABgIOmNM1OnJbmnF74OAMCA0xRTpZQ3J3lPkn/pnXEAAAaW1jNTM5J8LsnazW1QSplaSukupXQvX768cXcAAFuXLY6pUsrRSZbVWhe81Ha11gtqrRNqrRPGjh27pbsDANgqtZyZmpTkmFLK/UmuSHJoKeX/9spUAAADxBbHVK11Wq31zbXWXZN8MMkttdY/77XJAAAGAPeZAgBo0NUbX6TWemuSW3vjawEADCTOTAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANxBQAQAMxBQDQQEwBADQQUwAADcQUAEADMQUA0EBMAQA0EFMAAA3EFABAAzEFANBATAEANBBTAAANBmRMzZ07N93d3TnnnHM6PQoAMMR1dXqAV2rlypU577zzsmzZsvz0pz/NO97xjvzoRz/KGWec0enRAIAhbMDE1NSpU/PrX/86w4YNy+jRo7Nw4cLceeednR4LABjiBkxMXXnllRs+f+qppzJv3rzsueeeee6559LVNWBeBgAwyJRaa7/tbMKECbW7u7vf9gcAsKVKKQtqrRNebrsBcQH6ddddl3322SennXZakmTmzJn5/Oc/nyQ58sgjs2TJkhxzzDF517velcMOOyzLli3L008/nSlTpnRybABgCBgQ74/NmjUr3/3ud/PhD384STJ//vw8++yzG9afeeaZ+cUvfpEvfvGLWbp0aa688sosXrw406ZN69TIAMAQMSDOTJ166qk59thjs2jRoqxZsyZdXV3Zeeed88QTTyRJnnjiicybNy+33nprVq1alfHjx+fRRx/N6NGjOzw5ADDYDYiYmjRpUn74wx9mr732yty5czNp0qS8+93vzs0335wk+eQnP5kpU6Zk//33z/z583PQQQflE5/4RG699dbODg4ADHoDIqZ+30033ZQjjzwyhx56aG677bYkybvf/e7MnTs3u+yyS/bYY48kSVdXV3p6ejo5KgAwBAyIa6aeN2zYsCxdujTjxo1LkjzzzDMppWxY/+yzz7pNAgDQrwbUmanhw4dnzJgxGx7vvvvuWbly5YbH22yzTR577LEk666j2nbbbft9RgBgaBlQMfXUU0/l0EMP3fD4yCOP3HARepLss88++eUvf5mDDz44M2fOzHHHHdeJMQGAIcRNOwEANmFQ3bTzFVk0K5n+9uSsHdZ9XDSr0xMBAEPA4Lhae9Gs5Ft/kaxZve7xygfXPU6SPY/v3FwAwKA3OM5M3fw/fxdS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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = ['สัตว์','พืช','สิ่งมีชีวิต']\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "## Doesn't Match" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "It can also be used to do word groupings. For instance:\n", + "* อาหารเช้า อาหารสัตว์ อาหารเย็น อาหารกลางวัน - อาหารสัตว์ is type of food whereas others are meals in the day\n", + "* ลาก ดึง ดูด ดัน - ดัน is pushing while the rest is pulling.\n", + "* กด กัด กิน เคี้ยว - กด is not verbs for the eating process\n", + "Note that this could be relying on a different \"take\" than you would expect. For example, you could have answered ลูกเขย in the second example because it is the one associated with male gender." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-26T02:35:24.619900Z", + "start_time": "2018-01-26T02:35:24.505717Z" + }, + "hidden": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.6/dist-packages/gensim/models/keyedvectors.py:858: FutureWarning: arrays to stack must be passed as a \"sequence\" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.\n", + " vectors = vstack(self.word_vec(word, use_norm=True) for word in used_words).astype(REAL)\n" + ] + }, + { + "data": { + "text/plain": [ + "'อาหารสัตว์'" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.doesnt_match(\"อาหารเช้า อาหารสัตว์ อาหารเย็น อาหารกลางวัน\".split())" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-26T02:35:46.163075Z", + "start_time": "2018-01-26T02:35:45.838017Z" + }, + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlwAAAJCCAYAAAAVwBlbAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XuUnXV99/3PLwfAsioIogGR03NTQFkD4lQFEsgBIRoCiIVqUwF9QjhYIIqiLFpNxVaoBwgiFnqL+hRr5EYRATkKqchBGoQAalBOIhBkQIk3h5DT7/kjwwgaSIbxlz3JvF5rzcrsa1+H71yOy7fXvvaeUmsNAADtDOv0AAAAazvBBQDQmOACAGhMcAEANCa4AAAaE1wAAI0JLgCAxgQXAEBjggsAoLERnR7g+V796lfXrbbaqtNjAACs1C233PJYrXWTVVl3UAXXVlttlTlz5nR6DACAlSql/GpV1/WSIgBAY4ILAKAxwQUArNXuuuuufP/73+/oDIILAFgr/exnP8sRRxyRK6+8MuPHj+/oLIILAFgrnXnmmUmS0aNHZ7311uvoLIILAFgr7bDDDrnrrruyySar9MkNTQkuAGBQuvPOO7PXXntl6tSpfcsOP/zwLF68eJW2P+aYYzJ79uxsvvnmrUZcZYILABiUfvjDH+aNb3xj7rvvvixatCj/+Z//mSVLlmTkyJGdHq3fBBcAMChNnTo1G264YZYtW5b99tsvDz/8cP793/+902O9LIPqk+YBgKFryZIlGTHiD2myzjrr5J//+Z+TJDfccEM23XTTrLvuukmSRx55JKNGjcrChQvz9NNPZ6ONNurIzKtKcAEASZKZM2fmoosuSpI888wz2W+//XLiiSfmiSeeyOGHH56enp4sWrQon/70pzN+/PjcfPPNOfroo7PNNtvk/PPPT5Kce+65OfPMM/O3f/u3+djHPpYHHnggRx55ZJ5++unUWnPGGWdkp512Sk9PTw4++ODUWpMkw4cPz9FHH513v/vdueuuu3LSSSfld7/7XUaMGJEtt9wyPT09+cY3vpEkOfXUU3PNNddk7Nixue222/LQQw/lS1/6UnbaaacsWLCgb9Zaa3beeed8/vOfz/DhwztzUp9Tax00X29+85srALD6XX311XXmzJl9j5cuXVqPP/74+tWvfrVOnz69XnLJJbXWWh9//PE6evToWmutJ510Uv3xj39cp0yZUh999NFaa6377rtvXbhwYT3wwANrrbW++93vrnPnzq211nrPPffUSZMm1VprvfDCC+see+xRP/3pT9c77rjjBbN88IMfrPPnz6+11vrAAw/Uo48+uk6ePLnWWuuCBQv6vj/vvPPqvHnz6v33318POuigWmutRx11VL366qv79vWlL32pnnXWWX/GM/UHSebUVWwc93ABAJkwYUK23XbbvO1tb8vZZ5+dYcOGZdq0abn55ptzxBFHZNKkSUmSjTbaKOuvv36S5H3ve19OOOGEXH311Vm6dGmSZLvttsuoUaMybty4JMnJJ5+crq6uJMk222yTJUuWJEkOOOCAXHvttZk8eXIuuOCCTJkype9q15lnnpnrrrsuEyZMyO6775711lsvv//975Mk8+bNy0477ZRHH3005557br785S9nyy23zOOPP54k+cIXvpAJEyb0/Vz77LNP7rjjjtanb6UEFwCQJDnjjDNy2WWX5Yorrkiy/B6qZcuWZfvtt1/h+tttt11mz56diRMnJlkeQz09PZk1a1aeeeaZJMs/C+vFDBs2LF1dXZkxY0aGDRuWnp6eJMmNN96YSy65JJdeemkeeOCB7LXXXvnxj3+cJHnVq16VBQsW5Prrr8+hhx6axYsXp9ba987FP/6A0+HDh2fZsmUDOCt/HoILAEiSLFq0KJMnT+67OtVfJ598ck499dRssMEGeeqpp/q17fPDaPbs2Zk6dWpfPL3jHe/I2972tiTJtttum1//+tfZe++9853vfCfDhg1LKeVlzbs6CS4AIEkycuTI/OhHP8oxxxzT721nz56drq6ujBo1ql/b3X333Rk3blwuu+yyvmXPPvtsjjnmmBx22GF9LzM+9+7EZPlVrLvuuisbbbRRPve5z73ovv/xH/8xf/M3f9PPn6QNwQUAJEk22GCD/OQnP+l7fOutt2bjjTdepW2/9a1vZfr06f0+5nnnnZfTTjstY8aM6Xsn4YgRI/KFL3whI0aMyD333LPCOU866aScddZZLwix51u8eHF++tOf5mtf+1rn36EYHwsBAPT61Kc+laOPPjpLly5NrTV/+Zd/ma985SurtO0hhxzyovHzUiZPnpxp06Zls8026/ubh/vvv3+mTp2aV7/61dlqq61WuN3HP/7xl/yD1CNH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3bcuXLiwHnjggbXWWt/97nfXuXPn1lprveeee+qkSZNqrbVeeOGFdY899qif/vSn6x133PGCWb7//e/Xf/zHf6xLly6ttdY6d+7c+ta3vrXWWuv8+fPrYYcdVp988sm+9b/zne/UE088sdZa6+mnn17PPPPMWmutzzzzTH3LW95SFy9e3LfulClT6vz58+vb3/72Wmutp556av3KV77S9/yll15aTzjhhFprrRMnTqyLFi2qe++99wvmO+KII+p9993Xj7MLAJ2VZE5dxcZxhauhCRMmZNttt83b3va2nH322Rk2bFimTZuWm2++OUcccUQmTZqUJNloo42y/vrrJ0ne97735YQTTsjVV1+dpUuXJkm22267jBo1KuPGjUuy/N6orq6uJMk222yTJUuWJEkOOOCAXHvttZk8eXIuuOCCTJkyJct/H5ZfFfvNb36TG264IUnS1dWVrbbaKo899lhGjRqV//iP/8hnPvOZjBs3Lvvuu28WLFiQ2267LUmy3377ZerUqUmS9dZbLzvssEMef/zxvp/zqKOOyoEHHpjbb789SXLccce94F6tffbZJ3fccUeS5PDDD88ee+yRRx999M99ugFg0BJcjZ1xxhm57LLLcsUVVyRJ1llnnSxbtizbb7/9CtffbrvtMnv27EycODFJMm/evPT09GTWrFl55plnkiQ77LDDix5v2LBh6erqyowZMzJs2LD09PQkSd773vfmoYceyhve8Ia+dTfccMO+l/pOOeWUbL311rn22mtz0UUX5bHHHsvTTz+dJNl6662z7rrrvuA4tdY8/PDDWbBgQXbffffccMMN2XnnnZPkT9YdPnx4li1bliQ58MADc+ONN+a1r33tKpw9AFg7CK7GFi1alMmTJ/ddneqvk08+Oaeeemo22GCDPPXUU/3a9vmhM3fu3Oy6667ZaKONVrjujTfe2HdVavjw4fnQhz6UddZZ5yX3/+yzz2bq1Kl90TYQ8+bNyytf+coB7wcABiPB1djIkSPzox/9KMccc0y/t509e3a6uroyatSofm139913Z9y4cbnsssv6li1duvQl3624cOHC7L777vniF7+YZHl0DRv20r8eW2+9dWbMmJH3v//9Wbhw4QrXOeuss7Lbbru96D4ee+yxHHXUUbn//vuz3nrrveTxAGBNJbga22CDDfKTn/yk7/Gtt96ajTfeeJW2/da3vpXp06f3+5jnnXdeTjvttIwZMybDhw9fpW3WXXfd/OAHP8i3v/3tfh3rjW98Y0444YQceuihfe9qfL7vf//7ueyyyzJy5MgXLF+6dGlmzJiR9773vXnwwQfz9a9/PTNnzuzXsQFgTSG4GvvUpz6Vj370o30f4fCVr3wlxx577Cpte8ghh/zJ/VCrYvLkyZk2bVqWLFmSTTbZZJW2OfjggzN69OiXvBr1Yv76r/86Rx11VG699dY/eW7nnXfOuHHjXvAxF0nyy1/+MsOGDctVV12V9ddfP8cff3x23XXXfh8bANYE5bl3sQ0G3d3ddc6cOZ0eAwBgpUopt9Rau1dlXVe4AAAaE1ysdgsuvji/HD8hP9/hDfnl+AlZcPHFnR4JAJrytxRZrRZcfHHm/9MnUnvf1bjk4Ycz/58+kSTZYPLkTo4GAM24wsVq9ehpp/fF1nPqwoV59LTTOzQRALQnuFitlsyf36/lALA2EFysViM23bRfywFgbSC4WK1e86HpKX/0ifJlvfXymg/1/wNeAWBN4aZ5Vqvnbox/9LTTs2T+/IzYdNO85kPT3TAPwFpNcLHabTB5ssACYEjxkiIAQGOCCwCgMcEFANCY4AIAaExwAQA0JrgAABoTXAAAjQkuAIDGBBcAQGOCCwCgMcEFANCY4AIAaExwAQA0JrgAABoTXAAAjQkuAIDGBBcAQGOCCwCgMcEFANCY4AIAaExwAQA0JrgAABoTXAAAjQkuAIDGBBcAQGOCCwCgMcEFANCY4AIAaExwAQA0JrgAABoTXAAAjQkuAIDGBBcAQGOCCwCgMcEFANCY4AIAaExwAQA0JrgAABoTXAAAjQ0ouEopB5VSflpKWVZK6X7e8q1KKc+UUm7r/fr3gY8KALBmGjHA7e9McmCSs1fw3D211p0HuH8AgDXegIKr1vrzJCml/HmmAQBYC7W8h2vrUsqtpZT/LqWMaXgcAIBBbaVXuEopVycZtYKnTqq1XvQim81PskWt9fFSypuTfLeU8sZa6+9XsP9pSaYlyRZbbLHqkwMArCFWGly11r36u9Na67NJnu39/pZSyj1J/irJnBWse06Sc5Kku7u79vdYAACDXZOXFEspm5RShvd+v02SbZPc2+JYAACD3UA/FuJdpZQHk+ya5NJSyhW9T+2R5PZSym1JLkhyZK31twMbFQBgzTTQdylemOTCFSz/dpJvD2TfAABrC580DwDQmOACAGhMcAEANCa4AAAaE1wAAI0JLgCAxgQXAEBjggsAoDHBBQDQmOBaiW9+85vZa6+9ct999yVJzjjjjA5PBACsaQb0p32Gglpr7rvvvjz88MP5n//5nyxatKjTIwEAaxhXuFbiVa96VdZff/1897vfzSOPPJKPfOQjnR4JAFjDuMK1Em9/+9vzjne8o9NjAABrMFe4VmLECE0KAAyM4AIAaExwAQA0NqSDa8mSJZ0eAQAYAjoaXKWU40op1/R+3Th//vwkyRNPPJGDDjooY8eOzW677ZZrrrkmSXLzzTenu7s7Bx98cN8+zj333Oyyyy459dRTkyQPPPBA3vnOd2bs2LHZc889M3fu3CRJT09Pxo0bl7Fjx2bs2LGZMGFCLrrooiTJjBkzctNNN/Xt8/TTT8/48eOzyy675Oyzz06SnHjiibnuuuuSJDNnzszo0aOz66675mMf+1jjswQArOk6dkd4KWVCklprHd/7eNjSpUuXfu1rX8vcuXNz2GGHZdKkSfntb3+b/fffP+PHj8/3vve9nHXWWTnjjDPS09OTTTbZJBdeeGFuvPHG/N3f/V2S5MMf/nBOOeWUdHV15d57782xxx6bSy65JNdff32WLVuWvffeO/vvv3923HHHFc71q1/9Kp/85Cez995756KLLsrb3/72dHd358EHH8zo0aNz22235YYbbsh1112XUkoOP/zw3HDDDdltt91W27kDANYsHbvCVWv9QZJfllJuKqUcUWtd9upXvzo333xzjjjiiEyaNClJstFGG2X99ddPkrzvfe/LCSeckKuvvjpLly5Nkmy33XYZNWpUxo0blyQ5+eST09XVlSTZZptt+l42POCAA3Lttddm8uTJueCCCzJlypTUWv9krscffzxHHnlkJk6cmF/+8pfZfvvt87vf/S6llJRS8vrXvz5nnnlmSilJkt133z2//vWvm54rAGDN1ul7uI5N8o4k+yRJKSXLli3L9ttvv8KVt9tuu8yePTsTJ05MksybNy89PT2ZNWtWnnnmmSTJDjvs8KIHGzZsWLq6ujJjxowMGzYsPT09f7LOzjvvnF/96le5/PLLM3v27Bx66KHZa6+98sgjjyRJNt5442yyySYv2GZF4QYA8JxOf8jUOkkuTvKtl7PxySefnM9//vO5//77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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = \"อาหารเช้า อาหารสัตว์ อาหารเย็น อาหารกลางวัน\".split()\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T09:03:55.915881Z", + "start_time": "2018-01-25T09:03:55.811980Z" + }, + "hidden": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'ดัน'" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.doesnt_match(\"ลาก ดึง ดูด ดัน\".split())" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T09:03:57.111707Z", + "start_time": "2018-01-25T09:03:56.766901Z" + }, + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAl8AAAJCCAYAAAD+96JYAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3X2wZXV95/vPVxqFAIJgiygo8WpxZSzAnhNMBzpggwSx1ZhiLMSMjEJQAQXLxCjJGKIJcSrcASITSE/ihdzK1QEmEhSCMNKBziDEgwElYuThotI20AqibUDs7t/9ozfYNOf009n+9nl4vapOnb3XWmevby9Wdb1Ze53d1VoLAAB9PGvUAwAAzCXiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfzRj3Apjz/+c9v++6776jHAADYrFtvvfV7rbX5m9tuWsfXvvvum/Hx8VGPAQCwWVX1rS3ZztuOAAAdiS8AgI7EFwBAR+ILAKAj8QUA0NGci69rrrkmRx99dL785S+PehQAYA6a1h81MQx333135s2bl5e+9KW5884787GPfSyttbTWRj0aADAHzfr4+s3f/M38wi/8Qh5//PHsscce+ZVf+ZU85znPycEHHzzq0QCAOWjWx9fNN9/81OPvf//7ufHGG3PPPfeMcCIAYC6b9fG1oT322CNvectbRj0GADCHzYkb7m+//fYsWbIkixcvzqJFi3LmmWdm3bp1T61/xzvekVe/+tX5whe+MMIpAYC5YNbH1yOPPJJTTjklF1xwQa6//vosX748O++8cy688MIkyU9/+tOsWrUql112Wa688soRTwsAzHazPr5uuummHH/88VmxYkWOOOKInH322Tn11FOzbNmyJMn222+fBQsW5LjjjsvatWtHPC0AMNvN+vhKkieeeCJJsnr16lx66aXZdddds3r16nz9619PkvzxH/9xLr/88lGOCADMEbM+vhYuXJhly5ZlwYIFaa3ltNNOe2rd8uXLc+65545wOgBgrpn18bX77rtn9erVOf3007Nw4cKcdNJJT61797vfnSeeeCIXXXTRCCcEAOaSWR9fSbLjjjvm4YcfznnnnfeMdb/7u7+bb3/72/nrv/7rEUwGAMw1cyK+1q5dm3POOSdVNeH6s88+OytXruw8FQAwF9V0/jcOx8bG2vj4+KjHAADYrKq6tbU2trnt5sSVLwCA6WLuxtdXL03OfVVy1m7rv3/10lFPBADMAXPq33Z8ylcvTT73/uSnj61//uh31j9PkgPeOrq5AIBZb25e+frix34WXk/66WPrlwMA/BzNzfh69P6tWw4AMCRzM7523XvrlgMADMncjK8jPppsv+PTl22/4/rlAAA/R3Mzvg54a/LGP0t23SdJrf/+xj9zsz0A8HM3N3/bMVkfWmILAOhsbl75mmE++clP5vDDD8/ixYtz2GGHZenSpUmSb3/72znmmGNy+OGH57DDDsvtt9/+1M888MADOf7443PkkUfmNa95Tf7kT/5kVOMDABuYu1e+ZojPf/7zeeyxx7Js2bJUVdatW5ff/u3fzrXXXpulS5fmE5/4RA444IDce++9ef/735/Pf/7zSZL3v//9Ofvss/Pyl788a9asycknn5zLL788xx577Ij/RAAwt7nyNc0tWbIk73jHO/LOd74zixcvzrHHHpt99tknt9xySz7+8Y/ngAMOSJK87GUvy5o1a5Ikq1atyvOe97wsXbo0a9asybx58/KhD30o//AP/zDCPwkAkLjyNSOccsop+f3f//0sWLAgP/rRj3LiiSdm//33zytf+coJt58/f37222+/PPe5z828eev/E++2225ZvXp1z7EBgAls8ZWvqvpUVT1UVXdssOysqlpRVbcNvo6Z5GePrqp/raq7q+rDwxh8Lnn88cezYMGCJMkuu+yS973vfZv9mWuvvTYnnnjiz3s0AGArbc3bjhcnOXqC5ee21g4afF298cqq2i7Jf0vy+iT7J3lbVe2/LcPOVTfffHMWLlyY5cuXJ0m23377Lfq5qvp5jgUAbIMtjq/W2o1JHt6GfRyc5O7W2r2ttSeSfCbJm7fhdeasAw88MJdddln+4i/+YtSjAABTNIwb7k+rqq8O3pZ83gTrX5zkOxs8v3+wjC30yle+Mm9605vy1rf6XDIAmOmqtbblG1ftm+TzrbVXDZ7vmeR7SVqSjyfZq7X2ro1+5tgkR7fWTho8/49JXtNaO22SfZyc5OQkeclLXvLvv/Wtb23lHwkAoL+qurW1Nra57aZ05au19mBrbW1rbV2S/571bzFubEWSfTZ4vvdg2WSvubS1NtZaG5s/f/5UxgMAmHam9FETVbVXa23l4OlbktwxwWZfTvKKqvrFrI+u45IcP5X9smWu+OcV+dMv/Gu++4PH8qLddszv/Np++fVXe8cXAEZpi+Orqj6d5PAkz6+q+5P8QZLDq+qgrH/b8b4k7x5s+6Ikf9laO6a1tqaqTkvyhSTbJflUa+1fhvqn4Bmu+OcV+cjffi2P/XRtkmTFDx7LR/72a0kiwABghLbqnq/exsbG2vj4+KjHmJEO+cT1WfGDx56x/MW77Zj//eHFI5gIAGa3Lvd8MX19d4Lw2tRyAKAP8TVLvWi3HbdqOQDQh/iapX7n1/bLjttv97RlO26/XX7n1/Yb0UQAQOIf1p61nryp3m87AsD0Ir5msV9/9YvFFgBMM952BADoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHS0xfFVVZ+qqoeq6o4Nlv1pVX2jqr5aVZ+tqt0m+dn7quprVXVbVY0PY3AAgJloa658XZzk6I2WXZfkVa21A5J8M8lHNvHzr22tHdRaG9u6EQEAZo8tjq/W2o1JHt5o2bWttTWDpzcn2XuIswEAzDrDvOfrXUn+fpJ1Lcm1VXVrVZ28qRepqpOraryqxletWjXE8QAARm8o8VVVv5dkTZK/mWSTQ1trC5K8PsmpVfWrk71Wa21pa22stTY2f/78YYwHADBtTDm+quo/JVmS5O2ttTbRNq21FYPvDyX5bJKDp7pfAICZaErxVVVHJ/lQkje11v5tkm12qqpdnnyc5Kgkd0y0LQDAbLc1HzXx6SRfSrJfVd1fVScmuSDJLkmuG3yMxEWDbV9UVVcPfnTPJP9YVbcn+ackV7XWrhnqnwIAYIaYt6UbttbeNsHiv5pk2+8mOWbw+N4kB27TdAAAs4xPuAcA6Eh8AQB0JL4AADoSX9vg9ttvz5IlS7J48eIsWrQoZ555ZtatW5ckueGGG/K6170ur33ta3PooYfm/PPPH/G0AMB0Ir620iOPPJJTTjklF1xwQa6//vosX748O++8cy688MLcc889+cM//MN8+tOfzrJly3LDDTfkzjvvzFVXXTXqsQGAaUJ8baWbbropxx9/fFasWJEjjjgiZ599dk499dQsW7Ys11xzTT74wQ/mxhtvzBFHHJGLL744733ve7Ns2bJRjw0ATBPiaxs88cQTSZLVq1fn0ksvza677prVq1c/bd0jjzySK6644mnrAADE11ZauHBhli1blgULFqS1ltNOO+2pdYcccki++MUvZtGiRXn00Ufzvve9b4STAgDTkfjaSrvvvntWr16d008/PQsXLsxJJ5301LoDDzwwd955Z97+9rfntNNOy1FHHTXCSQGA6WiLP+Gen9lxxx3z8MMP57LLLnva8qrKQw89lCOPPDIf+MAHRjQdADCdufK1DdauXZtzzjknVfWMdc9+9rPzR3/0RyOYCgCYCaq1NuoZJjU2NtbGx8dHPQYAwGZV1a2ttbHNbefK1zYYHx/PkUcemaVLlyZJTjjhhBFPBADMFOJrG7TW8qxnPStXXHFFkuTBBx8c8UQAwEwhvrbBL/3SL+Xaa6/NT37yk6xbty5r1qx5at1V916Voy4/KgdcckCOuvyoXHWvT7cHAH7GbztOwSGHHJLDDjvsqbcdr7r3qpx101l5fO3jSZKVP16Zs246K0nyhpe9YVRjAgDTiBvuh+ioy4/Kyh+vfMbyvXbaK9cee+0IJgIAenHD/Qg88OMHtmo5ADD3iK8heuFOL9yq5QDA3CO+huj0Badnh+12eNqyHbbbIacvOH1EEwEA040b7ofoyZvqz//K+Xngxw/khTu9MKcvON3N9gDAU8TXkL3hZW8QWwDApLztCADQkfgCAOhIfAEAdCS+AAA6El8AAB2JLwCAjsQXAEBH4gsAoCPxBQDQkfgCAOhIfAEAdCS+AAA6El8AAB2JLwCAjsQXAEBH4gsAoCPxBQDQkfgCAOhIfAEAdCS+AAA6El8AAB2JLwCAjsQXAEBH4gsAoCPxBQDQkfgCAOhIfAEAdCS+AAA6El8AAB2JLwCAjsQXAEBH4gsAoCPxBQDQkfgCAOhIfAEAdCS+AAA6El8AAB2JLwCAjsQXAEBH4gsAoKOtiq+q+lRVPVRVd2ywbPequq6q7hp8f94kP3vCYJu7quqEqQ4OADATbe2Vr4uTHL3Rsg8n+WJr7RVJvjh4/jRVtXuSP0jymiQHJ/mDySINAGA226r4aq3dmOThjRa/Ocklg8eXJPn1CX7015Jc11p7uLX2SJLr8syIAwCY9YZxz9eerbWVg8cPJNlzgm1enOQ7Gzy/f7AMAGBOGeoN9621lqRN5TWq6uSqGq+q8VWrVg1pMgCA6WEY8fVgVe2VJIPvD02wzYok+2zwfO/BsmdorS1trY211sbmz58/hPEAAKaPYcTXlUme/O3FE5L83QTbfCHJUVX1vMGN9kcNlgEAzClb+1ETn07ypST7VdX9VXVikk8keV1V3ZXkyMHzVNVYVf1lkrTWHk7y8SRfHnx9bLAMAGBOqfW3aU1PY2NjbXx8fNRjAABsVlXd2lob29x2PuEeAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI6mHF9VtV9V3bbB1w+r6oyNtjm8qh7dYJuPTnW/AAAz0bypvkBr7V+THJQkVbVdkhVJPjvBpstba0umuj8AgJls2G87HpHkntbat4b8ugAAs8Kw4+u4JJ+eZN3Cqrq9qv6+qv7dZC9QVSdX1XhVja9atWrI4wEAjNbQ4quqnp3kTUkum2D1V5K8tLV2YJJPJrlistdprS1trY211sbmz58/rPEAAKaFYV75en2Sr7TWHtx4RWvth6211YPHVyfZvqqeP8R9AwDMCMOMr7dlkrccq+qFVVWDxwcP9vv9Ie4bAGBGmPJvOyZJVe2U5HVJ3r3BsvckSWvtoiTHJnlvVa1J8liS41prbRj7BgCYSYYSX621HyfZY6NlF23w+IIkFwxjXwAAM5lPuAcA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEdDi6+quq+qvlZVt1XV+ATrq6r+rKrurqqvVtWCYe0bAGCmmDfk13tta+17k6x7fZJXDL5ek+TCwXcAgDmj59uOb07y1229m5PsVlV7ddw/AMDIDTO+WpJrq+rWqjp5gvUvTvKdDZ7fP1gGADBnDPNtx0Nbayuq6gVJrquqb7TWbtzaFxmE28lJ8pKXvGSI4wEAjN7Qrny11lYMvj+U5LNJDt5okxVJ9tng+d6DZRu/ztLW2lhrbWz+/PnDGg8AYFoYSnxV1U5VtcuTj5McleSOjTa7Msk7Br/1+MtJHm2trRzG/gEAZophve24Z5LPVtWTr/n/ttauqar3JElr7aIkVyc5JsndSf4tyTuHtG8AgBljKPHVWrs3yYETLL9og8ctyanD2B8AwEzlE+4BADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANCR+AIA6GjK8VVV+1TVsqr6elX9S1WdPsE2h1fVo1V12+Dro1PdLwDATDRvCK+xJskHW2tfqapdktxaVde11r6+0XbLW2tLhrA/AIAZa8pXvlprK1trXxk8/lGSO5O8eKqvCwAwGw31nq+q2jfJq5PcMsHqhVV1e1X9fVX9u028xslVNV5V46tWrRrmeAAAIze0+KqqnZP8zyRntNZ+uNHqryR5aWvtwCSfTHLFZK/TWlvaWhtrrY3Nnz9/WOMBAEwLQ4mvqto+68Prb1prf7vx+tbaD1trqwePr06yfVU9fxj7BgCYSYbx246V5K+S3Nla+6+TbPPCwXapqoMH+/3+VPcNADDTDOO3HQ9J8h+TfK2qbhssOzPJS5KktXZRkmOTvLeq1iR5LMlxrbU2hH0DAMwoU46v1to/JqnNbHNBkgumui8AgJnOJ9wDAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKCjocRXVR1dVf9aVXdX1YcnWP+cqvofg/W3VNW+w9gvAMBMM+X4qqrtkvy3JK9Psn+St1XV/httdmKSR1prL09ybpL/MtX9AgDMRMO48nVwkrtba/e21p5I8pkkb95omzcnuWTw+PIkR1RVDWHfAAAzyjDi68VJvrPB8/sHyybcprW2JsmjSfYYwr4BAGaUaXfDfVWdXFXjVTW+atWqUY8DADBUw4ivFUn22eD53oNlE25TVfOS7Jrk+xO9WGttaWttrLU2Nn/+/CGMBwAwfQwjvr6c5BVV9YtV9ewkxyW5cqNtrkxywuDxsUmub621IewbAGBGmTfVF2itramq05J8Icl2ST7VWvuXqvpYkvHW2pVJ/irJ/1NVdyd5OOsDDQBgzplyfCVJa+3qJFdvtOyjGzx+PMl/GMa+AABmsml3wz0AwGwmvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR+ILAKAj8QUAzFif+cxnsmjRovz5n/95kmTdunV517veNeKpNk18AQAz1nXXXZfDDz88t912W1avXp0zzjgjhx566KjH2iTxBQDMWB//+Mfz4IMP5pvf/Gbe/va3Z9GiRdP+yte8UQ8AALCtXvSiF2Xp0qWjHmOruPIFAMxIt99+e5YsWZLFixdn0aJFOfPMM7Nu3bpceOGFWbBgQc4+++ynbf+e97wn991332iG3YD4AgBmnEceeSSnnHJKLrjgglx//fVZvnx5dt5551x44YW58sorc8stt+SGG24Y9ZgT8rYjADDj3HTTTTn++OOzYsWKnHjiiTniiCNy6qmn5sQTT8xv/dZv5Vd/9Vfz+OOPj3rMCbnyBQDMSE888USSZPXq1bn00kuz6667ZvXq1fmN3/iNfOlLX8qee+454gknJr4AgBln4cKFWbZsWRYsWJDWWk477bTN/sw3vvGNPPe5z+0w3aaJLwBgxtl9992zevXqnH766Vm4cGFOOumkSbf93ve+l/e+97257777ssMOO3SccmLiCwCYkXbcccc8/PDDOe+88yZcv3bt2px11ll529velvvvvz+XXHJJzj///M5TPpP4AgBmpLVr1+acc85JVU24/q677sqznvWsXHfdddlpp53ywQ9+MAsXLuw85TNVa23UM0xqbGysjY+Pj3oMAIDNqqpbW2tjm9vOlS8AYFZ69HOfy12Lj8idr9w/dy0+Io9+7nOjHimJz/kCAGahRz/3uaz8zx9NG3zW15rvfjcr//NHkyS7vvGNoxzNlS8AYPZ56NzzngqvJ7XHH89D5058c35P4gsAmHXWrFy5Vct7El8AwKwzb6+9tmp5T+ILAJh1XvCBM1IbfaBq7bBDXvCBM0Y00c+44R4AmHWevKn+oXPPy5qVKzNvr73ygg+cMfKb7RPxBQDMUru+8Y3TIrY25m1HAICOxBcAQEfiCwCgI/EFANCR+AIA6Eh8AQB0JL4AADoSXwAAHYkvAICOxBcAQEfiCwCgI/EFANDRlP5h7ar60yRvTPJEknuSvLO19oMJtrsvyY+SrE2yprU2NpX9AgDMVFO98nVdkle11g5I8s0kH9nEtq9trR0kvACAuWxK8dVau7a1tmbw9OYke099JACA2WuY93y9K8nfT7KuJbm2qm6tqpM39SJVdXJVjVfV+KpVq4Y4HgDA6G32nq+q+l9JXjjBqt9rrf3dYJvfS7Imyd9M8jKHttZWVNULklxXVd9ord040YattaVJlibJ2NhY24I/AwDAjLHZ+GqtHbmp9VX1n5IsSXJEa23CWGqtrRh8f6iqPpvk4CQTxhcAwGw2pbcdq+roJB9K8qbW2r9Nss1OVbXLk4+THJXkjqnsFwBgpprqPV8XJNkl699KvK2qLkqSqnpRVV092GbPJP9YVbcn+ackV7XWrpnifgEAZqQpfc5Xa+3lkyz/bpJjBo/vTXLgVPYDADBb1CS3aU0LVbUqybdGPccWen6S7416iBnIcds2jtu2cdy2jeO2bRy3bTOTj9tLW2vzN7fRtI6vmaSqxn2A7NZz3LaN47ZtHLdt47htG8dt28yF4+bfdgQA6Eh8AQB0JL6GZ+moB5ihHLdt47htG8dt2zhu28Zx2zaz/ri55wsAoCNXvgAAOhJf26CqPlVVD1XVHRss272qrququwbfnzfKGaejSY7bWVW1YvAhvbdV1TGjnHG6qap9qmpZVX29qv6lqk4fLHe+bcImjpvzbROqaoeq+qequn1w3P5wsPwXq+qWqrq7qv5HVT171LNOJ5s4bhdX1f+3wfl20KhnnY6qaruq+ueq+vzg+aw/38TXtrk4ydEbLftwki+21l6R5IuD5zzdxXnmcUuSc1trBw2+rp5g/Vy2JskHW2v7J/nlJKdW1f5xvm3OZMctcb5tyk+SLG6tHZjkoCRHV9UvJ/kvWX/cXp7kkSQnjnDG6Wiy45Ykv7PB+Xbb6Eac1k5PcucGz2f9+Sa+tkFr7cYkD2+0+M1JLhk8viTJr3cdagaY5LixCa21la21rwwe/yjr/4J6cZxvm7SJ48YmtPVWD55uP/hqSRYnuXyw3Pm2kU0cNzajqvZO8oYkfzl4XpkD55v4Gp49W2srB48fyPp/05Itc1pVfXXwtqS3zyZRVfsmeXWSW+J822IbHbfE+bZJg7eAbkvyUJLrktyT5AettTWDTe6PkH2GjY9ba+3J8+2PB+fbuVX1nBGOOF2dl+RDSdYNnu+ROXC+ia+fg7b+V0j9X8+WuTDJ/5H1l+pXJvm/RjvO9FRVOyf5n0nOaK39cMN1zrfJTXDcnG+b0Vpb21o7KMneSQ5O8n+OeKQZYePjVlWvSvKRrD9+v5Rk9yS/O8IRp52qWpLkodbaraOepTfxNTzzOYwSAAABoElEQVQPVtVeSTL4/tCI55kRWmsPDv7SWpfkv2f9X/ZsoKq2z/qA+JvW2t8OFjvfNmOi4+Z823KttR8kWZZkYZLdqmreYNXeSVaMbLBpboPjdvTg7e/WWvtJkv87zreNHZLkTVV1X5LPZP3bjednDpxv4mt4rkxywuDxCUn+boSzzBhPBsTAW5LcMdm2c9Hg/oe/SnJna+2/brDK+bYJkx0359umVdX8qtpt8HjHJK/L+vvlliU5drCZ820jkxy3b2zwP0iV9fctOd820Fr7SGtt79bavkmOS3J9a+3tmQPnmw9Z3QZV9ekkh2f9v7z+YJI/SHJFkkuTvCTJt5K8tbXm5vINTHLcDs/6t4BakvuSvHuDe5nmvKo6NMnyJF/Lz+6JODPr719yvk1iE8ftbXG+TaqqDsj6G5y3y/r/Ob+0tfaxqnpZ1l+Z2D3JPyf5zcHVHLLJ43Z9kvlJKsltSd6zwY35bKCqDk/y2621JXPhfBNfAAAdedsRAKAj8QUA0JH4AgDoSHwBAHQkvgAAOhJfAAAdiS8AgI7EFwBAR/8/1rpAa+jnqL0AAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = \"ลาก ดึง ดูด ดัน\".split()\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T09:00:04.040459Z", + "start_time": "2018-01-25T09:00:03.917290Z" + }, + "hidden": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'หมอ'" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.doesnt_match(\"แมว หมา หมู หมอ\".split())" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T09:00:23.186752Z", + "start_time": "2018-01-25T09:00:22.875191Z" + }, + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAAJCCAYAAADky0LWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAHBpJREFUeJzt3Xuw33V95/HXZ5NAQDEKOVwKXbl4WdxO1eS0U0l1GYHKIijMSIvIjnVx4jJ0G0Xo6m6plemOMMUGZHdgWMWkEswy3oBSo6BIl1BgT5DlFlhcbRUFCcMaWApyyWf/OIcQIBc875PzOyfn8ZjJ5Pw+5/c73/eZ73zheb7f7/ml9d4DAMD4/LNBDwAAMJ2JKQCAAjEFAFAgpgAACsQUAECBmAIAKBBTAAAFYgoAoEBMAQAUzJ7Mjc2fP7/vv//+k7lJAIBxWbNmzcO996FtPW9SY2r//ffPyMjIZG4SAGBcWmv/+HKe5zIfAECBmAIAKBBTAAAFYgoAoEBMAQAUiCkAgAIxBQBQIKYAAArEFABAgZgCACgQUwAABWIKAJgUV155ZRYsWJAlS5ZsXDvrrLOycOHCrFixIieccEIWLlyYNWvWbPz8ypUrs2zZsiTJD37wgxx//PE5/PDDc+ihh+aoo47K3XffPdnfxktM6j90DADMXJdffnlWrVqVk046aePa6tWrc+ONN+bYY4/NAQcckHPOOSdXX311Fi5c+JLXf/azn815552XfffdN0ly33335QMf+EBuueWWSfseNseZKQBgUpxyyik57rjjcscdd2xc22233bL33nvn1FNPzZw5c3L66adnw4YNm3395z73uZx22mk56qij8vDDD+f1r399Xve61+Whhx6arG9hs8QUADApFi1alNWrV+fNb35zkuTaa6/NG97whpx99tl54okncv755+eiiy7a4utHRkay77775sMf/nBWrVqVJNlpp522GF+TxWU+AGDSbdiwIRdccEFWrlyZK664Io8//vg2X/PLX/4yX//613PXXXflS1/60iRM+fI4MwUATKrWWpYvX54TTzwxu+yyy8b1c889NyeffHJuuOGG3HvvvZt97Uc+8pF861vfyp577jlZ426TM1MAwKSaO3durrnmmlx22WUvWL/++uuzZs2aLFy4MEuXLs2jjz6aBQsWZP78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TgkAzETTIqZOOeWUHHfccbnjjjs2ru22227Ze++9c+qpp2bOnDk5/fTTs2HDhgFOCQDMRLMHPcDLsWjRoqxevTpHHnlkkuTaa6/NG97whhxxxBF54okncv755+emm27KqlWrBjwpADDTTIszU5vasGFDLrjggpx55pmZN29eHn/88UGPBADMYNMqplprWb58eU488cTssssuG9fPPffcnHzyybnhhhty7733DnBCAGCmmRaX+Z4zd+7cXHPNNbnssstesH799ddnzZo1WbhwYZYuXZpHH300CxYsyPz58wc0KQAwU0yrM1Pr16/Pxz/+8ZesH3TQQTnkkEOyePHiXHTRRTnttNNy4YUXDmBCAGCmab33SdvY8PBwHxkZmbTtAQCMV2ttTe99eFvPm1ZnprblM5/5TA4//PD86Ec/yk033eTsFACw3U2re6a25uofXp1L7rgkP7nnJ3nv596b9//W+9PWt0GPBQDs4HaImLr6h1fnz2/888x919wM7TaURx57JJfcekneMecdgx4NANjB7RCX+c6/9fw8+eyTSZJX/stX5tGRR/Pgtx/MPb92z4AnAwB2dDvEmakHH39w48ez583Oaz/22iTJY3lsUCMBADPEDnFmau9X7P0rrQMATJQdIqaWLFiSubPmvmBt7qy5WbJgyYAmAgBmih3iMt+7D3x3ktF7px58/MHs/Yq9s2TBko3rAADbyw4RU8loUIknAGCy7RCX+QAABkVMAQAUiCkAgAIxBQBQIKYAAArEFABAgZgCACjY4WPqyiuvzIIFC7JkyfPvhn7WWWdl4cKFWbFiRU444YQsXLgwa9as2fj5lStXZtmyZUmS22+/PYcddlgOPfTQ/N7v/V5+/OMfT/a3AABMYTt8TF1++eVZtWpVVqxYsXHtr//6r7N06dJceumlec1rXpPddtstxxxzzAuC6uabb86yZcuyZMmSHH/88Xn22Wfz8MMP55BDDsmNN944iG8FAJiCdviYOuWUU3Lcccflscce27i200475eijj86pp56aZ599NnfeeWcOP/zwXH311S95/ac+9al84xvfyHe/+93ceuutOfjgg3PGGWek9z6Z3wYAMEXtMP+czJYsWrQoq1evzvz585Mk1157bfbYY48cc8wxeeKJJ3LxxRfnF7/4Rb797W/nwAMPfMnr3/72t2fRokWZM2dOkmTW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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = \"แมว หมา หมู หมอ\".split()\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cosine Similarity" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:49:26.327610Z", + "start_time": "2018-01-25T08:49:26.219002Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "China + Beijing: 0.3135956\n", + "Italy + Rome: 0.42819628\n", + "Beijing + Rome: 0.27347285\n", + "Italy + Beijing: 0.17900795\n", + "China + Rome: 0.02666693\n", + "China + Italy: 0.24352394\n" + ] + } + ], + "source": [ + "print('China + Beijing:', model.similarity('ปักกิ่ง', 'จีน'))\n", + "print('Italy + Rome:', model.similarity('โรม','อิตาลี'))\n", + "print('Beijing + Rome:', model.similarity('โรม', 'ปักกิ่ง'))\n", + "print('Italy + Beijing:', model.similarity('ปักกิ่ง', 'อิตาลี'))\n", + "print('China + Rome:', model.similarity('โรม','จีน'))\n", + "print('China + Italy:', model.similarity('อิตาลี','จีน'))" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "ExecuteTime": { + "end_time": "2018-01-25T08:55:58.556210Z", + "start_time": "2018-01-25T08:55:58.223988Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAAJCCAYAAAAC4omSAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xm0XWV9//HPQxIGGUWCjIFSKSV1ifCLkEgFwiQyU6NFpQwVU0AQh2pJKzhVSy1FpBUBR0QroWEMYSwJCpTBMBSqoIATxCBhDIEQMzy/P3JJk5DhJnluzr3J67XWXTlnn+fu871rk/Be++xzbqm1BgCAFbdGpwcAAFhVCCsAgEaEFQBAI8IKAKARYQUA0IiwAgBoRFgBADQirAAAGhFWAACN9O/UE2+yySZ122237dTTAwB02z333PN0rXXg0tZ1LKy23XbbTJw4sVNPDwDQbaWU33RnnZcCAQAaEVYAAI0IKwCARoQVAEAjwgoAoBFhBQCrsVmzZuWZZ57p9BirDGEFAKuxJ554Iv/wD//Q6TFWGR37HCsAYMkmTpyYs846K0899VTWXHPNnHzyyTn44INXaJ8333xzzjvvvDz33HNZb731MmLEiEbTkjhjBQC90owZM/Lud787kyZNyiuvvJI11lgjp512WiZMmLDc+5w0aVKOPvroTJkyJTNmzMicOXNyxhlnNJwaZ6wAoBdaa6218pvfzP2w71prnnzyyYwfPz6TJk1a7n1uueWW876/1ppJkyZl/PjxmT17dpOZSUqttSNPPGTIkOpX2gDA8pk5c2amTp2aN7zhDXnyySez6aabZo01vBDVU0op99RahyxtnTNWANBLffWrX81VV12VJJk+fXoOPfTQjBo1KtOnT8/hhx+etdZaK4cffniuuOKKzJo1K9dcc0369euX3/72tznhhBPy8ssvp9aac889NzvttFOS5N/+7d9y2WWXZY011sjs2bPzgQ98ICNHjuzkj7lKkbYA0AvdfPPNKaVk/PjxGT9+fG6//fY888wz+e53v5uLL744xxxzTH74wx/m+eefzxVXXJGhQ4fmhhtuSJJ8/OMfz5lnnplbbrkl3/nOd+a96++aa67J9OnTM2HChIwfPz4TJkzIww8/nBtvvLGTP+oqRVgBQC+0zz77ZPvtt8/QoUNzwQUXZI011sjIkSNz99135/77789uu+2Wa6+9NqNHj86ECROy66675qGHHkqSfOELX8hb3vKWJMl2222XWbNmJUkOPvjgHH300TnuuOOy9957Z8SIEdl6661z1113deznXNUIKwDopc4999xcd911885ErbnmmpkzZ05e//rX54UXXsiYMWNy8803Z9y4cVlnnXUyc+bMJMmOO+642H2edNJJ+chHPpLx48fnoosuyh133OHi9YaEFQD0Un/4wx9yyCGHZPjw4Qts//M///P85Cc/yamnnpq3vvWt+cu//Mtu7/OVV17JLrvskiRZf/31c8oppzSdeXUnrACglxowYEBuu+2218TP7rvvnokTJ+b222/P6aefnmHDhnV7n3feeWeGDRuWW2+9dd5z0I6wAoBeasMNN8y999477/59992XN7zhDdlggw1yzTXXZMCAATnmmGOWaZ877bRT/vM//zMXXHBB63GJj1sAgF7r85//fE466aTMnj07tdasv/76+da3vpUk2XjjjXPqqacu8z533HHHHHroofnsZz/beFoSHxAKALBU3f2AUC8FAgA0IqwAYDXywtixeWTvffLQjoPzyN775IWxYzs90irFNVYAsJp4YezYTD79jNRXXkmSzPrd7zL59DOSJBseckgnR1tlOGMFAKuJp75yzryoelV95ZU89ZVzOjTRqkdYAcBqYtbkycu0nWUnrABgNdF/882XaTvLTlgBwGpi0499NGXttRfYVtZeO5t+7KMdmmjV4+J1AFhNvHqB+lNfOSezJk9O/803z6Yf+6gL1xsSVgCwGtnwkEOEVA/q1kuBpZSNSiljSikPl1IeKqUMW+jxUko5t5TyaCnlgVLKLj0zLgBA79XdM1ZfTXJ9rXVEKWXNJK9b6PF3Jdm+62u3JF/v+hMAYLWx1DNWpZQNk+yR5FtJUmv9Q631+YWWHZbke3WuO5NsVErxFgMAYLXSnZcC/yjJlCTfKaXcV0r5Zill3YXWbJnk8fnuP9G1DQBgtdGdsOqfZJckX6+17pzkpSSnLc+TlVJGllImllImTpkyZXl2AQDQa3UnrJ5I8kSt9a6u+2MyN7TmNynJ1vPd36pr2wJqrRfWWofUWocMHDhweeYFAOi1lhpWtdYnkzxeStmha9M+SX620LKrkxzd9e7AoUleqLX6fHwAYLXS3XcFnpLkB13vCPxlkuNK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td61iGXvLqU8UEoZU0rZuumUAAB9QLfCqtY6u9b61iRbJdm1lPLmhZaMTbJtrfUtSW5KctGi9lNKGVlKmVhKmThlypQVmRsAoNdZpncF1lqfTzIhyQELbX+m1vrqb0X8ZpL/t5jvv7DWOqTWOmTgwIHLMy8AsBJMmzYtL730UqfH6HO6867AgaWUjbpur5NkvyQPL7Rm8/nuHprkoZZDAgAr15gxYzJ27NhOj9HndOddgZsnuaiU0i9zQ+zSWus1pZTPJ5lYa706yUdKKYcmmZXk2STH9tTAAEB75513XsaNG5eXX345gwYNynbbbZcddtih02P1Od15V+ADSXZexPYz5rs9KsmotqMBACvDmDFjcvbZZ2fzzTdPKSVPP/10rr766nz961/v9Gh9jt8VCACruREjRmTEiBFJkpkzZ+aRRx7JjTfemC222KLDk/U9wgoAmGfAgAEZPHhwBg8e3OlR+iS/KxAAVnOzZ8/Opz/96ey5554ZPnx4hg4dmvPPPz/PP/989txzz7z97W/P5MmT561/8sknc+yxx3Zu4F7MGSsAWM3dcMMN2WabbfKP//iPSea+HHjggQdmnXXWyUEHHZSNN944t956a9773vd2eNLezxkrAFjNHXjggdl2222z22675dprr82AAQOy++67Z9ttt82dd96Zs846K3PmzOn0mH2CsAIA8v3vfz833XTTAu8EXGuttXL55ZfntNNO6+BkfYuXAgGAvP/978+BBx6Y7vzKuYcffjgbbLDBSpiq73HGCgDIO9/5ztx2223ZYYcd8swzzyx23XXXXZejjz7ah4cuhrACAOb50z/90zz44IOZMWNG+vf/vxe27r///uy///755Cc/mUsuuSQ333xzZs2a1cFJeycvBQIA8xxxxBEZOXJkXv/61+f000+ft3306NG55ZZb8qtf/SqnnnpqtttuuwXCi7lKrbUjTzxkyJA6ceLEjjw3AMCyKKXcU2sdsrR1XgoEAGhEWAEAS/bApclX3px8dqO5fz5waacn6rW8OAoALN4DlyZjP5LMnD73/guPz72fJG/xSewLc8YKAFi8mz//f1H1qpnT527nNYQVALB4LzyxbNtXc8IKAFi8Dbdatu2rOWEFACzePmckA9ZZcNuAdeZu5zWEFQCweG95b3LIucmGWycpc/885FwXri+GdwUCAEv2lvcKqW5yxgoAoBFhBQDQiLACAGhEWAEANCKsAAAaEVYAAI0IKwCARoQVAEAjwgoAoBFhBQDQiLACAGhEWAEANCKsAAAaEVYAAI0IKwCARoQVAEAjwgoAoBFhBQDQiLACAGhEWAEANCKsAAAaEVYAAI0IKwCARoQVAEAjwgoAoBFhBQDQiLACAGhEWAEANCKsAAAaEVYAAI0IKwCARoQVAEAjSw2rUsrapZS7Syn/U0r5aSnlc4tYs1YpZXQp5dFSyl2llG17YlgAgN6sO2esZiTZu9a6U5K3JjmglDJ0oTUfTPJcrfVNSb6S5J/bjgkA0PstNazqXNO67g7o+qoLLTssyUVdt8ck2aeUUppNCQDQB3TrGqtSSr9Syv1JnkpyU631roWWbJnk8SSptc5K8kKSN7QcFACgt+tWWNVaZ9da35pkqyS7llLevDxPVkoZWUqZWEqZOGXKlOXZBQBAr7VM7wqstT6fZEKSAxZ6aFKSrZOklNI/yYZJnlnE919Yax1Sax0ycODA5ZsYAKCX6s67AgeWUjbqur1Okv2SPLzQsquTHNN1e0SS8bXWha/DAgBYpfXvxprNk1xUSumXuSF2aa31mlLK55NMrLVeneRbSS4upTya5NkkR/bYxAAAvdRSw6rW+kCSnRex/Yz5br+S5D1tRwMA6Ft88joAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaERYAQA0IqwAABoRVgAAjQgrAIBGhBUAQCPCCgCgEWEFANCIsAIAaGSpYVVK2bqUMqGU8rNSyk9LKacuYs1epZQXSin3d32d0TPjAgD0Xv27sWZWkk/UWu8tpayf5J5Syk211p8ttO7WWuvB7UcEAOgblnrGqtY6udZ6b9ftF5M8lGTLnh4MAKCvWaZrrEop2ybZOcldi3h4WCnlf0op15VS/qzBbAAAfUp3XgpMkpRS1ktyWZKP1lqnLvTwvUm2qbVOK6UcmOTKJNsvYh8jk4xMkkGDBi330AAAvVG3zliVUgZkblT9oNZ6+cKP11qn1lqndd2+NsmAUsomi1h3Ya11SK11yMCBA1dwdACA3qU77wosSb6V5KFa69mLWbNZ17qUUnbt2u8zLQcFAOjtuvNS4O5J/irJg6WU+7u2/X2SQUlSaz0/yYgkJ5ZSZiWZnuTIWmvtgXmTJNOmTUspJeuuu25PPQUAwDJbaljVWm9LUpay5t+T/PvC20sphyT5aJJ+SWqSXyb5m1rrrOWatsuYMWOy9tpr58gjj1yR3QAANNXti9eX0/pJXkpyVa31W8u7k/POOy/jxo3Lyy+/nEGDBmW77bbLDjvs0G5KAIAGevRX2tRa/yPJYUl2LaXsuzz7GDNmTM4+++xMnTo1s2fPztNPP51zzjmn7aAAAA309Bmr1FprKeWHSXZN8l/L+v0jRozIiBEjkiQzZ87MI488khtvvDFbbLFF40kBAFZMj4fVfOadHSulDNhpp52SJE8++WQ23XTTrLHG0k+eDRgwIIMHD87gwYN7bkoAgOXUoy8FLkopZZ0k1/z617/Ot7/97XzoQx/KQQcdlNmzZydJvvvd7+aSSy5Z4HtuuOGG7Lvvvtlrr72y11575Y477pj32HXXXZfdd98973rXuzJr1txr4g844IAkyW9/+9scfPDB2XvvvbPnnnvmS1/60sr5IYEVNnny5Hn/LgD0FSs9rDL3oxsu+qM/+qM8//zzueKKKzJ06NDccMMNi1z8wAMP5PLLL8+1116bW265JRdffHFOOumkvPzyy0mS0aNH501velM23HDD15z1OvXUU/PlL38548ePz49+9KO88MILue6663r65wMaGDVqVKZMmdLpMQCWSSfC6q1J7po6dWpGjx6dCRMmZNddd81DDz20yMWPPvpokmTcuHFJkq233jrvfOc787Of/SxJsu666+akk07KJZdc8pqw+uEPf7jAy4b7779/HnzwwR74kQAAOhNWzyXZ8LnnnsvNN9+ccePGZZ111snMmTMXufjwww/PpEmTsssuu8zbttFGG2XatGlJkr//+7/PEUcckb322iv33HPPAt+79tprL3C/X79+mTNnTtufBugR3/3ud7PZZpt1egyAZbIyL15/1W1J3rbpppvmrW99ay6++OLMmDFjsYsnTZqUzTbbLNtss80iH7/gggvy/e9/P3vvvXcPjQsA0D0r84zVh0op/5XkZ0mGTJs2LaeffnqGDRv2moWf/exnM2LEiEyfPj2zZ89O//6L77/f/va3S32XYK01xx9/fE455ZQV/BGApRk1alT22GOP3H777UmS+++/f6mfPffSSy/lE5/4RPbbb78MHz48p59+eqZPn74yxgVoamWF1awklya5MMl7khxcSskxxxzzmoX9+vXLsccemwMOOGDeP8xLsvnmm+fuu++ed/+BBx7IRhtttMCaxx57LOutt17+6Z/+Kf369VuxnwRYorvuuitvetOb8thjj+WPCo4KAAAL+klEQVTiiy/O0KFDs+++S/584FGjRmXChAnzXuL/7//+73z0ox9dGeMCNLWyXgq8L8nnkuyXue8KPG7TTTdd5MUTw4cPzxFHHJENN9wwl112WZ577rkl7vjjH/94jj/++Jx99tkppaRfv3752te+tsCabbfdNr/85S/zuc99Lt/+9rfb/ETAIn3pS1/KWWedle985zv5+c9/ns985jN585vfvMTvOffcc+fdfumll/KTn/wk48ePz8yZMzNgwICeHhmgmVJr7cgTDxkypE6cOLEjzw2sHLfcckvuvPPOnHbaaZ0eBWCFlFLuqbUOWdq6TrwrEFjFXH311dlll11y8sknL3bNkj7oN0n+9V//NcOHD88ee+yRv/iLv8jvfve7BR7/2te+lp133jlf+MIXeuRnAGihE+8KXKl+cdeTueOqxzLt2RlZb+O1MuywP86f7OYt3NDSpZdemuuvvz5HHXXUIh+f/4N+11xzzTz++OM59NBDc/vtt+d1r3tdzj///Ky//vqZMGFCkuSmm27KiSeemKuuumrePsaOHZu77rorhx566Er5mQCWxyp9xuoXdz2ZCT94ONOenftxDtOenZEJP3g4v7jryQ5PBquWE088MUccccRiP4B3aR/0++yzz2bixIl5+OGHkyT77bffvAvZX/WhD30oe+65Z37/+9/31I8BsMJW6bC646rHMusPC34g6Kw/zMkdVz3WoYlg1bT77rvn9ttvz6u/XH1hS/ug3/e97315/vnnM2jQoHmPv3rR+mOPPZY//OEPefe735077rgjb3zjG3vwJwFYMat0WL16pqq724GesbQP+r3tttty6KGH5nWve91rHnv22WczcuTIeb9kHaA3W6XDar2N11qm7UDPWNoH/S7p8be97W059thjc8IJJ/iVVECvt0qH1bDD/jj911zwR+y/5hoZdtgfd2giWLWtvfbaeeSRR+bd/+lPf5rXv/71K7zfvfbaK4cffnhOPvnkdOojYgC6Y5V+V+Cr7/7zrkBYOU4//fR88IMfTL9+/TJ79uy88Y1vzLe//e0888wzK7zvgw8+OFOnTs2PfvSjBpMC9AwfEAoAsBQ+IBQAYCVbpV8KBPq+K++blH+54ef53fPTs8VG6+ST79whh++8ZafHAlgkYQX0WlfeNymjLn8w02fOTpJMen56Rl0+90NIxRXQG3kpEOi1/uWGn8+LqldNnzk7/3LDzzs0EcCSCSug1/rd89OXaTtApwkroNfaYqN1lmk7QKcJK6DX+uQ7d8g6A/otsG2dAf3yyXfu0KGJAJbMxetAr/XqBereFQj0FcIK6NUO33lLIQX0GV4KBABoRFgBADQirAAAGnGNFR01duzYnHPOOZk9e3ZKKdluu+1ywQUXpH9//2kC0Pf4vxcd9eKLL2bdddfNYYcdlg9+8IOdHgcAVoiXAumo97///bnqqqty991357/+6786PQ4ArBBhRceVUvK+970v9957b6dHAYAVIqzoNebMmbPI7bNnz17sYwDQmwgrep3bbrstu+22W4YPH5699torhx56aB566KE8+eST2WOPPbLHHnvkxRdfnLf+hBNOyK9//evODQwAXVy8Tq8zduzYbL311tlnn31y+OGHZ/PNN0+SjBkzJieffHIeeOCB3Hfffdljjz06PCkALEhY0ev88z//c2bMmJE77rgjZ5xxRrbffvt86lOfyv77758PfOADefDBB7Pvvvt2ekwAeA0vBdIrrbXWWtlrr73yjW98IzfffHOSZIMNNsjYsWNzwgkndHg6AFg0YUWvV0rp9AgA0C3Cil7jG9/4Rvbdd988/vjjSZKrrroqw4YNy+9///skc98deNRRR+W8887LlVdemaeffrqT4wLAawgreoX+/fvnve99b0aOHJnRo0cnSS666KL8+Mc/zkYbbZQkue+++/Inf/Inufjii/Pwww/n+OOPz6hRozJ9+vROjg4A8wgreoWdd945d999d7785S/noIMOSpIccMABGTZs2LwL1f/sz/4st99+ez72sY/l05/+dK688soMHjw4l112WSdHB4B5Sq21I088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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "sample_words = \"ปักกิ่ง จีน โรม อิตาลี โตเกียว ญี่ปุ่น\".split()\n", + "sample_idx = []\n", + "for word in sample_words:\n", + " sample_idx.append(labels.index(word))\n", + "sample_plot = thai2plot[sample_idx]\n", + "plot_with_labels(sample_plot,sample_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Spellchecking" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Originally contributed by [Sakares ATV](https://github.com/sakares), adapted from [Kaggle Spell Checker using Word2vec by CPMP](https://www.kaggle.com/cpmpml/spell-checker-using-word2vec)." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "words = model.index2word\n", + "\n", + "w_rank = {}\n", + "for i,word in enumerate(words):\n", + " w_rank[word] = i\n", + "\n", + "WORDS = w_rank" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "thai_letters = 'กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤฤๅลฦฦๅวศษสหฬอฮะัาำิีึืุูเแโใไ็่้๊๋์'\n", + "\n", + "def words(text): return re.findall(r'\\w+', text.lower())\n", + "\n", + "def P(word): \n", + " \"Probability of `word`.\"\n", + " # use inverse of rank as proxy\n", + " # returns 0 if the word isn't in the dictionary\n", + " return - WORDS.get(word, 0)\n", + "\n", + "def correction(word): \n", + " \"Most probable spelling correction for word.\"\n", + " return max(candidates(word), key=P)\n", + "\n", + "def candidates(word): \n", + " \"Generate possible spelling corrections for word.\"\n", + " return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])\n", + "\n", + "def known(words): \n", + " \"The subset of `words` that appear in the dictionary of WORDS.\"\n", + " return set(w for w in words if w in WORDS)\n", + "\n", + "def edits1(word):\n", + " \"All edits that are one edit away from `word`.\"\n", + " letters = thai_letters\n", + " splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]\n", + " deletes = [L + R[1:] for L, R in splits if R]\n", + " transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]\n", + " replaces = [L + c + R[1:] for L, R in splits if R for c in letters]\n", + " inserts = [L + c + R for L, R in splits for c in letters]\n", + " return set(deletes + transposes + replaces + inserts)\n", + "\n", + "def edits2(word): \n", + " \"All edits that are two edits away from `word`.\"\n", + " return (e2 for e1 in edits1(word) for e2 in edits1(e1))" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'พัฒนา'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "correction('พัดนา')" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'จริง'" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "correction('ขริง')" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'จ้า'" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "correction('จย้า')" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'นะคะ'" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "correction('นะค่ะ')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pythainlp/benchmarks/__init__.py b/pythainlp/benchmarks/__init__.py index 711404da2..181e8b775 100644 --- a/pythainlp/benchmarks/__init__.py +++ b/pythainlp/benchmarks/__init__.py @@ -1,3 +1,3 @@ -from .word_tokenisation import benchmark +from .word_tokenization import benchmark __all__ = ["benchmark"] \ No newline at end of file diff --git a/pythainlp/benchmarks/word_tokenisation.py b/pythainlp/benchmarks/word_tokenization.py similarity index 86% rename from pythainlp/benchmarks/word_tokenisation.py rename to pythainlp/benchmarks/word_tokenization.py index 75e074b84..ee3c21ae9 100644 --- a/pythainlp/benchmarks/word_tokenisation.py +++ b/pythainlp/benchmarks/word_tokenization.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- -import sys import re +import sys import numpy as np import pandas as pd + SEPARATOR = "|" # regex for removing to a space surrounded by separators, i.e. | | @@ -68,7 +69,7 @@ def benchmark(ref_samples: list, samples: list): """ Performace benchmark of samples - Please see :meth:`pythainlp.benchmarks.word_tokenisation.compute_stats` for + Please see :meth:`pythainlp.benchmarks.word_tokenization.compute_stats` for metrics being computed. :param list[str] ref_samples: ground truth samples @@ -173,26 +174,25 @@ def compute_stats(ref_sample: str, raw_sample: str) -> dict: c_f1 = _f1(c_precision, c_recall) # Compute word-level statistics - word_boundaries = _find_word_boudaries(ref_sample) - - correctly_tokenised_words = _count_correctly_tokenised_words( - sample, - word_boundaries - ) - w_precision = correctly_tokenised_words / np.sum(sample) - w_recall = correctly_tokenised_words / np.sum(ref_sample) - w_f1 = _f1(w_precision, w_recall) + # Find correctly tokenized words in the reference sample + word_boundaries = _find_word_boudaries(ref_sample) # Find correctly tokenized words in the sample ss_boundaries = _find_word_boudaries(sample) - tokenisation_indicators = _find_words_correctly_tokenised( + tokenization_indicators = _find_words_correctly_tokenised( word_boundaries, ss_boundaries ) - tokenisation_indicators = list( - map(lambda x: str(x), tokenisation_indicators) + correctly_tokenised_words = np.sum(tokenization_indicators) + + w_precision = correctly_tokenised_words / np.sum(sample) + w_recall = correctly_tokenised_words / np.sum(ref_sample) + w_f1 = _f1(w_precision, w_recall) + + tokenization_indicators = list( + map(lambda x: str(x), tokenization_indicators) ) return { @@ -211,7 +211,7 @@ def compute_stats(ref_sample: str, raw_sample: str) -> dict: 'f1': w_f1 }, 'global': { - 'tokenisation_indicators': "".join(tokenisation_indicators) + 'tokenisation_indicators': "".join(tokenization_indicators) } } @@ -267,29 +267,6 @@ def _find_word_boudaries(bin_reps) -> list: return list(zip(start_idx, end_idx)) -def _count_correctly_tokenised_words(bin_reps, word_boundaries) -> list: - """ - Count how many words are tokenized correctly - - :param str bin_reps: binary representation of a text - :param list[tuple(int, int)] word_boundaries: list of when each word starts and ends - - :return: no. correctly tokenized words - :rtype: int - """ - count = 0 - for st, end in word_boundaries: - pend = min(end, bin_reps.shape[0]) - if (bin_reps[st] == 1 and np.sum(bin_reps[st+1:pend]) == 0) \ - and ( - (pend == bin_reps.shape[0]) or - (pend != bin_reps.shape[0] and bin_reps[pend] == 1) - ): - count = count + 1 - - return count - - def _find_words_correctly_tokenised( ref_boundaries: list, predicted_boundaries: list diff --git a/pythainlp/tag/named_entity.py b/pythainlp/tag/named_entity.py index d480768fc..b6690018d 100644 --- a/pythainlp/tag/named_entity.py +++ b/pythainlp/tag/named_entity.py @@ -94,7 +94,7 @@ def get_ner( ) -> Union[List[Tuple[str, str]], List[Tuple[str, str, str]]]: """ This function tags named-entitiy from text in IOB format. - + :param string text: text in Thai to be tagged :param boolean pos: To include POS tags in the results (`True`) or exclude (`False`). The defualt value is `True` diff --git a/pythainlp/tokenize/__init__.py b/pythainlp/tokenize/__init__.py index 2db648f91..95170eb4d 100644 --- a/pythainlp/tokenize/__init__.py +++ b/pythainlp/tokenize/__init__.py @@ -20,7 +20,6 @@ def word_tokenize( ) -> List[str]: """ This function tokenizes running text into words. - :param str text: text to be tokenized :param str engine: name of the tokenizer to be used :param marisa_trie.Trie custom_dict: marisa dictionary trie @@ -29,7 +28,6 @@ def word_tokenize( Otherwise, whitespaces are omitted. :return: list of words :rtype: list[str] - **Options for engine** * *newmm* (default) - dictionary-based, Maximum Matching + Thai Character Cluster @@ -39,19 +37,15 @@ def word_tokenize( language-model-based * *icu* - wrapper for ICU (International Components for Unicode, using PyICU), dictionary-based - + * attacut - Wrapper for `AttaCut (https://github.com/PyThaiNLP/attacut)` .. warning:: * the option for engine named *ulmfit* has been deprecated since \ PyThaiNLP version 2.1 - :Note: - The parameter **custom_dict** can be provided as an argument \ only for *newmm*, *longest*, and *deepcut* engine. - :Example: - Tokenize text with different tokenizer: - >>> from pythainlp.tokenize import word_tokenize >>> >>> text = "โอเคบ่พวกเรารักภาษาบ้านเกิด" @@ -69,9 +63,10 @@ def word_tokenize( >>> >>> word_tokenize(text, engine="ulmfit") ['โอเค', 'บ่', 'พวกเรา', 'รัก', 'ภาษา', 'บ้านเกิด'] - + >>> tokenize.word_tokenize('โอเคบ่พวกเรารักภาษาบ้านเกิด', engine='attacut') + ['โอเค', 'บ่', 'พวกเรา', 'รัก', 'ภาษา', 'บ้านเกิด'] + >>> Tokenize text by omitiing whitespaces: - >>> from pythainlp.tokenize import word_tokenize >>> >>> text = "วรรณกรรม ภาพวาด และการแสดงงิ้ว " @@ -79,9 +74,7 @@ def word_tokenize( ['วรรณกรรม', ' ', 'ภาพวาด', ' ', 'และ', 'การแสดง', 'งิ้ว', ' '] >>> word_tokenize(text, engine="newmm", keep_whitespace=False) ['วรรณกรรม', 'ภาพวาด', 'และ', 'การแสดง', 'งิ้ว'] - Tokenize with default and custom dictionary: - >>> from pythainlp.corpus.common import thai_words >>> from pythainlp.tokenize import dict_trie, word_tokenize >>> @@ -123,6 +116,10 @@ def word_tokenize( elif engine == "icu": from .pyicu import segment + segments = segment(text) + elif engine == 'attacut': + from .attacut import segment + segments = segment(text) else: # default, use "newmm" engine from .newmm import segment @@ -134,7 +131,6 @@ def word_tokenize( return segments - def dict_word_tokenize( text: str, custom_dict: Trie = DEFAULT_DICT_TRIE, @@ -171,22 +167,17 @@ def sent_tokenize(text: str, engine: str = "whitespace+newline") -> List[str]: This function does not yet automatically recognize when a sentence actually ends. Rather it helps split text where white space and a new line is found. - :param str text: the text to be tokenized :param str engine: choose between *'whitespace'* or *'whitespace+newline'* :return: list of splited sentences :rtype: list[str] - **Options for engine** * *whitespace+newline* (default) - split by whitespace token \ and newline. * *whitespace* - split by whitespace token. Specifiaclly, with \ :class:`regex` pattern ``r" +"`` - :Example: - Split the text based on *whitespace* - >>> from pythainlp.tokenize import sent_tokenize >>> sentence_1 = "ฉันไปประชุมเมื่อวันที่ 11 มีนาคม" >>> sentence_2 = "ข้าราชการได้รับการหมุนเวียนเป็นระยะ \\ @@ -196,9 +187,7 @@ def sent_tokenize(text: str, engine: str = "whitespace+newline") -> List[str]: >>> sent_tokenize(sentence_2, engine="whitespace") ['ข้าราชการได้รับการหมุนเวียนเป็นระยะ', '\\nและได้รับมอบหมายให้ประจำในระดับภูมิภาค'] - Split the text based on *whitespace* and *newline* - >>> from pythainlp.tokenize import sent_tokenize >>> sentence_1 = "ฉันไปประชุมเมื่อวันที่ 11 มีนาคม" >>> sentence_2 = "ข้าราชการได้รับการหมุนเวียนเป็นระยะ \\ @@ -229,30 +218,23 @@ def subword_tokenize(text: str, engine: str = "tcc") -> List[str]: Thai contiguous characters namely `Thai Character Clusters (TCCs) \ `_ - TCCs are the units based on Thai spelling feature that could not be separated any character further such as 'ก็', 'จะ', 'ไม่', and 'ฝา'. If the following units are separated, they could not be spelled out. - This function apply the TCC rules to tokenizes the text into the smallest units. For example, the word 'ขนมชั้น' would be tokenized into 'ข', 'น', 'ม', and 'ชั้น' - :param str text: text to be tokenized :param str engine: the name subword tokenizer :return: list of subwords :rtype: list[str] - **Options for engine** * *tcc* (default) - Thai Character Cluster (Theeramunkong et al. 2000) * *ssg* - CRF syllable segmenter for Thai. * *etcc* - Enhanced Thai Character Cluster (Inrut et al. 2001) [In development] - :Example: - Tokenize text into subword based on *tcc* - >>> from pythainlp.tokenize import subword_tokenize >>> text_1 = "ยุคเริ่มแรกของ ราชวงศ์หมิง" >>> text_2 = "ความแปลกแยกและพัฒนาการ" @@ -262,9 +244,7 @@ def subword_tokenize(text: str, engine: str = "tcc") -> List[str]: >>> subword_tokenize(text_2, engine='tcc') ['ค', 'วา', 'ม', 'แป', 'ล', 'ก', 'แย', 'ก', 'และ', 'พัฒ','นา', 'กา', 'ร'] - Tokenize text into subword based on *etcc* **(Work In Progress)** - >>> from pythainlp.tokenize import subword_tokenize >>> text_1 = "ยุคเริ่มแรกของ ราชวงศ์หมิง" >>> text_2 = "ความแปลกแยกและพัฒนาการ" @@ -291,7 +271,6 @@ def syllable_tokenize(text: str, engine: str = "default") -> List[str]: This function is to tokenize text into syllable (Thai: พยางค์), a unit of pronunciation having one vowel sound. For example, the word 'รถไฟ' contains two syallbles including 'รถ', and 'ไฟ'. - Under the hood, this function uses :func:`pythainlp.tokenize.word_tokenize` with *newmm* as a tokenizer. The function tokenize the text with the dictionary of Thai words from @@ -299,17 +278,13 @@ def syllable_tokenize(text: str, engine: str = "default") -> List[str]: and then dictionary of Thai syllable from :func:`pythainlp.corpus.common.thai_syllables`. As a result, only syllables are obtained. - :param str text: input string to be tokenized :return: list of syllables where whitespaces in the text **are included** :rtype: list[str] - **Options for engine** * *default* * *ssg* - CRF syllable segmenter for Thai. - :Example: - >>> from pythainlp.tokenize import syllable_tokenize >>> >>> text = 'รถไฟสมัยใหม่จะใช้กำลังจากหัวรถจักรดีเซล หรือจากไฟฟ้า' @@ -340,7 +315,6 @@ def dict_trie(dict_source: Union[str, Iterable[str], Trie]) -> Trie: For more information on the trie data structure, see: `marisa-trie's Official Documentation \ `_ - :param string/list dict_source: a list of vocaburaries or a path to source file :return: a trie created from a dictionary input @@ -366,19 +340,16 @@ def dict_trie(dict_source: Union[str, Iterable[str], Trie]) -> Trie: return trie + class Tokenizer: """ This class allows users to pre-define custom dictionary along with tokenizer and encapsulate them into one single object. - It is an wrapper for both two functions including :func:`pythainlp.tokenize.word_tokenize`, and :func:`pythainlp.tokenize.dict_trie` - :Example: - Tokenizer object instantiated with :class:`marisa_trie.Trie` - >>> from pythainlp.tokenize import Tokenizer >>> from pythainlp.tokenize import Tokenizer, dict_trie >>> from pythainlp.corpus.common import thai_words @@ -392,9 +363,7 @@ class Tokenizer: >>> _tokenizer = Tokenizer(custom_dict=trie, engine='newmm') ['อะเฟเซีย', ' ', '(', 'Aphasia', ')', ' ', 'เป็น', 'อาการ', 'ผิดปกติ', 'ของ', 'การ', 'พูด'] - Tokenizer object instantiated with a list of words - >>> from pythainlp.tokenize import Tokenizer >>> from pythainlp.corpus.common import thai_words >>> @@ -403,12 +372,9 @@ class Tokenizer: >>> _tokenizer.word_tokenize(text) ['อะ', 'เฟเซีย', ' ', '(', 'Aphasia', ')', ' ', 'เป็น', 'อาการ', 'ผิดปกติ', 'ของ', 'การ', 'พูด'] - - Tokenizer object instantiated with a file path containing list of word separated with *newline* and explicitly set a new tokeneizer after initiation. - >>> from pythainlp.tokenize import Tokenizer >>> >>> PATH_TO_CUSTOM_DICTIONARY = './custom_dictionary.txtt' @@ -438,7 +404,6 @@ def __init__( ): """ Initialize tokenizer object - :param str: a file path, a list of vocaburaies* to be used to create a trie, or an instantiated :class:`marisa_trie.Trie` object. @@ -455,7 +420,6 @@ def __init__( def word_tokenize(self, text: str) -> List[str]: """ :param str text: text to be tokenized - :return: list of words, tokenized from the text :rtype: list[str] """ @@ -464,9 +428,8 @@ def word_tokenize(self, text: str) -> List[str]: def set_tokenize_engine(self, engine: str) -> None: """ Set the tokenizer - :param str engine: choose between different options of engine to token (i.e. *newmm*, *longest*, *deepcut*) - """ self.__engine = engine + diff --git a/pythainlp/tokenize/attacut.py b/pythainlp/tokenize/attacut.py new file mode 100644 index 000000000..07e12c906 --- /dev/null +++ b/pythainlp/tokenize/attacut.py @@ -0,0 +1,15 @@ +""" +Wrapper for AttaCut - Fast and Reasonably Accurate Word Tokenizer for Thai +:See Also: + * `GitHub repository `_ +""" +from typing import List + +import attacut + + +def segment(text: str) -> List[str]: + if not text or not isinstance(text, str): + return [] + + return attacut.tokenize(text) diff --git a/pythainlp/tokenize/deepcut.py b/pythainlp/tokenize/deepcut.py index 394444c85..1ae7aeab1 100644 --- a/pythainlp/tokenize/deepcut.py +++ b/pythainlp/tokenize/deepcut.py @@ -1,9 +1,7 @@ -# -*- coding: utf-8 -*- """ Wrapper for deepcut Thai word segmentation. deepcut is a Thai word segmentation library using Deep Neural, specifically, 1D Convolution Neural Network. - :See Also: * `GitHub repository `_ """ @@ -26,3 +24,4 @@ def segment(text: str, custom_dict: Union[Trie, List[str], str] = None) -> List[ return deepcut.tokenize(text, custom_dict) return deepcut.tokenize(text) + diff --git a/pythainlp/ulmfit/__init__.py b/pythainlp/ulmfit/__init__.py index 5e9f4d3f7..89dfbe2a8 100644 --- a/pythainlp/ulmfit/__init__.py +++ b/pythainlp/ulmfit/__init__.py @@ -5,8 +5,8 @@ """ import collections import re -from typing import List, Collection, Callable +from typing import List, Collection, Callable import emoji import html import numpy as np @@ -18,7 +18,8 @@ ''' # Fastai dependencies -The following codes are copied from copied from https://github.com/fastai/fastai/blob/master/fastai/text/transform.py +The following codes are copied from +https://github.com/fastai/fastai/blob/master/fastai/text/transform.py in order to avoid importing the entire fastai library ''' @@ -26,28 +27,67 @@ TK_REP = 'xxrep' TK_WREP = 'xxwrep' TK_END = 'xxend' +TK_URL ='xxurl' class BaseTokenizer(): - "Basic class for a tokenizer function." - def __init__(self, lang:str): self.lang = lang - def tokenizer(self, t:str) -> List[str]: return t.split(' ') - def add_special_cases(self, toks:Collection[str]): pass + """Basic class for a tokenizer function. (code from `fastai`)""" + def __init__(self, lang: str): self.lang = lang + + def tokenizer(self, t: str) -> List[str]: return t.split(' ') + + def add_special_cases(self, toks: Collection[str]): pass -def fix_html(x:str) -> str: - "List of replacements from html strings in `x`." +def replace_url(x): + """ + Replace url in `x` with TK_URL + + :param str x: text to replace url + + :return: text where urls are replaced + :rtype: str + + :Example: + + >>> from pythainlp.ulmfit import replace_url + >>> replace_url("go to github.com") + go to xxurl + """ + URL_PATTERN = r"""(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(? str: + """ + List of replacements from html strings in `x`. (code from `fastai`) + + :param str x: text to replace html string + + :return: text where html strings are replaced + :rtype: str + + :Example: + + >>> from pythainlp.ulmfit import fix_html + >>> fix_html("Anbsp;amp;nbsp;B @.@ ") + A & B. + """ re1 = re.compile(r' +') - x = x.replace('#39;', "'").replace('amp;', '&').replace('#146;', "'").replace( - 'nbsp;', ' ').replace('#36;', '$').replace('\\n', "\n").replace('quot;', "'").replace( - '
', "\n").replace('\\"', '"').replace('',UNK).replace(' @.@ ','.').replace( - ' @-@ ','-').replace(' @,@ ',',').replace('\\', ' \\ ') + x = x.replace('#39;', "'").replace('amp;', '&').replace( + '#146;', "'").replace('nbsp;', ' ').replace( + '#36;', '$').replace('\\n', "\n").replace('quot;', "'").replace( + '
', "\n").replace('\\"', '"').replace('', UNK).replace( + ' @.@ ', '.').replace(' @-@ ', '-').replace(' @,@ ', ',').replace( + '\\', ' \\ ') return re1.sub(' ', html.unescape(x)) -def rm_useless_spaces(t:str) -> str: - "Remove multiple spaces in `t`." + +def rm_useless_spaces(t: str) -> str: + """Remove multiple spaces in `t`. (code from `fastai`)""" return re.sub(' {2,}', ' ', t) -def spec_add_spaces(t:str) -> str: - "Add spaces around / and # in `t`. \n" + +def spec_add_spaces(t: str) -> str: + """Add spaces around / and # in `t`. \n (code from `fastai`)""" return re.sub(r'([/#\n])', r' \1 ', t) ''' @@ -74,6 +114,7 @@ def spec_add_spaces(t:str) -> str: _THAI2FIT_WORDS = get_corpus("words_th_thai2fit_201810.txt") _pythainlp_tokenizer = Tokenizer(custom_dict=_THAI2FIT_WORDS, engine="newmm") + # Download pretrained models def _get_path(fname: str) -> str: """ @@ -122,7 +163,7 @@ def tokenizer(text: str) -> List[str]: >>> >>> text = "อาภรณ์, จินตมยปัญญา ภาวนามยปัญญา" >>> ThaiTokenizer.tokenizer(text) - ['อาภรณ์', ',', ' ', 'จิน', 'ตม', 'ย', 'ปัญญา', + ['อาภรณ์', ',', ' ', 'จิน', 'ตม', 'ย', 'ปัญญา', ' ', 'ภาวนามยปัญญา'] >>> >>> word_tokenize(text, engine='ulmfit') @@ -139,8 +180,22 @@ def add_special_cases(self, toks): def replace_rep_after(text: str) -> str: """ Replace repetitions at the character level in `text` after the repetition. - This is done to prevent such case as 'น้อยยยยยยยย' becoming 'น้อ xxrep 8 ย'; - instead it will retain the word as 'น้อย xxrep 8' + This is done to prevent such case as 'น้อยยยยยยยย' becoming 'น้อ xxrep 8 ย' + ;instead it will retain the word as 'น้อย xxrep 8' + + :param str text: input text to replace character repetition + + :return: text with repetitive token **xxrep** and the counter + after character repetition + + :rtype: str + :Example: + + >>> from pythainlp.ulmfit import replace_rep_after + >>> + >>> text = "กาาาาาาา" + >>> replace_rep_after(text) + 'กาxxrep7 ' """ def _replace_rep(m): @@ -151,23 +206,39 @@ def _replace_rep(m): return re_rep.sub(_replace_rep, text) -def replace_wrep_post(toks:Collection): + +def replace_wrep_post(toks: Collection): """ - Replace reptitive words post tokenization; + Replace reptitive words post tokenization; fastai `replace_wrep` does not work well with Thai. + + :param list[str] toks: list of tokens + + :return: list of tokens where **xxwrep** token and the counter + is added in front of repetitive words. + :rtype: list[str] + + :Example: + + >>> from pythainlp.ulmfit import replace_wrep_post_nonum + >>> + >>> toks = ["กา", "น้ำ", "น้ำ", "น้ำ", "น้ำ"] + >>> replace_wrep_post(toks) + ['กา', 'xxwrep', '3', 'น้ำ'] + """ previous_word = None rep_count = 0 res = [] for current_word in toks+[TK_END]: - if current_word==previous_word: - rep_count+=1 - elif (current_word!=previous_word) & (rep_count>0): - res += [TK_WREP,str(rep_count),previous_word] - rep_count=0 + if current_word == previous_word: + rep_count += 1 + elif (current_word != previous_word) & (rep_count > 0): + res += [TK_WREP, str(rep_count), previous_word] + rep_count = 0 else: res.append(previous_word) - previous_word=current_word + previous_word = current_word return res[1:] @@ -186,7 +257,7 @@ def rm_brackets(text: str) -> str: return new_line -def ungroup_emoji(toks:Collection): +def ungroup_emoji(toks: Collection): "Ungroup emojis" res = [] for tok in toks: @@ -197,17 +268,34 @@ def ungroup_emoji(toks:Collection): res.append(tok) return res -def lowercase_all(toks:Collection): - """Lowercase all English words; + +def lowercase_all(toks: Collection): + """Lowercase all English words; English words in Thai texts don't usually have nuances of capitalization. """ return [tok.lower() for tok in toks] + def replace_rep_nonum(text: str) -> str: """ Replace repetitions at the character level in `text` after the repetition. - This is done to prevent such case as 'น้อยยยยยยยย' becoming 'น้อ xrep 8 ย'; - instead it will retain the word as 'น้อย xrep 8' + This is done to prevent such case as 'น้อยยยยยยยย' becoming 'น้อ xxrep ย'; + instead it will retain the word as 'น้อย xxrep ' + + :param str text: input text to replace character repetition + + :return: text with repetitive token **xxrep** after + character repetition + :rtype: str + + :Example: + + >>> from pythainlp.ulmfit import replace_rep_nonum + >>> + >>> text = "กาาาาาาา" + >>> replace_rep_nonum(text) + 'กา xxrep ' + """ def _replace_rep(m): c, cc = m.groups() @@ -215,38 +303,62 @@ def _replace_rep(m): re_rep = re.compile(r"(\S)(\1{3,})") return re_rep.sub(_replace_rep, text) -def replace_wrep_post_nonum(toks:Collection): + +def replace_wrep_post_nonum(toks: Collection): """ - Replace reptitive words post tokenization; + Replace reptitive words post tokenization; fastai `replace_wrep` does not work well with Thai. + + :param list[str] toks: list of tokens + + :return: list of tokens where **xxwrep** token is added in front of + repetitive words. + :rtype: list[str] + + :Example: + + >>> from pythainlp.ulmfit import replace_wrep_post_nonum + >>> + >>> toks = ["กา", "น้ำ", "น้ำ", "น้ำ", "น้ำ"] + >>> replace_wrep_post_nonum(toks) + ['กา', 'xxwrep', 'น้ำ'] + """ previous_word = None rep_count = 0 res = [] for current_word in toks+[TK_END]: - if current_word==previous_word: - rep_count+=1 - elif (current_word!=previous_word) & (rep_count>0): - res += [TK_WREP,previous_word] - rep_count=0 + if current_word == previous_word: + rep_count += 1 + elif (current_word != previous_word) & (rep_count > 0): + res += [TK_WREP, previous_word] + rep_count = 0 else: res.append(previous_word) - previous_word=current_word + previous_word = current_word return res[1:] -def remove_space(toks:Collection): + +def remove_space(toks: Collection): """ Do not include space for bag-of-word models. + + :param list[str] toks: list of tokens + + :return: list of tokens where space tokens (" ") are filtered out + :rtype: list[str] """ res = [] for t in toks: - if t!=' ': res.append(t) + if t != ' ': + res.append(t) return res # Pretrained paths # TODO: Let the user decide if they like to download (at setup?) _THWIKI_LSTM = dict( - wgts_fname=_get_path(_MODEL_NAME_LSTM), itos_fname=_get_path(_ITOS_NAME_LSTM) + wgts_fname=_get_path(_MODEL_NAME_LSTM), + itos_fname=_get_path(_ITOS_NAME_LSTM) ) # Preprocessing rules for Thai text @@ -259,30 +371,90 @@ def remove_space(toks:Collection): rm_useless_spaces, rm_useless_newlines, rm_brackets, + replace_url, ] + post_rules_th = [replace_wrep_post, ungroup_emoji, lowercase_all,] # sparse features pre_rules_th_sparse = pre_rules_th[1:] + [replace_rep_nonum] -post_rules_th_sparse = post_rules_th[1:] + [replace_wrep_post_nonum, remove_space] +post_rules_th_sparse = post_rules_th[1:] + [replace_wrep_post_nonum, + remove_space] + -def process_thai(text: str, pre_rules: Collection = pre_rules_th_sparse, tok_func:Callable = _pythainlp_tokenizer.word_tokenize, - post_rules: Collection = post_rules_th_sparse) -> Collection[str]: +def process_thai(text: str, pre_rules: Collection = pre_rules_th_sparse, + tok_func: Callable = _pythainlp_tokenizer.word_tokenize, + post_rules: Collection = post_rules_th_sparse) -> Collection[str]: """ Process Thai texts for models (with sparse features as default) + :param str text: text to be cleaned - :param pre_rules List: rules to apply before tokenization - :param tok_func Callable: tokenization function - :param post_rules List: rules to apply after tokenization + :param list[func] pre_rules: rules to apply before tokenization. + :param func tok_func: tokenization function (by default, **tok_func** is + :func:`pythainlp.tokenize.word_tokenize`) + + :param list[func] post_rules: rules to apply after tokenizations + :return: a list of cleaned tokenized texts + :rtype: list[str] + + + :Note: + - The default **pre-rules** consists of :func:`fix_html`, + :func:`pythainlp.util.normalize`, + :func:`spec_add_spaces`, + :func:`rm_useless_spaces`, + :func:`rm_useless_newlines`, + :func:`rm_brackets` + and :func:`replace_rep_nonum`. + + - The default **post-rules** consists of :func:`ungroup_emoji`, + :func:`lowercase_all`, :func:`replace_wrep_post_nonum`, + and :func:`remove_space`. + + :Example: + + 1. Use default pre-rules and post-rules: + + >>> from pythainlp.ulmfit import process_thai + >>> text = "บ้านนนนน () อยู่นานนานนาน 😂🤣😃😄😅 PyThaiNLP amp; " + >>> process_thai(text) + [บ้าน', 'xxrep', ' ', 'อยู่', 'xxwrep', 'นาน', '😂', '🤣', + '😃', '😄', '😅', 'pythainlp', '&'] + + 2. Modify pre_rules and post_rules arugments with + rules provided in :mod:`pythainlp.ulmfit`: + + >>> from pythainlp.ulmfit import ( + process_thai, + replace_rep_after, + fix_html, + ungroup_emoji, + replace_wrep_post, + remove_space) + >>> + >>> text = "บ้านนนนน () อยู่นานนานนาน 😂🤣😃😄😅 PyThaiNLP amp; " + >>> process_thai(text, + pre_rules=[replace_rep_after, fix_html], + post_rules=[ungroup_emoji, + replace_wrep_post, + remove_space] + ) + ['บ้าน', 'xxrep', '5', '()', 'อยู่', 'xxwrep', '2', 'นาน', '😂', '🤣', + '😃', '😄', '😅', 'PyThaiNLP', '&'] + + """ res = text - for pre in pre_rules: res = pre(res) + for pre in pre_rules: + res = pre(res) res = tok_func(res) - for post in post_rules: res = post(res) + for post in post_rules: + res = post(res) return res _tokenizer = ThaiTokenizer() + def document_vector(text: str, learn, data, agg: str = "mean"): """ This function vectorize Thai input text into a 400 dimension vector using @@ -326,7 +498,8 @@ def document_vector(text: str, learn, data, agg: str = "mean"): """ s = _tokenizer.tokenizer(text) - t = torch.tensor(data.vocab.numericalize(s), requires_grad=False).to(device) + t = torch.tensor(data.vocab.numericalize(s), + requires_grad=False).to(device) m = learn.model[0].encoder.to(device) res = m(t).cpu().detach().numpy() if agg == "mean": diff --git a/setup.py b/setup.py index 85739ef8b..bc8830c87 100644 --- a/setup.py +++ b/setup.py @@ -10,20 +10,21 @@ extras = { "artagger": ["artagger"], + "attacut": ["attacut"], "deepcut": ["deepcut", "keras", "tensorflow"], "icu": ["pyicu"], "ipa": ["epitran"], "ssg": ["ssg"], - "ml": ["fastai>=1.0.38", "keras", "numpy", "torch"], + "ml": ["keras", "numpy", "torch"], "ner": ["sklearn-crfsuite"], "thai2fit": ["emoji", "gensim", "numpy"], "thai2rom": ["torch", "numpy"], "benchmarks": ["numpy", "pandas"], "full": [ "artagger", + "attacut", "deepcut", "epitran", - "fastai>=1.0.38", "gensim", "keras", "numpy", @@ -39,7 +40,7 @@ setup( name="pythainlp", - version="2.1.dev2", + version="2.1.dev4", description="Thai Natural Language Processing library", long_description=readme, long_description_content_type="text/markdown", diff --git a/tests/data/sentences.yml b/tests/data/sentences.yml index 6d913a38d..3c8a0dcc9 100644 --- a/tests/data/sentences.yml +++ b/tests/data/sentences.yml @@ -39,4 +39,8 @@ binary_sentences: - expected: "10001010" actual: "10101000" - expected_count: 0 \ No newline at end of file + expected_count: 0 + - + expected: "10101001000" # "ฝน|ตก|ที่|ทะเล + actual: "10001001010" # "ฝนตก|ที่|ทะ|เล" + expected_count: 1 \ No newline at end of file diff --git a/tests/test_benchmarks.py b/tests/test_benchmarks.py index aad63fd76..e0c95892c 100644 --- a/tests/test_benchmarks.py +++ b/tests/test_benchmarks.py @@ -1,31 +1,29 @@ -import datetime -import os -import sys import unittest -import yaml + import numpy as np +import yaml +from pythainlp.benchmarks import word_tokenization -from pythainlp.benchmarks import word_tokenisation -with open("./tests/data/sentences.yml", 'r') as stream: +with open("./tests/data/sentences.yml", "r", encoding="utf8") as stream: TEST_DATA = yaml.safe_load(stream) class TestBenchmarksPackage(unittest.TestCase): def test_preprocessing(self): - self.assertIsNotNone(word_tokenisation.preprocessing( + self.assertIsNotNone(word_tokenization.preprocessing( txt="ทดสอบ การ ทำ ความสะอาด ข้อมูลok" )) def test_benchmark_not_none(self): - self.assertIsNotNone(word_tokenisation.benchmark( + self.assertIsNotNone(word_tokenization.benchmark( ["วัน", "จัน", "ทร์", "สี", "เหลือง"], ["วัน", "จันทร์", "สี", "เหลือง"] )) def test_binary_representation(self): sentence = "อากาศ|ร้อน|มาก|ครับ" - rept = word_tokenisation._binary_representation(sentence) + rept = word_tokenization._binary_representation(sentence) self.assertEqual( [1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0], @@ -36,9 +34,9 @@ def test_compute_stats(self): for pair in TEST_DATA['sentences']: exp, act = pair['expected'], pair['actual'] - result = word_tokenisation.compute_stats( - word_tokenisation.preprocessing(exp), - word_tokenisation.preprocessing(act) + result = word_tokenization.compute_stats( + word_tokenization.preprocessing(exp), + word_tokenization.preprocessing(act) ) self.assertIsNotNone(result) @@ -50,7 +48,7 @@ def test_benchmark(self): expected.append(pair['expected']) actual.append(pair['actual']) - df = word_tokenisation.benchmark(expected, actual) + df = word_tokenization.benchmark(expected, actual) self.assertIsNotNone(df) @@ -59,10 +57,15 @@ def test_count_correctly_tokenised_words(self): sample = np.array(list(d['actual'])).astype(int) ref_sample = np.array(list(d['expected'])).astype(int) - wb = list(word_tokenisation._find_word_boudaries(ref_sample)) + sb = list(word_tokenization._find_word_boudaries(sample)) + rb = list(word_tokenization._find_word_boudaries(ref_sample)) + + # in binary [{0, 1}, ...] + correctly_tokenized_words = word_tokenization\ + ._find_words_correctly_tokenised(rb, sb) self.assertEqual( - word_tokenisation._count_correctly_tokenised_words(sample, wb), + np.sum(correctly_tokenized_words), d['expected_count'] ) @@ -72,7 +75,7 @@ def test_words_correctly_tokenised(self): expected = "01" - labels = word_tokenisation._find_words_correctly_tokenised(r, s) + labels = word_tokenization._find_words_correctly_tokenised(r, s) self.assertEqual(expected, "".join(np.array(labels).astype(str))) def test_flatten_result(self): @@ -81,5 +84,5 @@ def test_flatten_result(self): key2=dict(v2=7) ) - actual = word_tokenisation._flatten_result(result) - self.assertEqual(actual, {'key1:v1': 6, 'key2:v2': 7}) \ No newline at end of file + actual = word_tokenization._flatten_result(result) + self.assertEqual(actual, {'key1:v1': 6, 'key2:v2': 7}) diff --git a/tests/test_tokenize.py b/tests/test_tokenize.py index 9ddc4ed83..e4aca4a9e 100644 --- a/tests/test_tokenize.py +++ b/tests/test_tokenize.py @@ -12,6 +12,7 @@ ) from pythainlp.tokenize import DEFAULT_DICT_TRIE, Tokenizer from pythainlp.tokenize import deepcut as tokenize_deepcut +from pythainlp.tokenize import attacut from pythainlp.tokenize import ( dict_trie, dict_word_tokenize, @@ -70,6 +71,9 @@ def test_word_tokenize(self): self.assertIsNotNone( word_tokenize("หมอนทองตากลมหูว์MBK39", engine="XX") ) + self.assertIsNotNone( + word_tokenize("หมอนทองตากลมหูว์MBK39", engine="attacut") + ) self.assertIsNotNone(dict_trie(())) self.assertIsNotNone(dict_trie(("ทดสอบ", "สร้าง", "Trie"))) @@ -174,6 +178,16 @@ def test_word_tokenize_newmm(self): ["จุ๋ม", "ง่วง"], ) + + def test_word_tokenize_attacut(self): + self.assertEqual(attacut.segment(None), []) + self.assertEqual(attacut.segment(""), []) + self.assertEqual( + word_tokenize("ฉันรักภาษาไทยเพราะฉันเป็นคนไทย", engine="attacut"), + ['ฉัน', 'รัก', 'ภาษา', 'ไทย', 'เพราะ', 'ฉัน', 'เป็น', 'คน', 'ไทย'], + ) + + def test_sent_tokenize(self): self.assertEqual(sent_tokenize(None), []) self.assertEqual(sent_tokenize(""), []) diff --git a/tests/test_ulmfit.py b/tests/test_ulmfit.py index 1401190d5..5084f2dfe 100644 --- a/tests/test_ulmfit.py +++ b/tests/test_ulmfit.py @@ -2,10 +2,36 @@ import datetime import os -import sys import unittest -from pythainlp.ulmfit import * +from pythainlp.corpus import get_corpus +from pythainlp.tokenize import Tokenizer +from pythainlp.ulmfit import ( + ThaiTokenizer, + BaseTokenizer, + fix_html, + _THWIKI_LSTM, + pre_rules_th, + post_rules_th, + pre_rules_th_sparse, + post_rules_th_sparse, + rm_useless_spaces, + spec_add_spaces, + rm_useless_newlines, + rm_brackets, + ungroup_emoji, + lowercase_all, + replace_rep_nonum, + replace_rep_after, + replace_wrep_post, + replace_wrep_post_nonum, + remove_space, + process_thai +) + +_THAI2FIT_WORDS = get_corpus("words_th_thai2fit_201810.txt") +_pythainlp_tokenizer = Tokenizer(custom_dict=_THAI2FIT_WORDS, engine="newmm") + class TestUlmfitPackage(unittest.TestCase): @@ -13,9 +39,152 @@ def test_ThaiTokenizer(self): self.thai = ThaiTokenizer() self.assertIsNotNone(self.thai.tokenizer("ทดสอบการตัดคำ")) self.assertIsNone(self.thai.add_special_cases(["แมว"])) + + def test_BaseTokenizer(self): + self.base = BaseTokenizer(lang='th') + self.assertIsNotNone(self.base.tokenizer("ทดสอบ การ ตัด คำ")) + self.assertIsNone(self.base.add_special_cases(["แมว"])) + def test_load_pretrained(self): self.assertIsNotNone(_THWIKI_LSTM) + def test_pre_rules_th(self): self.assertIsNotNone(pre_rules_th) + def test_post_rules_th(self): self.assertIsNotNone(post_rules_th) + + def test_pre_rules_th(self): + self.assertIsNotNone(pre_rules_th_sparse) + + def test_post_rules_th(self): + self.assertIsNotNone(post_rules_th_sparse) + + def test_fix_html(self): + self.assertEqual( + fix_html("Some HTML text
"), + "Some HTML& text\n") + + def test_rm_useless_spaces(self): + self.assertEqual( + rm_useless_spaces("Inconsistent use of spaces."), + "Inconsistent use of spaces.") + + def test_spec_add_spaces(self): + self.assertEqual( + spec_add_spaces("I #like to #put #hashtags #everywhere!"), + "I # like to # put # hashtags # everywhere!") + + def test_replace_rep_after(self): + self.assertEqual( + replace_rep_after("น้อยยยยยยยย"), + "น้อยxxrep8 ") + + def test_replace_rep_nonum(self): + self.assertEqual( + replace_rep_nonum("น้อยยยยยยยย"), + "น้อย xxrep ") + + def test_replace_wrep_post(self): + self.assertEqual( + replace_wrep_post(["น้อย", "น้อย"]), + ["xxwrep", "1", "น้อย"]) + + self.assertEqual( + replace_wrep_post(["นก", "กา", "กา", "กา"]), + ["นก", "xxwrep", "2", "กา"]) + + def test_replace_wrep_post_nonum(self): + self.assertEqual( + replace_wrep_post_nonum(["น้อย", "น้อย"]), + ["xxwrep", "น้อย"]) + + self.assertEqual( + replace_wrep_post_nonum(["นก", "กา", "กา", "กา"]), + ["นก", "xxwrep", "กา"]) + + def test_remove_space(self): + self.assertEqual( + remove_space([" ", "น้อย", " ", "."]), + ["น้อย", "."]) + + def test_rm_useless_newlines(self): + self.assertEqual( + rm_useless_newlines("text\n\n"), + "text ") + + def test_rm_brackets(self): + self.assertEqual( + rm_brackets("()()(ข้อความ)"), + "(ข้อความ)") + self.assertEqual( + rm_brackets("[][][ข้อความ]"), + "[ข้อความ]") + self.assertEqual( + rm_brackets("{}{}{ข้อความ}"), + "{ข้อความ}") + + def test_ungroup_emoji(self): + self.assertEqual( + ungroup_emoji("👍👍👍"), + ["👍", "👍", "👍"]) + + def test_lowercase_all(self): + self.assertEqual( + lowercase_all("HeLlO ."), + ['h', 'e', 'l', 'l', 'o', ' ', '.']) + + def test_process_thai_1(self): + """rules for sparse features""" + + text = "👍👍👍 #AnA มากกกก น้อยน้อย ().1146" + + actual = process_thai(text) + + # after pre_rules_th_sparse + # >>> "👍👍👍 # Ana มาก xxrep น้้อยน้อย .1146" + # + # after tokenize with word_tokenize(engine="newmm") + # >>> ["👍👍👍", " ", "#", " ","Ana", " ", "มาก", "xxrep", + # " ", "น้อย", "น้อย", " ", ".", "1146"] + # + # after post_rules_th + # - remove whitespace token (" ") + # >>> ["xxwrep, "👍", "#", "ana", "มาก", + # "xxrep", " ", "xxwrep", "น้อย", ".", "1146"] + + expect = ["xxwrep", "👍", "#", "ana", "มาก", "xxrep", + " ", "xxwrep", "น้อย", ".", "1146"] + + self.assertEqual(actual, expect) + + def test_process_thai_2(self): + """rules for dense features""" + + text = "👍👍👍 #AnA มากกกก น้อยน้อย ().1146" + + actual = process_thai(text, + pre_rules=pre_rules_th, + post_rules=post_rules_th, + tok_func=_pythainlp_tokenizer.word_tokenize) + + # after pre_rules_th + # >>> "👍👍👍 # Ana มากxxrep4 น้้อยน้อย .1146" + # + # after tokenize with word_tokenize(engine="newmm") + # >>> ["👍👍👍", " ", "#", "Ana", " ", "มาก", "xxrep", "4", + # " ", "น้อย", "น้อย", " ", ".", "1146"] + # after post_rules_th + # -- because it performs `replace_wrep_post` before `ungroup_emoji`, + # 3 repetitive emoji are not marked with special token "xxwrep num" + # + # >>> ["👍", "👍","👍", " ", "#", "ana", " ", "มาก", + # "xxrep", "4", " ", "xxwrep", "1", "น้อย", " ", + # ".", "1146"] + + expect = ["👍", "👍", "👍", " ", "#", " ", + "ana", " ", "มาก", "xxrep", "4", + " ", "xxwrep", "1", "น้อย", " ", + ".", "1146"] + + self.assertEqual(actual, expect)