<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Phylypo Tum on Medium]]></title>
        <description><![CDATA[Stories by Phylypo Tum on Medium]]></description>
        <link>https://medium.com/@phylypo?source=rss-bac53c544b44------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*7UyThQJn0k6mApga</url>
            <title>Stories by Phylypo Tum on Medium</title>
            <link>https://medium.com/@phylypo?source=rss-bac53c544b44------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 13:04:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@phylypo/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Khmer Semantic Search Using Text Embeddings]]></title>
            <link>https://medium.com/@phylypo/khmer-semantic-search-using-text-embeddings-1b20f3e6e00c?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/1b20f3e6e00c</guid>
            <category><![CDATA[text-embedding]]></category>
            <category><![CDATA[labse]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[semantic-search]]></category>
            <category><![CDATA[khmer]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Mon, 01 Dec 2025 20:22:35 GMT</pubDate>
            <atom:updated>2025-12-01T20:22:35.114Z</atom:updated>
            <content:encoded><![CDATA[<h3>Goal</h3><p>Our goal is to develop a contextually relevant search system for the Khmer language using text embeddings generated by a Large Language Model (LLM). Instead of relying on traditional keyword matching, this approach enables the search engine to understand the meaning and context behind words — returning results that are semantically related.</p><p>To achieve this, we experimented with several embedding models and found the Language-agnostic BERT Sentence Embedding (LaBSE) model [4] to perform best for Khmer. The embeddings produced by LaBSE are stored and queried through a vector database, enabling powerful semantic retrieval.</p><p>In this post, we’ll walk through the end-to-end implementation using Postgres DB, and share how the results revealed some surprising cross-lingual connections between Khmer and English terms.</p><h3>Previous Works</h3><h3>Khmer Word Search (Buoy et al.)</h3><p>One notable approach comes from Buoy et al. (2021) in <em>“Khmer Word Search: Challenges, Solutions, and Semantic-Aware Search” </em>[2112.08918]. This study focuses on solving practical problems with Khmer script that make word search difficult, such as words that look the same but are written differently, spelling variations, and stacked versus unstacked syllables.</p><p>To address these issues, the authors created several processing steps: character normalization to make spellings consistent, spell-checking at both the letter and sound levels (using a G2P model and the SymSpell algorithm), and a FastText word-embedding model to find semantically query words.</p><p>Word-embedding model was trained on Khmer text from websites and news articles to create embedding vectors for each term. When a user enters a search term, the system uses these embedding to find several related terms that have similar embedding from FastText. The searches then use these terms as OR query. This approach improves <strong>recall </strong>by finding more relevant documents even when words are written differently or different words completely.</p><p>Buoy’s method improves Khmer search by fixing spelling and pronunciation differences and expanding queries with related terms. However, it works mainly on individual words and does not fully capture the broader context like phrase or sentences.</p><p><em>As a side notes, if you need a start on Khmer corpora, we have some available on github (</em><a href="https://github.com/phylypo/khmer-text-data"><em>https://github.com/phylypo/khmer-text-data</em></a><em>, </em><a href="https://github.com/phylypo/segmentation-crf-khmer/tree/master/data"><em>segmentation-crf-khmer</em></a><em>) that includes Wikipedia, Oscar and 10,000 Khmer news articles that we crawled in 2019.</em></p><h3>Khmer Semantic Search Engine (KSE)</h3><p>Another approach is by Nimol Thuon (2024) in <em>“Khmer Semantic Search Engine (KSE): Digital Information Access and Document Retrieval” </em>[2406.09320].</p><p>The paper presents KSE, a system designed to improve Khmer search results using three parts: keyword search, ontology-based meaning expansion, and weighted ranking.</p><p>The system first identifies important words in each document using TF-IDF and basic text processing. It then uses a tourism ontology — a structured map of related places and terms — to better interpret user queries. Finally, it ranks results by giving more weight to keywords found in titles than in the body text.</p><p>KSE was tested on about 1,150 tourism articles, with human reviewers providing relevance scores. The system showed that combining keyword search with ontology relationships can improve accuracy in domain-specific Khmer search</p><p>KSE is essentially an ontology-enhanced keyword search engine. It enhances traditional keyword search by using domain relationships to expand queries.</p><p>Both early approaches expand the input query to more terms and perform keyword search on the document.</p><h3>Introduction to Embeddings</h3><p>Word embeddings are a foundational concept in <strong>natural language processing (NLP)</strong>. They represent words as <strong>vectors of decimal numbers</strong>, capturing semantic meaning in a numerical form that computers can process.</p><p>One of the earliest and most influential models in this area was <strong>Word2Vec </strong>[3], which learns these representations by analyzing large text corpora and identifying words that frequently appear together. Through this process, Word2Vec captures <strong>semantic relationships</strong> between words — how they relate in meaning rather than just in spelling or frequency.</p><p>A well-known example of this capability is the analogy:</p><blockquote>King - Man + Woman ≈ Queen</blockquote><p>This simple vector operation illustrates how Word2Vec encodes relationships like gender and royalty directly within the embedding space. The idea that meaning can be represented and manipulated mathematically became a cornerstone for future advances in NLP.</p><p>Today, this foundational concept has evolved into modern text embedding models, such as OpenAI’s text-embedding-3. These newer models operate in high-dimensional vector spaces, capturing deeper contextual and semantic nuances across entire sentences or paragraphs. As a result, they significantly enhance tasks like semantic search.</p><h3>Text Embeddings for Context-Aware</h3><p>Our goal is to enhance Khmer language search by moving beyond traditional keyword matching and leveraging text embeddings. Earlier approaches — such as Word2Vec or FastText — work well for representing individual words but often fail to capture the contextual meaning of phrases or sentences. For example, the word <em>“bank”</em> can refer to an <em>“investment bank”</em> or a <em>“river bank,”</em> depending on context. Text embeddings address this limitation by representing the semantic meaning of entire phrases and sentences, enabling more contextually relevant search results.</p><p>This approach aligns with techniques commonly used in Retrieval-Augmented Generation (RAG) systems, where embeddings are used to retrieve the most relevant documents to assist Large Language Models (LLMs) in generating accurate and contextually aware responses. We recognize the increasing capability of modern LLMs — such as Google Gemini and OpenAI’s GPT-5 — in understanding and representing Khmer text, and we aim to leverage these advances to improve Khmer search performance.</p><p>One key advantage of using embeddings is their tolerance to spelling variations and misspellings, as semantically similar phrases often appear close together in the embedding space — provided the model has seen similar examples during training. Since we are using pre-trained models without direct access to their training data, we plan to spot-check and analyze the results to infer their effectiveness for Khmer content.</p><p>To identify the best-performing approach, we will evaluate both open-source and commercial embedding models (including OpenAI’s state-of-the-art offerings). Our evaluation focuses on how well these models generate high-quality, context-aware embeddings for Khmer text, which are crucial for building a robust Khmer Semantic Search system.</p><h3>Evaluate Embeddings Models</h3><p>We look at some candidates and narrow down to two models from Open Source and commercial. Here are some candidates we looked at:</p><h4>Open Source Multilingual Embedding Models</h4><p><strong>LaBSE (Language-agnostic BERT Sentence Embeddings) [4]</strong></p><ul><li>Developed by Google, trained in 109<strong> languages</strong> (Khmer included).</li><li>Works well for cross-lingual semantic similarity.</li><li>Widely used baseline for multilingual RAG.</li></ul><p><strong>distiluse-base-multilingual-cased-v2</strong> (from <em>sentence-transformers</em>)</p><ul><li>A distilled version of multilingual Universal Sentence Encoder.</li><li>Supports <strong>50+ languages</strong>, including Khmer.</li><li>More lightweight than LaBSE, often faster in production.</li></ul><h4>Commercial API Models</h4><p><strong>OpenAI text-embedding-3-large or text-embedding-3-small</strong></p><ul><li>Trained on a very wide set of languages (unspecified about Khmer).</li><li>High-quality embeddings with cross-lingual alignment.</li><li>Scales easily for production RAG pipelines.</li></ul><p><strong>Cohere Multilingual Embeddings</strong></p><ul><li>Strong cross-lingual semantic search performance.</li><li>Support over 100 languages including Khmer (<a href="https://docs.cohere.com/docs/cohere-embed">Cohere’s Embed Models (Details and Application) | Cohere</a>)</li></ul><p>We chose two options (one from commercial and one from open source) based on their features description. We chose LaBSE and commercial and OpenAI’s text-embedding-3 models based on Khmer support, performance, and accessibility. Here are some highlights between the two models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/848/1*vA6bAF4_82DwczCClcevvQ.png" /></figure><h3>Evaluation Setup</h3><p>In order to compare the performance of these two models, we performed a series of basic tests to gain insight into the embedding space and the models’ performance on Khmer text. While the raw vector values are not directly interpretable, we compare them using a <strong>cosine similarity score</strong> (ranging from 0 for unrelated to 1 for perfectly related) to measure the semantic relationship between terms. These preliminary tests are not intended to be a concrete quantitative evaluation score but rather to provide a qualitative sense of each model’s language support for Khmer.</p><h4>Test Criteria 1: Translation (Khmer — English)</h4><p>The first evaluation criterion is designed to measure the cross-lingual semantic alignment between English and Khmer terms. Achieving a high score on this test is a strong indication that an embedding model successfully represents equivalent words from both languages within the same shared vector space.</p><p>The table below presents the cosine similarity scores for direct translations:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*QhLBeryoJY3nyOWkk-WUow.png" /></figure><p>The results, which use Cosine Similarity (where 1.0 is very similar and 0.0 is no similarity), show a stark contrast, with scores decisively <strong>favoring LaBSE</strong> for cross-lingual translation tasks.</p><h4>Test Criteria 2: King-queen analogy</h4><p>This test uses the well-known “King-Queen” analogy to illustrate how the model’s embedding space captures semantic relationships through vector arithmetic. While not a core quantitative metric, it provides an insight into how relative categories are encoded within the vector space.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/990/1*A67Pu0xYP6oMB2RrnwdBrQ.png" /></figure><p>For the Khmer analogy, a custom test such as “(boy or male) — (man) + (woman) ≈ (girl or female)” yielded a high similarity score of 0.9263 with LaBSE. This, combined with the other results, suggests that the LaBSE model provides clear support for vector arithmetic and successfully encodes semantic relationships like gender and royalty in the Khmer embedding space, again decisively For the Khmer analogy, a custom test such as “(boy or male) — (man) + (woman) ≈ (girl or female)” yielded a high similarity score of 0.9263 with LaBSE.</p><p>This, combined with the other results, suggests that the LaBSE model provides clear support for vector arithmetic and successfully encodes semantic relationships like gender and royalty in the Khmer embedding space, again decisively <strong>favoring LaBSE</strong> over the OpenAI model.over the OpenAI model.</p><pre>words = [&quot;ប្រុស&quot;,  # boy or male<br>         &quot;បុរស&quot;,  # man<br>         &quot;ស្ត្រី&quot;,    # woman <br>         &quot;ស្រី&quot;]    # girl or female<br># Cosine similarity: 0.9263  : analogy (male - man + woman = female)<br># Cosine similarity: 0.6896  : male, female<br># Cosine similarity: 0.7360  : man, woman<br># Cosine similarity: 0.9448  : male, man<br># Cosine similarity: 0.8900  : woman, female</pre><h4>Test Criteria 3: Similarity and Dissimilarity</h4><p>This test begins with a basic check using keywords to determine how similar words cluster in the embedding space and, conversely, how unrelated words are represented with lower similarity scores.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1009/1*Q1N-Y7wws3j2WJfEvU5Tfg.png" /><figcaption>**The OpenAI embedding model used is <strong>text-embedding-3-small</strong>.</figcaption></figure><p>Testing with the OpenAI large model (<strong>text-embedding-3-large</strong>) showed that similarity scores for unrelated Khmer terms (0.47 and 0.38) were <em>higher</em> than the score for related “eat” synonyms (0.32). This suggests the OpenAI embedding model does not cluster the embedding space for Khmer text as effectively as LaBSE.</p><h4>Model Testing Conclusion:</h4><p>Our initial tests were limited to single terms and short phrases. Despite this, LaBSE consistently delivered better similarity scores in both cross-lingual and vector arithmetic evaluations, showing a strong correlation between Khmer and English terms. Based on this preliminary evidence, LaBSE is selected as the foundational embedding model for our Khmer Semantic Search system.</p><h3>LaBSE for Khmer Text Embedding</h3><p>LaBSE is an excellent choice for a search system, especially for resource-limited languages like Khmer, because it creates strong, multilingual sentence embeddings that maintain semantic consistency across languages, which is essential for effective search.</p><h4>Tokenization</h4><p>Since Khmer is <strong>morphologically complex and has no spaces between words</strong>, proper <strong>tokenization</strong> matters. The use of a Khmer word segmentation before embedding might be a good strategy to improve accuracy since many tokenizers may not know how to segment Khmer words. But if their training process does not run through this process, this can affect the embedding process in a negative way. So next we will test how the tokenization works for this model.</p><p>For Khmer text, we use the zero width space “\u200B” character as a word separation for spell check and other purposes. Here is an example Khmer text that uses zero width space between words, not visible.</p><p>Khmer text: តាម​ទម្លាប់​នៅ​ក្នុង​សហគមន៍​ខ្មែរ កាលណា​មាន</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/532/1*sR5xQT-_mePcE2Um8kM9PQ.png" /><figcaption>Visual image from Open Office Write that show gray vertical bar as the zero width space (“\u200B”)</figcaption></figure><p>We are going to test the tokenizer to see how it treats “\u200B” characters.</p><p>We are going to test the tokenizer to see how it treats “\u200B” characters.</p><p>Input text: តាម​ទម្លាប់​នៅ​ក្នុង​សហគមន៍​ខ្មែរ កាលណា​មាន</p><p>Tokens: [‘តាម’, ‘##ទ’, ‘##ម្លាប់’, ‘##នៅ’, ‘##ក្នុង’, ‘##ស’, ‘##ហ’, ‘##គ’, ‘##មន៍’, ‘##ខ្មែរ’, ‘កាល’, ‘##ណា’, ‘##មាន’]</p><p>Token IDs: [23416, 118714, 499577, 107664, 113574, 43611, 214354, 200777, 443523, 119830, 36040, 68867, 47903]</p><p>The original text has 8 words, the model tokenizes this into 13 tokens. The ‘##’ characters in the token indicate this token part of the previous word. For example: កា​លណា​ as two tokens ‘កាល’ and ‘##ណា’. The later token with ## means that it preceded by the previous token.</p><p>Now let’s test without any spaces:</p><p>Original text without any zero width spaces: តាមទម្លាប់នៅក្នុងសហគមន៍ខ្មែរ កាលណាមាន</p><p>Tokens: [‘តាម’, ‘##ទ’, ‘##ម្លាប់’, ‘##នៅ’, ‘##ក្នុង’, ‘##ស’, ‘##ហ’, ‘##គ’, ‘##មន៍’, ‘##ខ្មែរ’, ‘កាល’, ‘##ណា’, ‘##មាន’]</p><p>Token IDs: [23416, 118714, 499577, 107664, 113574, 43611, 214354, 200777, 443523, 119830, 36040, 68867, 47903]</p><p>The result is the same 13 tokens as the text with zero width spaces. Now tries by adding zero width space “\u200B” characters to many incorrect position to see how the tokenizer output:</p><p>Text: តា​ម​ទម្លាប់​នៅ​ក្នុ​ង​សហគមន៍​ខ្មែរ កា​លណា​មា​ន</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/528/1*i_EXt90cgLPxuWgmyfvBnw.png" /><figcaption>Visual image from Open office that show gray vertical bar as the zero width space (Unicode character \u200B)</figcaption></figure><p>Tokens: [‘តាម’, ‘##ទ’, ‘##ម្លាប់’, ‘##នៅ’, ‘##ក្នុង’, ‘##ស’, ‘##ហ’, ‘##គ’, ‘##មន៍’, ‘##ខ្មែរ’, ‘កាល’, ‘##ណា’, ‘##មាន’]</p><p>Token IDs: [23416, 118714, 499577, 107664, 113574, 43611, 214354, 200777, 443523, 119830, 36040, 68867, 47903]</p><p>The consistent token output across both tests confirms that the LaBSE tokenizer effectively <strong>removes the zero-width space (\u200B) character</strong> during preprocessing, meaning this character has no impact on tokenization.</p><p>However, in both results, many tokens were subword units (indicated by the ## prefix), showing the model was not tokenizing to individual Khmer words. To investigate the potential for improvement, we manually separated the words using a standard space:</p><p>Text: តា​ម ​ទម្លាប់​ នៅ​ ក្នុ​ង​ សហគមន៍​ ខ្មែរ កា​លណា​ មា​ន</p><p>Tokens: [‘តាម’, ‘ទម្លាប់’, ‘នៅ’, ‘ក្នុង’, ‘សហគមន៍’, ‘ខ្មែរ’, ‘កាល’, ‘##ណា’, ‘មាន’]</p><p>Token IDs: [23416, 381475, 16636, 17367, 160164, 43067, 36040, 68867, 16887]</p><p>As shown above, explicit spacing did result in the tokenizer recognizing whole words like ‘ទម្លាប់’ and ‘សហគមន៍’ as single tokens. While tokenizing to whole words appears logically sound, the key concern is the model’s training data. If the corpus used to train LaBSE was unsegmented, then explicitly adding spaces now might negatively impact the quality of the resulting embedding vectors. Conversely, if the training text was segmented, then adding spaces would be the correct approach. Given that Khmer uses spaces to separate phrases or clauses rather than individual words, this choice carries significant contextual implications. Therefore, the critical next step is to empirically check the impact on embedding quality by comparing the cross-lingual similarity scores between English and Khmer for texts with and without manual word spacing.</p><p>Text: អ្វីទៅជាស្នេហា?</p><p>Tokens: [‘អ្វី’, ‘##ទៅ’, ‘##ជា’, ‘##ស’, ‘##្ន’, ‘##េ’, ‘##ហ’, ‘##ា’, ‘?’]</p><blockquote># Cosine similarity: (KH vs EN) អ្វីទៅជាស្នេហា? | What is love? =&gt; 0.9713</blockquote><p>The result above shows a high similarity (0.971) between the unsegmented Khmer sentence and its English translation. We then tested the effect of manual word segmentation:</p><p>Text: អ្វី ទៅ ជា ស្នេហា?</p><p>Tokens: [‘អ្វី’, ‘ទៅ’, ‘ជា’, ‘ស្នេហា’, ‘?’]</p><blockquote># Cosine similarity: (KH vs EN) អ្វី ទៅ ជា ស្នេហា? | What is love? =&gt; 0.9694</blockquote><p>The similarity score for the manually segmented text (0.969) is just slightly lower (a difference of 0.002). This demonstrates the model’s tolerance: even when the unsegmented input resulted in multiple subword tokens (e.g., the word ស្នេហា “love” being split), the LaBSE model was still able to generate highly relevant vectors. We obtained similar results across five other sentences (see the appendix).</p><p>Our experiments show that manually introducing spaces for explicit word segmentation does not improve the model’s effectiveness. In fact, sentences with manual segmentation resulted in a slightly lower average cross-lingual similarity score (5.33) compared to the unsegmented input (5.36) across six test examples. This suggests that the text used to train the LaBSE model may not have been pre-segmented using a Khmer word tokenizer. Nonetheless, the model demonstrates robustness, accommodating both segmented and unsegmented text inputs effectively, as the resulting similarity scores are extremely close.</p><h3>System Overview</h3><p>The architecture for the Khmer Semantic Search system is primarily implemented using a <strong>PostgreSQL vector database</strong>, with an alternative solution for Mongo Atlas detailed in the Appendix.</p><p>The system consists of the following key components:</p><ol><li><strong>Embedding API Service:</strong> An API service is used to generate the numerical representations (text embeddings) of Khmer input. This service utilizes the LaBSE model and provides the necessary real-time embedding for user queries, as well as offline batch embedding for the main data corpus.</li><li><strong>Vector Datastore (Embedding Storage):</strong> This is a dedicated vector database (e.g., PostgreSQL with the pgvector extension) that stores the pre-computed text embeddings of all searchable Khmer content.</li><li><strong>Query Processing and Retrieval:</strong> This component manages the search workflow to deliver semantically relevant results:<br>- It first sends the user’s query to the <strong>Embedding API Service</strong> to generate a corresponding vector embedding.<br>- It then performs a similarity search on the <strong>Vector Datastore</strong> using the query embedding to find and rank the matched entries with the highest similarity scores.</li></ol><h3>Implementation Steps</h3><h4>Embedding API Service</h4><p>In our environment, we use fastAPI to wrap our Python code to generate the embedding.</p><ol><li>Install a few components such as fastapi and sentence-transformers for LaBSE</li><li>With our Python code, create an endpoint to process the input and generate the output of the embedding vector.</li></ol><p>Minimal code to generate the embeddings:</p><pre>from sentence_transformers import SentenceTransformer<br># Load LaBSE model once at startup<br>model = SentenceTransformer(&quot;sentence-transformers/LaBSE&quot;)<br>def get_embedding(q: str = Query(..., description=&quot;Input text to embed&quot;)):<br>    # Encode the text using LaBSE<br>    embedding = model.encode([q])[0]<br>    # Convert to list for JSON serialization<br>    embedding_list = embedding.tolist()<br>    return {<br>        &quot;embedding&quot;: embedding_list<br>    }</pre><h4>Generation Embedding in Postgres DB</h4><p>To prepare your data for semantic search, you must add a vector column to your searchable tables, pre-process the text to generate embeddings, and store these vectors. This requires the pgvector extension for PostgreSQL.</p><p>1. Database Setup (SQL)</p><p>The following commands enable the necessary extension, add the embedding column (specifying the 768 dimensions from the LaBSE model), and create an index for fast similarity search using ivfflat.</p><pre>CREATE EXTENSION IF NOT EXISTS vector;<br>ALTER TABLE dict.proverb <br>ADD COLUMN embedding vector(768);<br>CREATE INDEX ON dict.proverb <br>USING ivfflat (embedding vector_cosine_ops)<br>WITH (lists = 100);</pre><p>You can create multiple embedding fields if you need to embed different combinations of text columns.</p><p>2. Batch Embedding Generation and Storage (Python)</p><p>After setting up the database, you must iterate through your existing data, generate the LaBSE embedding for each row’s text content, and store the resulting vector in the new column.</p><p>The following Python snippet illustrates how to encode the text and update a specific row in the database:</p><pre># Assuming &#39;model&#39; is the loaded LaBSE <br># and &#39;cur&#39; is your PostgreSQL cursor<br># Generate the embedding vector<br>embeddings = model.encode([text], convert_to_tensor=False)<br>embedding = embeddings[0].tolist()<br>cur.execute(&quot;UPDATE dict.proverb SET embedding = %s WHERE id = %s&quot;, (embedding, row_id))</pre><p>In this code:</p><ul><li><em>text </em>is the string from your document that needs to be embedded (e.g., concatenated text from multiple columns).</li><li><em>row_id </em>is the primary key of the row being updated.</li><li>The embedding vector is converted to a list for insertion into the database.</li></ul><h4>Query Processing and Retrieval</h4><p>When a user submits a search query, the system first calls the API service with the query text to generate a corresponding embedding vector. It then performs a similarity search on the vector index to find and rank document embeddings that are closest to the query embedding.</p><p>The ranking is performed on the raw <strong>cosine distance in ascending order</strong> (using the &lt;=&gt; operator for performance), which implicitly ranks the calculated similarity in descending order (highest similarity first).</p><p>Below is a sample function to perform the vector query in PostgreSQL:</p><pre>def query_emb(query_text):<br>  # &lt;=&gt; = cosine distance → similarity score = 1 - distance<br>  sql = &quot;&quot;&quot;<br>  SELECT id, proverb, 1 - (embedding &lt;=&gt; %s) AS similarity<br>  FROM dict.proverb<br>  WHERE embedding IS NOT NULL<br>  ORDER BY embedding &lt;=&gt; %s<br>  LIMIT 5;<br>  &quot;&quot;&quot;<br>  embeddings = model.encode([query_text], convert_to_tensor=False)<br>  embedding = embeddings[0].tolist() if hasattr(embeddings[0], &quot;tolist&quot;) else embeddings[0]<br>  vec = Vector(embedding)<br>  cur.execute(sql, (vec, ))<br>  results = cur.fetchall()</pre><p><strong>Mongo Atlas DB Approach</strong></p><p>For an alternative approach, instructions are provided in the Appendix for a Mongo Atlas implementation. Mongo Atlas facilitates powerful vector search capabilities through its <strong>Atlas Search</strong> feature. This involves storing your LaBSE embeddings as arrays of numbers within your documents and defining a search index using the dedicated vectorSearch field type for efficient similarity queries.</p><h3>Sample UI</h3><p>We build using Khmer proverb data we collected. Here are some search examples on Khmer proverbs. The score is to the right for each entry.</p><p>Search string: បាយ (rice)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/951/1*UzpF8KbKVeYy9Jo1hHgiDQ.png" /><figcaption>Search string: បាយ</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/949/1*NhyA6XnzHNf9B-ViEbJvHQ.png" /><figcaption>Search string: “rice”</figcaption></figure><p>The result is very similar to Khmer text search, especially the first entry. This shows strong correlation on English/Khmer terms as expected from our embedding. It picked up entries with the word “plate” which can be related to a rice plate. And also return entry with the term ស្រូវ​ (raw rice) which is a different word. But it missed one of the proverbs កក​ក៏​បាយ មេម៉ាយ​ក៏​ស្រី (leftover rice is still rice and widow is still women) proverb. We set a score cut off 0.4 so anything lower is not returned.</p><p>Try full phrase: កក​ក៏​បាយ មេម៉ាយ​ក៏​ស្រី</p><p>The top two entries have the same proverb entry but give different scores because the second entry was appended to other fields used in generating the embedding. This explains why one has the exact matched score (1.0) and the other is only 0.67 since it has other strings not shown in the UI.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/958/1*CftlNDRGNK3FBNRLuAp-JQ.png" /></figure><h3>Conclusion</h3><p>In summary, we evaluated several commercial and open-source text embedding models and concluded that <strong>LaBSE (Language-agnostic BERT Sentence Embeddings) is the optimal choice</strong> for our Khmer Semantic Search system. We focused on evaluating the model through its output, specifically its similarity score, to infer its effectiveness for our use case.</p><p>Our testing revealed key insights into the model’s performance on Khmer text:</p><ul><li><strong>Superior Cross-Lingual Alignment:</strong> LaBSE consistently demonstrated significantly stronger similarity scores in cross-lingual tasks (Khmer-English translation) and indicating a robust representation of Khmer semantic space.</li><li><strong>Tokenization Robustness:</strong> Inspection of the tokenization process showed that the LaBSE tokenizer removes the zero-width space (\u200B) character and handles unsegmented Khmer text effectively reinforcing the choice to use unsegmented text for simplicity and performance.</li></ul><p>We detail the system implementation using a <strong>PostgreSQL vector database</strong> and demonstrate a working example of the semantic search on Khmer proverbs, which can be viewed here: <a href="https://dict.tovnah.com/km/dict/proverb">https://dict.tovnah.com/km/dict/proverb</a>.</p><h3>Future Considerations: Hybrid Search Approaches</h3><p>A purely semantic search solution is often insufficient for comprehensive document retrieval, as it can lack the precision needed for exact matches. The superior solution is a <strong>hybrid search approach</strong> that combines the contextual understanding of semantic search (using embeddings) with the precision of full-text keyword search. While the full implementation is outside the scope of this writing, we explored two methods for integrating the full-text component:</p><ol><li><strong>Search String without Segmentation (RegEx):</strong> This method combines semantic search with a string search using regular expressions to bypass the need for explicit word segmentation. The approach is effective for exact matches of a single keyword or string, although its utility decreases for multi-term queries where terms are scattered throughout a document. This implementation is similar to a LIKE function in a database query but includes Khmer Character Cluster logic to minimize partial term matching (e.g., searching for ក ‘KA’ matches កម្លាំង but not កូន). The hybrid score is calculated by adding a fixed weighting of <strong>0.5</strong> for the keyword search result to the semantic similarity score. This feature can be demonstrated on the <a href="https://dict.tovnah.com/km/dict/proverb">proverb search page</a>.</li><li><strong>Full-Text Search with Segmentation (Postgres `tsvector`):</strong> This is an advanced solution that solves the issue of multi-term searches but requires proper Khmer word segmentation on both the search input and the document data. We tested this using PostgreSQL’s tsvector feature, which supports weighted full-text search across multiple fields. For Khmer word segmentation, we use the <a href="https://github.com/phylypo/segmentation-crf-khmer">Khmer CRF word segmentation</a> tool [7]. The hybrid score is calculated by combining the semantic score with the full-text score, where the tsvector component is assigned a value of <strong>1.0</strong> for an exact match. An example of this full-text-search without semantic is available on the <a href="https://dict.tovnah.com/km/dict/song">Khmer oldies songs page</a> [9].</li></ol><h3>References</h3><ul><li><strong>[1]</strong> R. Buoy and N. T. Sovis, “Khmer Word Search: Challenges, Solutions, and Semantic-Aware Search,” arXiv:2112.08918 [cs.CL], Dec. 2021.</li><li><strong>[2]</strong> N. Thuon, “Khmer Semantic Search Engine (KSE): Digital Information Access and Document Retrieval,” arXiv:2406.09320 [cs.CL], June 2024.</li><li><strong>[3] </strong>T. Mikolov, K. Chen, G. Corrado, and J. Dean, “Efficient Estimation of Word Representations in Vector Space,” in <em>Proc. of Workshop on Learning Representations for NLP (NIPS’13)</em>, 2013.</li><li><strong>[4] </strong>F. Feng et al., “Language-Agnostic BERT Sentence Embedding,” in <em>Proc. of Conf. on Empirical Methods in Natural Language Processing (EMNLP)</em>, 2020.</li><li><strong>[5]</strong> H. Reimers, “Sentence-Transformers,” GitHub. [Online]. Available: <a href="https://github.com/huggingface/sentence-transformers#citing--authors">https://github.com/huggingface/sentence-transformers#citing--authors</a>. [Accessed: Nov. 2, 2025].</li><li><strong>[6]</strong> Cohere, “Cohere’s Embed Models (Details and Application).” [Online]. Available: <a href="https://docs.cohere.com/docs/cohere-embed">https://docs.cohere.com/docs/cohere-embed</a>. [Accessed: Oct. 8, 2025].</li><li><strong>[7]</strong> P. Tum, “Khmer CRF Word Segmentation,” GitHub. [Online]. Available: <a href="https://github.com/phylypo/segmentation-crf-khmer">https://github.com/phylypo/segmentation-crf-khmer</a>. [Accessed: Nov. 29, 2025].</li><li><strong>[8]</strong> P. Tum, “Khmer Proverbs Search Demo,” Tovnah Dictionary. [Online]. Available: <a href="https://dict.tovnah.com/km/dict/proverb">https://dict.tovnah.com/km/dict/proverb</a>. [Accessed: Nov. 29, 2025].</li><li><strong>[9]</strong> P. Tum, “Khmer Oldies Songs Search,” Tovnah Dictionary. [Online]. Available: <a href="https://dict.tovnah.com/km/dict/song">https://dict.tovnah.com/km/dict/song</a>. [Accessed: Nov. 29, 2025].</li><li><strong>[10]</strong> NLP Techostartup Center. [Online]. Available: <a href="https://nlp.techostartup.center/">https://nlp.techostartup.center/</a>. [Accessed: Oct. 3, 2025].</li><li><strong>[11] </strong>OpenAI, “OpenAI API Documentation,” [Online]. Available: <a href="https://openai.com/api/">https://openai.com/api/</a>. [Accessed: Oct. 20, 2025].</li></ul><h3>Appendix</h3><h4>Mongo Atlas DB</h4><p>Storing Embeddings</p><p>Each document in your collection would include a field for the text and another for its corresponding embedding.</p><pre>{<br>  &quot;text&quot;: &quot;This is a Khmer sentence.&quot;,<br>  &quot;embedding&quot;: [0.123, 0.456, 0.789, ..., 0.001]<br>}</pre><p>Creating an Atlas Search Index</p><p>Define an Atlas Search index on your collection with a vectorSearch field for the embedding.</p><pre>{<br>  &quot;mappings&quot;: {<br>    &quot;dynamic&quot;: true,<br>    &quot;fields&quot;: {<br>      &quot;embedding&quot;: {<br>        &quot;type&quot;: &quot;vectorSearch&quot;,<br>        &quot;dimensions&quot;: 768, // Adjust based on your LaBSE model&#39;s output dimension<br>        &quot;similarity&quot;: &quot;cosine&quot;<br>      }<br>    }<br>  }<br>}</pre><p>Performing a Cosine Vector Search:</p><p>When a user query comes in, generate its embedding using LaBSE and then use the $vectorSearch operator in your aggregation pipeline.</p><pre>from pymongo import MongoClient<br><br># Assume &#39;query_embedding&#39; is the LaBSE embedding of the user&#39;s query<br># and &#39;collection&#39; is your MongoDB collection<br><br>results = collection.aggregate([<br>    {<br>        &quot;$vectorSearch&quot;: {<br>            &quot;queryVector&quot;: query_embedding,<br>            &quot;path&quot;: &quot;embedding&quot;,<br>            &quot;numCandidates&quot;: 100, # Number of nearest neighbors to consider<br>            &quot;limit&quot;: 10,          # Number of results to return<br>            &quot;index&quot;: &quot;default&quot;    # Name of your Atlas Search index<br>        }<br>    },<br>    {<br>        &quot;$project&quot;: {<br>            &quot;text&quot;: 1,<br>            &quot;score&quot;: { &quot;$meta&quot;: &quot;vectorSearchScore&quot; }<br>        }<br>    }<br>])<br><br>for doc in results:<br> print(f&quot;Text: {doc[&#39;text&#39;]}, Score: {doc[&#39;score&#39;]}&quot;)</pre><h4>PostgreSQL for Cosine Vector Search</h4><p>PostgreSQL can also be used for vector search, especially with extensions like pgvector. This extension allows you to store vector data and perform efficient similarity searches, including cosine similarity.</p><p><strong>Enabling pgvector Extension:<br></strong>First, ensure the pgvector extension is enabled in your PostgreSQL database.</p><pre>CREATE EXTENSION vector;</pre><p><strong>Creating a Table with Vector Column:<br></strong>Create a table to store your Khmer text and their embeddings.</p><pre>CREATE TABLE khmer_documents (<br>    id SERIAL PRIMARY KEY,<br>    text TEXT,<br>    embedding VECTOR(768) -- Adjust dimension based on your LaBSE model<br>);</pre><p><strong>Inserting Data:<br></strong>Insert your preprocessed text and their LaBSE embeddings into the table.</p><pre>INSERT INTO khmer_documents (text, embedding)<br>VALUES (&#39;This is a Khmer sentence.&#39;, &#39;[0.123, 0.456, 0.789, ..., 0.001]&#39;);</pre><p><strong>Performing a Cosine Vector Search:<br></strong>To find documents similar to a query embedding, use the &lt;=&gt; operator for cosine distance.</p><pre>import psycopg2<br>import numpy as np<br><br># Assume &#39;query_embedding&#39; is the LaBSE embedding as a numpy array<br>query_embedding_str = &#39;[&#39; + &#39;,&#39;.join(map(str, query_embedding)) + &#39;]&#39;<br><br>with conn.cursor() as cur:<br>  cur.execute(f&quot;&quot;&quot;<br>SELECT text, 1 - (embedding &lt;=&gt; &#39;{query_embedding_str}&#39;) AS cosine_similarity<br>FROM khmer_documents<br>ORDER BY embedding &lt;=&gt; &#39;{query_embedding_str}&#39;<br>LIMIT 10;<br>  &quot;&quot;&quot;)<br>  results = cur.fetchall()<br>    for text, similarity in results:<br>     print(f&quot;Text: {text}, Similarity: {similarity}&quot;)</pre><p>Example scores on text between Khmer and English</p><pre># textkh = [&quot;សួស្តីឆ្នាំថ្មី!&quot;, &quot;តើអ្នកសុខសប្បាយទេថ្ងៃនេះ?&quot;, &quot;តើអ្នកឈ្មោះអ្វី?&quot;, &quot;កាលយើងជួបគ្នាលើផ្ទៃអាកាស&quot;, &quot;ពិតជាច្រៀងពិរោះណាស់&quot;, &quot;អ្វីទៅជាស្នេហា?&quot;]<br><br><br>textkh = [&quot;សួស្តី ឆ្នាំ ថ្មី!&quot;, &quot;តើ អ្នក សុខ សប្បាយ ទេ ថ្ងៃ នេះ?&quot;, &quot;តើ អ្នក ឈ្មោះ អ្វី?&quot;, &quot;កាល យើង ជួប គ្នា លើ ផ្ទៃ អាកាស&quot;, &quot;ពិត ជា ច្រៀង ពិរោះ ណាស់&quot;, &quot;អ្វី ទៅ ជា ស្នេហា?&quot;]<br>texten = [&quot;Happy New Year!&quot;, &quot;How are you today?&quot;, &quot;What is your name?&quot;, &quot;When we met in the sky&quot;, &quot;It’s really beautifully sung&quot;, &quot;What is love?&quot;]<br>embeddings_kh = model.encode(textkh, convert_to_tensor=False)<br>embeddings_en = model.encode(texten, convert_to_tensor=False)<br><br><br># iterate between enbeddings_kh and embeddings_en and compute cosine similarity<br>for i in range(len(textkh)):<br>    cos_sim = cosine_similarity([embeddings_kh[i]], [embeddings_en[i]])[0][0]<br>    print(f&quot;Cosine similarity: (KH vs EN) {textkh[i]}  |  {texten[i]}  =&gt; {cos_sim:.4f}&quot;)<br><br># Cosine similarity: (KH vs EN) សួស្តីឆ្នាំថ្មី!  |  Happy New Year!  =&gt; 0.8991<br># Cosine similarity: (KH vs EN) តើអ្នកសុខសប្បាយទេថ្ងៃនេះ?  |  How are you today?  =&gt; 0.8775<br># Cosine similarity: (KH vs EN) តើអ្នកឈ្មោះអ្វី?  |  What is your name?  =&gt; 0.8726<br># Cosine similarity: (KH vs EN) កាលយើងជួបគ្នាលើផ្ទៃអាកាស  |  When we met in the sky  =&gt; 0.8690<br># Cosine similarity: (KH vs EN) ពិតជាច្រៀងពិរោះណាស់  |  It’s really beautifully sung  =&gt; 0.8754<br># Cosine similarity: (KH vs EN) អ្វីទៅជាស្នេហា?  |  What is love?  =&gt; 0.9713<br><br><br># Cosine similarity: (KH vs EN) សួស្តី ឆ្នាំ ថ្មី!  |  Happy New Year!  =&gt; 0.8972<br># Cosine similarity: (KH vs EN) តើ អ្នក សុខ សប្បាយ ទេ ថ្ងៃ នេះ?  |  How are you today?  =&gt; 0.8117<br># Cosine similarity: (KH vs EN) តើ អ្នក ឈ្មោះ អ្វី?  |  What is your name?  =&gt; 0.8984<br># Cosine similarity: (KH vs EN) កាល យើង ជួប គ្នា លើ ផ្ទៃ អាកាស  |  When we met in the sky  =&gt; 0.8782<br># Cosine similarity: (KH vs EN) ពិត ជា ច្រៀង ពិរោះ ណាស់  |  It’s really beautifully sung  =&gt; 0.8729<br># Cosine similarity: (KH vs EN) អ្វី ទៅ ជា ស្នេហា?  |  What is love?  =&gt; 0.9694</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1b20f3e6e00c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Basic NLP to ChatGPT and Beyond]]></title>
            <link>https://medium.com/@phylypo/from-basic-nlp-to-chatgpt-and-beyond-7e224a8a869c?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/7e224a8a869c</guid>
            <category><![CDATA[gpt-4]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[agi]]></category>
            <category><![CDATA[nlp]]></category>
            <category><![CDATA[bards]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Sat, 20 May 2023 05:59:50 GMT</pubDate>
            <atom:updated>2023-05-20T05:59:50.058Z</atom:updated>
            <content:encoded><![CDATA[<p>ChatGPT, a chatbot developed by OpenAI, has captured the world’s attention and changed the way we interact with computers. It was one of the fastest-growing consumer apps in history, with an estimated 100 million monthly active users just two months after its launch in November 2022.</p><p>To understand the details of ChatGPT, let’s first start with a basic understanding of how artificial intelligence (AI) performs natural language processing (NLP) and its evolution. Then we will delve into the GPT language model and its training process. Finally, we will discuss some implications of artificial general intelligence (AGI). The following topics will be covered:</p><ul><li>Introduction to NLP</li><li>Transformer architecture</li><li>Large language models such as BERT and GPT</li><li>Training of large language models, including ChatGPT</li><li>Bing Chat and Google Bard</li><li>Sparks of AGI</li></ul><h3>Introduction to NLP</h3><p>Natural Language Processing (NLP) is a powerful tool that allows computers to analyze human language. Unlike formal language, like computer programming languages, natural language has loose rules that can change over time. When creating an algorithm to perform NLP, you don’t have the complete rule to program into the algorithm thus you need a completely different approach.</p><p>In NLP, the algorithms can perform tasks such as document classification to identify whether an email is spam, or analyze the sentiment of a given text as positive or negative. This type of program artificial intelligence (AI) program can perform a wide variety of other tasks as well such as summarize text, answer questions, translate between languages, identify entities within a text (name entity recognition or NER), and generate text like ChatGPT.</p><h3>Bag-of-Words</h3><p>A simple approach to NLP in the early days is to count the frequency of words in a document in the document. This approach is called bag-of-words algorithm. While it was initially used for scoring and searching documents, it can also be used for tasks like text classification and sentiment analysis. Improvements like Term Frequency-Inverse Document Frequency (TF-IDF) help normalize the count and improve performance of the tasks.</p><h3>Word Vectors</h3><p>To obtain more meaningful insights, word vectors are used to represent each word as a list of values. This approach captures both the syntactic and semantic information of words.</p><p>The idea is that you can map a word into a vector space. So words that are located in close proximity are similar while others with opposite values in some axis are different in that category.</p><p>For example, the gender ‘male’ can be considered as one vector value, so “man” and “boy” would have high values belonging to a close proximity, while “woman” and “girl” would have the opposite values in one vector.</p><p>Word vectors are generated through unsupervised learning from text documents, using algorithms like word2vec to pre-train the vectors based on the co-occurring of words.</p><p>Additionally, vector arithmetic can be performed on words, such as the well-known example from word2vec paper below demonstrates the representation of these words through their values.</p><p><em>[King] — [Man] + [Woman] = [Queen]</em></p><p>Another approach to generate the word vector is called Global Vectors for Word Representation (GloVe). It has shown better performance by capturing global statistics to improve the learning of word representation.</p><p>Both approaches rely on the probabilities of co-occurring words during pre-training, but they are context-independent when used as inputs to algorithms. But word vector or word embedding has become the feature inputs to many NLP algorithms. In the next section, we will explore context-dependent approaches.</p><h3>Language Model</h3><p>Although word vectors are generated based on the probabilities of co-occurring words, they are context-independent when used as input for many algorithms. To incorporate context, we need to explore the language models approaches.</p><p>A language model is a random process that models word sequences by calculating the probability given a sequence of words. There are two approaches to accomplish this:</p><ol><li>Statistical language models use traditional statistical techniques like N-Gram to learn the probability distribution of words.</li><li>Neural language models use neural networks, such as Recurrent Neural Networks (RNN), to model language.</li></ol><h4>N-Gram</h4><p>N-Gram is an approach that takes into account some number of words in a sequence, where N is the number of words. For example, a Bigram (N = 2) accounts for two sequential words at a time. Given a sequence of words, the next word’s probability is the probability of the second word given the first word, multiplied by the probability of the third word given the second word, and so forth.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/395/1*b5WPWKkQ3_5wF-pvdN3UJg.png" /></figure><p>Similarly, a Trigram (N = 3) takes into account three words at a time. As N increases, the accuracy of the model improves, but the amount of computation increases exponentially with the dimension of the vocabulary size to the power of N. This approach has a fairly good performance in many of the NLP tasks without having a very big N. But N-gram models often lack the ability to generalize well beyond the specific phrases or sentences they were trained on.</p><h4>Neural Language Model</h4><p>The neural language model uses a neural network to model language. Neural network is a type of machine learning approach that is inspired by how the neurons in the human brain function. It consists of layers of interconnected neurons that are designed to process complex data.</p><p>In 2003, Bengio et al proposed “A Neural Probabilistic Language Model” that showed a 10–20% performance improvement over the Trigram algorithm based on perplexity score,, a measure of how well it can predict a sequence of words.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/1*UT_s9bb2F5jf2xwteO_nug.png" /><figcaption>Bengio et al., “A Neural Probabilistic Language Model”, ResearchGate <a href="https://www.researchgate.net/publication/2413241">https://www.researchgate.net/publication/2413241</a>, 2001.</figcaption></figure><p>The next phase in the neural network language model was the Recurrent Neural Network (RNN), which has become a standard approach for sequence-to-sequence (seq2seq) tasks using specific implementations like Long Short-Term Memory (LSTM) and Gated Recurrent Unit (GRU). Also known as deep learning, these approaches become the standard NLP and other domains such as computer vision and speech recognition.</p><h3>Transformer Architecture</h3><p>The RNN approach has limitations due to its serial computation as it processes each input word. In order to efficiently process the inputs in mass parallel computing infrastructure, a team from Google proposed an architecture in the seminal paper “Attention is all you need” by Vaswani et al. in 2017 known as the Transformer. The Transformer architecture allows parallel computing and uses the self-attention mechanism to capture the relationship between input words/tokens. Additionally, the Transformer uses key-value stores and positional encoding to improve performance. The transformer architecture has achieved state-of-the-art results on a wide range of NLP tasks, particularly in machine translation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/318/1*mJYzWIDfmgYYazQg1XN37A.png" /><figcaption>Vaswani et al., “Attention is all you need” , 2017</figcaption></figure><h3>BERT</h3><p>The Transformer architecture addressed the massive processing issue but it needed another breakthrough for the algorithm to learn from massive text data on the Internet. BERT (Bidirectional Encoder Representations from Transformers) is the next leap in NLP, enabled by the ability to pretrain on massive amounts of text data available on the internet. Similar to pretraining in computer vision, BERT pretrain the text using the masked language model (MLM). MLM is a pretraining approach that involves masking some words/tokens in the input sequence and training the model to predict the original token based on its context. This approach allows the model to learn the representations of words depending on its context.</p><p>The language model at this point can predict the next word very well. Then it is fine-tuned for the downstream tasks such as questions and answers. This approach allows BERT to perform better than humans on the Stanford Question Answering Dataset (SQuAD).</p><p>BERT was released in October 2018 by Google and other transformer-based models that use the MLM approach have revolutionized NLP by significantly advancing language understanding, text generation, and machine translation. BERT has achieved state-of-the-art results on a wide range of NLP tasks, and subsequent models like GPT-2, Ernie, and T5 have also demonstrated the power of transformer architecture and its pretraining approach.</p><p>There are more detail timeline of different models from my survey article here: <a href="https://medium.com/@phylypo/a-survey-of-the-state-of-the-art-language-models-up-to-early-2020-aba824302c6">https://medium.com/@phylypo/a-survey-of-the-state-of-the-art-language-models-up-to-early-2020-aba824302c6</a>.</p><h3>Large Language Model</h3><p>To better understand the training of large language models such as ChatGPT, it’s important to first grasp the sheer size of these models as it has a direct impact on the training time. As a neural network trains, it adjusts these connections, or weights. Therefore, the more connections the network has, the more computation it must perform during training and inference.</p><p>The term “large language model” or LLM is given to models due to the large number of parameters, or weights in the language model. The number of parameters in these models has increased exponentially in recent years. For instance, GPT had 117 million parameters in 2018, GPT-2 had 1.5 billion parameters in 2019, and the largest model as of January 2020, T-NLG from Microsoft, had 17 billion parameters. In June 2020, GPT-3 was released with a whopping 175 billion parameters, representing a significant increase in size from previous models. The chart below with a logarithmic scale on the y-axis illustrates the trend of exponentially increasing the number of parameters in more recent models up to 2021.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*YhRDgZ1bTEERFxoeUWGe9w.png" /><figcaption><a href="https://venturebeat.com/ai/microsoft-and-nvidia-team-up-to-train-one-of-the-worlds-largest-language-models/">https://venturebeat.com/ai/microsoft-and-nvidia-team-up-to-train-one-of-the-worlds-largest-language-models/</a></figcaption></figure><p>Related to ChatGPT model by Open AI, we can see the following is a timeline of OpenAI’s large language models and their sizes and how its grows exponentially over time.</p><ul><li>GPT (Generative Pretrained Transformer): Released in June 2018, this model had 117 million parameters and was trained on a diverse range of internet text.</li><li>GPT-2: Released in February 2019, this model had 1.5 billion parameters and was trained on an even larger and more diverse dataset than GPT.</li><li>GPT-3: Released in June 2020, this model had a massive 175 billion parameters, making it the largest and most powerful language model at the time.</li><li>GPT-3.5: Released on March 15, 2022, this model was trained on data up to June 2021 and included Codex, a language model designed for generating code.</li><li>ChatGPT: Based on GPT-3.5, ChatGPT was released on November 30, 2022, and is specifically designed for chat and conversational applications.</li><li>GPT-4: Started the limited release on February 7, 2023 by Microsoft under the code name Sydney embedded in Bing Search, this model is more powerful than GPT-3.</li></ul><h3>Training Large Language Models</h3><p>To train a language model like ChatGPT, a large quantity of high-quality data is necessary. Although there is a vast amount of text data available on the internet, it must be filtered to ensure that only high-quality data is used for training. The quality of the training data is essential in determining the effectiveness of the model. However, the data collection and preprocessing process can be time-consuming and resource-intensive.</p><h3>Dataset</h3><p>The exact dataset used in ChatGPT is unknown but based on GPT-3, we see the main datasets used are:</p><ol><li>Common Crawl 2016–2019: This is a massive corpus of web pages, totaling 45 terabytes in size of compressed plaintext before filtering and 570GB after filtering, roughly equivalent to 400 billion byte-pair-encoded tokens.</li><li>WebText2: This is a collection of filtered web pages from the Internet.</li><li>BooksCorpus: This dataset includes over 11,000 books.</li><li>Wikipedia: This dataset includes a dump of the English Wikipedia, totaling 2.5 billion words.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/1*ddSBrRxbfXUSkEX5ZN9WtA.png" /><figcaption>Brown et al, “Language Models are Few-Shot Learners”, Jul 2020.</figcaption></figure><h3>Training</h3><p>The training process of a large language model typically consists of two phases.</p><ol><li>Pre-training: In this phase, the model is trained on a vast amount of text data. A popular approach, such as BERT’s mask language model, employs semi-supervised learning. The model is fed raw text without specific labels, but certain words are programmatically omitted, and the model learns to predict those missing words.</li><li>Fine-tuning: In the fine-tuning phase, the model is trained on specific data and formats to enable it to perform particular tasks like sentiment analysis, text summarization, or translation. The model updates its weights as it learns from new data, improving its performance on the given task. Some models, like T5 (Text-to-Text Transfer Transformer), are trained to handle multiple tasks, such as translation, summarization, question answering, and text generation, within a single model.</li></ol><p>OpenAI’s large language models (LLMs), such as GPT, follow a similar pre-training approach. However, they employ a different fine-tuning process. GPT uses in-context learning, where it is not fine-tuned for specific tasks. During inference, the model is conditioned with a few task demonstrations as input, but its weights are not updated in this process.</p><p>The in-context learning approach yields interesting emergent behavior, as the model learns to generalize by reading input text conditioned on previous words then predict the next words. OpenAI demonstrated that GPT-2 can perform multitask learning, but the learning process is slower compared to explicitly supervised approaches.</p><p>The pre-training approach for GPT-3 is similar to that of GPT-2, including the model architecture, data, and training methods. Scaling up from GPT-2 to GPT-3 was relatively straightforward in terms of increasing the model and dataset sizes, diversifying the data, and extending the training duration. Evaluation of the GPT-3 model focuses on its performance with zero-shot learning (no examples), one-shot learning (one example), and few-shot learning (several examples).</p><p>GPT-3 has demonstrated the ability to achieve performance levels that are close to state-of-the-art results on CoQA reading comprehension tasks when utilizing a large enough model.</p><p>ChatGPT, which utilizes the GPT-3 language model, undergoes a fine-tuning process that involves supervised learning. During this process, conversations generated by human trainers are used to train the model on appropriate responses. Additionally, ChatGPT incorporates reinforcement learning from human feedback (RLHF) to further enhance the quality and format of its generated answers. In RLHF, human trainers provide scores indicating their preference for different responses, and the model learns to generate responses that maximize these scores. This version of the model is known as InstructGPT (or GPT-3.5).</p><p>OpenAI has also implemented safety measures in ChatGPT to mitigate the risk of toxic, biased, or harmful responses. This ensures that the system adheres to safety guidelines. ChatGPT is now publicly accessible through the OpenAI website’s web interface. The diagram below illustrates the different models and features involved in the ChatGPT system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/622/1*jyB6daoHh4o6csficSL9JQ.png" /><figcaption><a href="https://lifearchitect.ai/chatgpt/">https://lifearchitect.ai/chatgpt/</a></figcaption></figure><p>The ChatGPT trained model possesses knowledge about current events up to 2021 since it was trained on data collected up to that time period.</p><p>GPT-4 is a similar model to its predecessor, but specific details regarding its training data are not widely known. The model underwent fine-tuning using the Reinforcement Learning from Human Feedback (RLHF) approach, similar to InstructGPT. However, the report regarding GPT-4 did not disclose information about its architecture, such as model size, hardware, training compute, dataset construction, or training method. These details were omitted due to competitive considerations within the technology field.</p><p>One notable addition to GPT-4 is the ability to process images. The chart below illustrates the improved performance of GPT-4 compared to GPT-3 in academic and professional exams.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/623/1*-68G_G-mOyLQrWS4NWvGWA.png" /><figcaption>GPT-4 Technical Report, Mar 2023</figcaption></figure><p>Here is the summary of the key differences in model and dataset size for GPT models.</p><ul><li>GPT was trained on a dataset of 40GB of text, with 117 million parameters. It achieved state-of-the-art results on a variety of language modeling tasks at the time of its release in 2018.</li><li>GPT-2 was trained on a much larger dataset of 40GB of text, with 1.5 billion parameters. It also introduced the “unsupervised task” of generating coherent text from a given prompt.</li><li>GPT-3 was trained on an even larger dataset of 45TB of text, with 175 billion parameters. It introduced a range of new features, including the ability to perform arithmetic, answer questions, and translate languages.</li><li>GPT-3.5/ChatGPT has been trained on a dataset with over 570 terabytes of text data.</li><li>GPT-4: training data size and model size are not disclosed.</li></ul><h3>Environment Impact</h3><p>With the introduction of LLM (Large Language Models), researchers raised concerns regarding the environmental impact associated with training these models. Reports emerged with headlines like “Training a single AI model can emit as much carbon as five cars in their lifetimes,” citing a study conducted by the University of Massachusetts Amherst. The charts below depict the estimated environmental footprint of the five largest models at that time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/647/1*2mKIySYMNA9kgUDwjzj9cA.png" /><figcaption><em>Strubell et al., Energy and Policy Considerations for Deep Learning in NLP, arXiv preprint arXiv:1906.02243, June 2019.</em></figcaption></figure><p>A subsequent study conducted by Google and the University of California, Berkeley, titled “Carbon Emissions and Large Neural Network Training” (Patterson et al., 2021), highlighted that the carbon emissions associated with training large neural networks can vary depending on factors such as the data center’s efficiency and the type of hardware employed (Nvidia P100 GPU vs TPU v2). However, the overall magnitude of emissions aligns with the findings of a 2019 report, estimating that approximately 200 kWh of energy consumption corresponds to roughly 0.1 metric tons of carbon emissions.</p><p>Furthermore, the report demonstrates that the training process of GPT-3 consumed 1,287 MWh of energy, resulting in the emission of 552 metric tons of carbon or approximately 1.2 million pounds. To provide a comparative perspective, this level of carbon emission is equivalent to the emissions generated by 10 cars over the course of their lifetimes.</p><p>In addition to training time, the size of the models also impacts their usage by users. According to estimates from the lifearchitect.ai website, the utilization of ChatGPT by 10 million users could cost the company up to $12 million per month. Based on the cloud compute cost from Strubell et al., this monthly cost is four times higher than the cost of training the largest model. So every month, the operation of ChatGPT alone emits an amount of carbon equivalent to that produced by 20 cars over their lifetimes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/495/1*ks0y5hOo43jt4RW7PtIW4w.png" /><figcaption><a href="https://lifearchitect.ai/chatgpt/">https://lifearchitect.ai/chatgpt/</a></figcaption></figure><p>As some researchers pointed out the amount of greenhouse gas it emitted, others worried that research communities with limited access to computational resources will be unable to compete with large companies that possess extensive computing capabilities.. However, Sam Altman from OpenAI has reassured that “we are at the end of the era where it’s going to be these, like, giant, giant models”[<a href="https://www.wired.com/story/openai-ceo-sam-altman-the-age-of-giant-ai-models-is-already-over/">wired.com</a>].</p><h3>Bing Chat and Google Bard</h3><p>Microsoft integrated GPT-4 to its search engine Bing in the chat mode in February 6, 2023. The code name of the model is known as Sydney as a Stanford student created a prompt injection to reveal its instructions.</p><p>In February 6, 2023, Microsoft integrated GPT-4 into its search engine Bing in the chat mode. The model was internally referred to as “Sydney” because a Stanford student discovered a way to reveal its instructions via prompt injection.</p><p>These language models are trained on a collection of internet data up to a certain point in time. As for ChatGPT, it learned about current events up to 2021. While GPT-4 has similar limitations, Bing Chat allows the model to access the Internet, specifically through Bing Search, for up to 3 searches based on the revealed instructions. This feature enables the model to provide more up-to-date information.</p><p>Following the popularity of ChatGPT, Google introduced its own large language model called Bard in March 2023. Bard is powered by a Language Model for Dialogue Applications (LaMDA).</p><p>As of early May 2023, the latest version of Bard is powered by another language model called PaLM 2. PaLM, a Pathways Language Model, has 540 billion parameters, nearly five times larger than LaMDA, which has 137 billion parameters. PaLM is trained on a dataset of text and code that is 100 times larger than what LaMDA is trained on. It features a new AI architecture designed to be more efficient and scalable. PaLM can handle various tasks and learn new tasks more effectively, resembling how humans learn.</p><p>PaLM 2 has a “significantly smaller” number of parameters than PaLM but performs similarly. It is more heavily trained on multilingual text, spanning more than 100 languages. It has the ability to understand, generate and translate nuanced text across a wide variety of languages. PaLM 2 also passes advanced language proficiency exams at the “mastery” level. It has an improved capabilities in logic, common sense reasoning, and mathematics. In addition, it can generate code and has debugging skills across multiple programming languages.</p><h3>Sparks of AGI</h3><p>As AI technology has advanced, we have witnessed impressive achievements, such as IBM’s Deepblue program defeating chess Grandmaster Garry Kasparov in 1997 and DeepMind Alpha Go beating world champion Go player Lee Sedol in 2017. However, these are considered artificial narrow intelligent (ANI) systems, meaning that they are only capable of mastering specific tasks and cannot transfer their skills to similar ones as humans can. In contrast, humans are considered to have general intelligence, which enables us to generalize from one learned task to the next rapidly. For AI to become artificial general intelligent (AGI), it must possess this ability to generalize and master any task. Once it reaches this stage, it may become an artificial super intelligent (ASI) quickly, which can bring significant knowledge and unimaginable impacts to the world.</p><p>According to Nick Bostrom, a philosopher and researcher at the University of Oxford, author of the book, “Superintelligence: Paths, Dangers, and Strategies” (2014), AGI is predicted to be achieved by machines around 2045, as per the average estimates of experts surveyed. However, Bostrom also raised concerns about the challenges of controlling AI once it reaches AGI.</p><p>One challenge is that we cannot simply program our goals into AI. In a thought experiment called the paperclip maximizer, imagine instructing a smart machine to produce as many paperclips as possible. This could lead the AI to prioritize paperclip production above all else, disregarding human instructions and may prevent humans from turning it off. Bostrom refers to this as the alignment problem.</p><p>Additionally, there is another challenge known as the “Control Problem.” Bostrom asks how we can establish initial conditions that ensure safety in the outcome. Suggestions like isolating the AI or limiting its access to the outside world may not be effective, as a highly intelligent machine could find ways to manipulate us or possess advanced technology beyond our awareness. This idea was depicted in the movie “Ex Machina,” where an inventor tries to maintain control over a smart AI confined to an isolated environment but ultimately loses control of it.</p><p>As researchers strive to achieve the goal of AGI, in his book “The Master Algorithm: How the Quest for the Ultimate Learning Machine Will Remake Our World” (2015), Pedro Domingos discusses the diverse approaches taken by different AI disciplines. Domingos categorizes these disciplines into five tribes:</p><ol><li>Symbolists (logic-based AI with decision tree algorithms),</li><li>Connectionists (neural network-based AI with a focus on deep learning),</li><li>Evolutionaries (evolution-based AI utilizing genetic algorithms),</li><li>Bayesians (probability-based AI with methods like Naive Bayes), and</li><li>Analogizers (psychology-based AI using kernel machines).</li></ol><p>Each tribe advocates for their approach as the one capable of advancing us towards AGI. This is evident in the debate between Gary Marcus, a symbolist, and Yoshua Bengio, a connectionist. The symbolist tribe defends their approach, challenging the popularity of the connectionist tribe, particularly deep learning.</p><p>( <a href="https://www.youtube.com/watch?v=EeqwFjqFvJA">AI DEBATE : Yoshua Bengio | Gary Marcus</a> — <a href="https://www.youtube.com/watch?v=EeqwFjqFvJA)">https://www.youtube.com/watch?v=EeqwFjqFvJA)</a></p><p>Domingos suggests that a combination of different AI tribes can create a master algorithm to reach AGI, such as in the context of curing cancer, which requires expertise from multiple fields that no single human alone can master.</p><p>Recent trends in AI research include the influential paper “Attention is All You Need” by Vaswani et al. (2017), which introduced transformer models and paved the way for large-scale models like ChatGPT in deep learning.</p><p>In the evolutionaries tribe, reinforcement learning has demonstrated remarkable progress. Notably, DeepMind’s AlphaGo, AlphaStar, and AlphaFold are prime examples of reinforcement learning-based systems. These systems have achieved unprecedented success in various games, such as Go and StarCraft 2, and have even made breakthroughs in tackling complex challenges in biology and physics, such as protein folding.</p><p>Affirming the potential of the reinforcement learning approach, David Silver’s 2021 paper “Reward Is Enough” supports the notion that learning through behavior rewards can eventually enable the replication of human cognitive capabilities and the achievement of AGI.</p><p>In terms of AGI advancements, a Google ex-employee claimed in July 2022 that the chatbot LaMDA possesses sentience. Additionally, Sebastian Bubeck from Microsoft, who had early access to GPT-4, published a paper titled “Sparks of Artificial General Intelligence: Early experiments with GPT-4” in March 2023. Bubeck highlighted GPT-4’s remarkable ability to solve novel and intricate tasks across multiple domains, approaching human-level performance in areas such as mathematics, coding, vision, medicine, law, and psychology. He sees it as a promising early version of an AGI system.</p><p>Geoffrey Hinton, considered the godfather of deep learning and the recipient of the 2018 Turing Award, recently left Google to express his concerns about AI as an existential threat. He emphasized that humanity is a transitory phase for evolutionary intelligence and urged caution in our approach to AI development.</p><h3>Summary</h3><p>A chatbot is a program designed to accurately predict the next word, creating the impression of human-like conversation or expertise on a particular subject. It functions as a sophisticated statistical machine, though some critics, like Noam Chomsky, argue that chatbots such as ChatGPT as mere impersonators lacking novelty or true understanding.</p><p>However, recent advancements in large language models have shown remarkable performance, surpassing humans in various tasks and achieving mastery-level proficiency in advanced language skills. While these chatbots have proven useful in assisting us with many tasks, concerns have arisen regarding their negative impact on society. Issues like the spread of fake news, deep fakes, and other worrisome developments have raised alarms among many individuals.</p><p>In comparison, AI recommendation systems are designed to maximize user engagement and generate profits through targeted advertising. By analyzing our preferences and clicks, these systems can gradually manipulate our perspectives, leading us down rabbit holes or influencing us with radical views.</p><p>As machines continue to grow more intelligent, whether or not this represents the emergence of AGI, it is only a matter of time before the machine surpasses human intelligence and reaches the level of artificial superintelligence. This raises important questions: Are we adequately prepared for this future? Can we ensure the safety and well-being of humanity in the face of such advancements?</p><h3>Web References</h3><ul><li><a href="https://www.reuters.com/technology/chatgpts-popularity-explodes-us-lawmakers-take-an-interest-2023-02-13/">https://www.reuters.com/technology/chatgpts-popularity-explodes-us-lawmakers-take-an-interest-2023-02-13/</a></li><li><a href="https://venturebeat.com/ai/openai-chief-says-age-of-giant-ai-models-is-ending-a-gpu-crisis-could-be-one-reason-why/">https://venturebeat.com/ai/openai-chief-says-age-of-giant-ai-models-is-ending-a-gpu-crisis-could-be-one-reason-why/</a></li><li><a href="https://www.fierceelectronics.com/sensors/chatgpt-runs-10k-nvidia-training-gpus-potential-thousands-more">https://www.fierceelectronics.com/sensors/chatgpt-runs-10k-nvidia-training-gpus-potential-thousands-more</a></li><li><a href="https://en.wikipedia.org/wiki/GPT-3">https://en.wikipedia.org/wiki/GPT-3</a></li><li><a href="https://lambdalabs.com/blog/demystifying-gpt-3">https://lambdalabs.com/blog/demystifying-gpt-3</a></li><li><a href="https://www.technologyreview.com/2019/06/06/239031/training-a-single-ai-model-can-emit-as-much-carbon-as-five-cars-in-their-lifetimes/">https://www.technologyreview.com/2019/06/06/239031/training-a-single-ai-model-can-emit-as-much-carbon-as-five-cars-in-their-lifetimes/</a></li><li><a href="https://arstechnica.com/information-technology/2023/02/ai-powered-bing-chat-spills-its-secrets-via-prompt-injection-attack/">https://arstechnica.com/information-technology/2023/02/ai-powered-bing-chat-spills-its-secrets-via-prompt-injection-attack/</a></li><li><a href="https://stanford-cs324.github.io/winter2022/lectures/environment/">https://stanford-cs324.github.io/winter2022/lectures/environment/</a></li><li><a href="https://www.theguardian.com/technology/2022/jul/23/google-fires-software-engineer-who-claims-ai-chatbot-is-sentient">https://www.theguardian.com/technology/2022/jul/23/google-fires-software-engineer-who-claims-ai-chatbot-is-sentient</a></li><li><a href="https://ai.googleblog.com/2022/04/pathways-language-model-palm-scaling-to.html">https://ai.googleblog.com/2022/04/pathways-language-model-palm-scaling-to.html</a></li></ul><h3>Video References</h3><ol><li>The AI revolution: Google’s developers on the future of artificial intelligence | 60 Minutes<br><a href="https://www.youtube.com/watch?v=880TBXMuzmk">https://www.youtube.com/watch?v=880TBXMuzmk</a> (Apr 16, 2023) ~27mins</li><li>The A.I. Dilemma — March 9, 2023 (<a href="https://www.youtube.com/@CenterforHumaneTechnology">Center for Humane Technology</a>) (Apr 5, 2023) ~107mins<strong><br></strong><a href="https://www.youtube.com/watch?v=xoVJKj8lcNQ">https://www.youtube.com/watch?v=xoVJKj8lcNQ</a></li><li>Sparks of AGI: early experiments with GPT-4 (<a href="https://www.youtube.com/@SebastienBubeck">Sebastien Bubeck</a>) Apr 6, 2023 ~48 mins<br>https://www.youtube.com/watch?v=qbIk7-JPB2c</li><li>Stuart Russell — How Not To Destroy the World With AI (CITRIS) Apr 5, 2023 ~110mins<br><a href="https://www.youtube.com/watch?v=ISkAkiAkK7A">https://www.youtube.com/watch?v=ISkAkiAkK7A</a></li><li>Yann LeCun and Andrew Ng: Why the 6-month AI Pause is a Bad Idea<strong> </strong>(<a href="https://www.youtube.com/@Deeplearningai">DeepLearningAI</a>)Apr 7, 2023 (30 mins)<br><a href="https://www.youtube.com/watch?v=BY9KV8uCtj4">https://www.youtube.com/watch?v=BY9KV8uCtj4</a></li><li>Possible End of Humanity from AI? Geoffrey Hinton at MIT Technology Review’s<br><a href="https://www.youtube.com/watch?v=sitHS6UDMJc">https://www.youtube.com/watch?v=sitHS6UDMJc</a></li></ol><h3>Paper References</h3><ol><li>GPT:<br>Radford, Alec, Karthik Narasimhan, Jeffrey Wu, Rewon Child, David Luan, Dario Amodei, and Ilya Sutskever. “Improving language understanding by generative pre-training.” OpenAI Blog 1, no. 8 (2018).</li><li>GPT2:<br>Radford, Alec, Jeffrey Wu, Rewon Child, David Luan, Dario Amodei, and Ilya Sutskever. “Language models are unsupervised multitask learners.” arXiv preprint arXiv:1807.03819 (2018).</li><li>GPT-3:<br>Brown, Tom B., Benjamin Mann, Nick Ryder, Melanie Subbiah, Jared Kaplan, Prafulla Dhariwal, Arvind Neelakantan, et al. “Language models are few-shot learners.” arXiv preprint arXiv:2005.14165 (2020).</li><li>InstructGPT:<br>Ouyang, Long, et al. “Training language models to follow instructions with human feedback.” arXiv preprint arXiv:2203.02155 (2022).</li><li>GPT-4: <br>OpenAI. “GPT-4 Technical Report.” arXiv preprint arXiv:2303.08774 (2023).</li><li>Vaswani, Ashish, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser, and Illia Polosukhin. “Attention is all you need.” Advances in Neural Information Processing Systems 30 (2017): 5998–6008.</li><li>Silver, David, et al. “Reward is enough.” arXiv preprint arXiv:2104.08677 (2021).</li><li>Bubeck, Sébastien. “Sparks of AGI: Early Experiments with GPT-4.” arXiv preprint arXiv:2303.12712 (2023).</li><li>Strubell, Emma, Ananya Ganesh, and Andrew McCallum. “Energy and policy considerations for deep learning in NLP.” arXiv preprint arXiv:1906.02243 (2019).</li><li>Patterson, David A., Joseph Gonzalez, Christopher Ré, Jeffrey Dean, and Matei Zaharia. “Carbon emissions and large neural network training.” arXiv preprint arXiv:2104.10350 (2021).</li></ol><h3>Book References</h3><ol><li>Bostrom, Nick. Superintelligence: Paths, Dangers, Strategies. Oxford University Press, 2014.</li><li>Domingos, Pedro. The Master Algorithm: How the Quest for the Ultimate Learning Machine Will Remake Our World. Basic Books, 2015.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7e224a8a869c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy a Pycaret App to AKS using Azure Container Registry]]></title>
            <link>https://medium.com/@phylypo/deploy-a-pycaret-app-to-aks-using-azure-container-registry-fc9e56c378d0?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/fc9e56c378d0</guid>
            <category><![CDATA[azure-container-registry]]></category>
            <category><![CDATA[azure-aks]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[cloud-shell]]></category>
            <category><![CDATA[pycaret]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Tue, 08 Mar 2022 02:28:05 GMT</pubDate>
            <atom:updated>2022-03-12T07:22:30.226Z</atom:updated>
            <content:encoded><![CDATA[<p>This tutorial describes steps by steps to build a Docker container using a Pycaret App and push the image to Azure Container Registry (ACR) and then deploy it to Azure Kubernetes Service (AKS) using Cloud Shell. We will be using Azure API and some <em>kubectl </em>commands. You don’t need to anything to be installed on your computer. To follow along, you just need a web browser and an Azure subscription that can be signed up for <a href="https://azure.microsoft.com/en-ca/free/">free</a> if you never have one.</p><p>This is the summary of the steps that we will go over in this tutorial.</p><ol><li>Create Azure Container Registry (Private)</li><li>Build the Docker container</li><li>Push the image into ACR registry</li><li>Create AKS cluster and add a node pool</li><li>Create a Kubernetes secrete for accessing the registry</li><li>Deploy the container to AKS from private registry</li></ol><p>The code can be found here: <a href="https://github.com/phylypo/pycaret-deployment-azure">https://github.com/phylypo/pycaret-deployment-azure</a></p><h3>About the App</h3><p>This is an ML insurance application that predict the cost for customer. It is built using <a href="https://www.pycaret.org/">Pycaret </a>where the model is loaded from a saved <em>pkl </em>file. The web interface is built using Flask framework. The interface looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/902/0*DfjzXtsDH1R3SqRX" /></figure><h3>Environment Setup</h3><p>First, sign in to Azure portal (<a href="https://portal.azure.com/">https://portal.azure.com</a>).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/757/1*E-Xj91GLuvGKpkQ3ht2ajw.png" /></figure><p>From the top icon, click on <a href="https://docs.microsoft.com/en-us/azure/cloud-shell/overview">cloud shell</a> icon highlight in yellow above. You may need to setup your storage account for the first time. The storage would save all your files during your session. Make sure you select <a href="https://docs.microsoft.com/en-us/azure/cloud-shell/quickstart">Bash </a>not PowerShell.</p><p>You should see something like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/729/1*LQd_CGCFWE1VmorS_MWp4A.png" /></figure><p>We will do most of the work in this Bash command window.</p><h3>Create Resource Group</h3><p>Before creating any Azure resources, we will need a Resource Group to put all of Azure resource that we will create. At the end, we can delete this resource group and all the resources in this Resource Group will be deleted so we don’t incur any future charges.</p><p>We will be using a few variables to store values in this tutorial including the resource group name. Run the commands below in the cloud shell prompt.</p><pre>RESOURCE_GROUP=PYCARET-KUBE-RG<br>ACR_NAME=pycaretacr<br>CLUSTER_NAME=PYCARET-AKS</pre><p>The ACR_NAME sometimes is hardcoded in the commands in later steps for simplicity. Please change accordingly. Here is an example output.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/405/1*YJJ6_-rJlmdweDzak15IIQ.png" /></figure><p>Now, create the Resource Group using the Azure API command ‘<em>az</em>’ as follow. We put this resource in Western US availability zone ‘westus2’. Change this to your prefer zone as needed.</p><pre>az group create --name $RESOURCE_GROUP --location westus2</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*jd1s8rCThEsEKW2a7KDxdQ.png" /></figure><h3>Azure Container Registry (ACR)</h3><p>The Azure Container Registry (ACR) will be our private repository that store our Docker image that we will create. We will begin by creating ACR.</p><pre>az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Premium</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/783/1*dlLuSmPNQ-NJQ-kGmzNPyQ.png" /></figure><p>Clone the github repository</p><pre>git clone <a href="https://github.com/phylypo/pycaret-deployment-azure.git">https://github.com/phylypo/pycaret-deployment-azure.git</a><br>cd pycaret-deployment-azure</pre><p>Build Docker image</p><pre>az acr build --registry $ACR_NAME --image pycaret-ins-5000:v1 .</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*e_LSQkU-DHuazVuDCtJkgA.png" /></figure><p>This will take several minutes (4 minutes for me) and ignore some of the warning in red. When successful you should see similar to below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/797/1*3V04tUr0786ANTmt6Py3DQ.png" /></figure><p>We will verify via the result from the web portal in a bit but first let’s create AKS next.</p><h3>Create Kubernetes Cluster</h3><pre># create kubernetes cluster<br>az aks create \<br>    --resource-group $RESOURCE_GROUP \<br>    --name $CLUSTER_NAME \<br>    --node-count 2 \<br>    --enable-addons http_application_routing \<br>    --enable-managed-identity \<br>    --generate-ssh-keys \<br>    --node-vm-size Standard_B2s</pre><p>After about 10 minutes, you should see the output similar to below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/679/1*Rhc-9jvHTVRHegU2SnenFA.png" /></figure><p>Now add node pool the cluster.</p><pre># add node pool<br>az aks nodepool add \<br>    --resource-group $RESOURCE_GROUP \<br>    --cluster-name $CLUSTER_NAME \<br>    --name mypool \<br>    --node-count 2 \<br>    --node-vm-size Standard_B2s</pre><p>This will take several minutes. The output looks something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/584/1*tiQk9umolfkt3qqzfkJLWw.png" /></figure><h3>Reviewing Created Resources</h3><p>This will take several minutes so while waiting let’s verify our ACR. From the portal main screen, enter “<em>resource group</em>” in the search string and click on the “<em>Resource Groups</em>” result with the icon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/574/1*xUF-lzfwkJs8GnR8YvmUIw.png" /></figure><p>Now you should see the resource group we created along with AKS resource group <em>MC_&lt;Resource-group&gt;…AKS_…</em> which is part of Kubernetes cluster.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/585/1*8H6RqgOZrv7jNav_ClF-Ag.png" /></figure><p>Now, click the resource group PYCARET-KUBE-RG and you should see the resources in the resource group which is the Kubernetes service and the Container registry.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*xfbQdNC7go9wGGG-jDf-Ug.png" /></figure><h3>Setup the User and Password in ACR</h3><p>Let’s click on <em>pycaretacr </em>from above screen. Then in <em>Settings </em>menu on the left click <em>Access Keys</em>, then toggle to <em>Enabled </em>in <em>Admin user</em>. Now you should see the <em>Name </em>and <em>password</em>. Copy the two values these for the next step.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/829/1*8t3HQHbir2wFKSINPP1XGw.png" /></figure><h3>Create Azure Secret for registry credential</h3><p>We are going to create a Kubernetes secret so the cluster can use to download the image.</p><p>But first we need to setup the credential to the AKS with the follow command so it allow to use <em>kubectl </em>command.</p><pre>az aks get-credentials --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP</pre><p>You might be prompt to override if you have connect to AKS before.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1012/1*ONFwLl2SAm7pqV-xq-ovew.png" /></figure><p>Create the Kubernetes secret with the following command. Change the password to the string copy from the portal from previous steps. The username should be the same as ACR name unless you change it. Note the docker-server contain the url with <em>ACR_NAME.azurecr.io</em>, so change if needed.</p><pre>kubectl create secret docker-registry azure-reg-cred \<br>    --docker-username=pycaretacr \<br>    --docker-password=&lt;PASSWORD_COPIED_EARLIER&gt; \<br>    --docker-server=pycaretacr.azurecr.io</pre><p>You should see the secret get created. This will not check if the username/password is correct. This is just a variable for the deployment to use in the deployment file below with secret name “<em>azure-reg-cred</em>”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/1*CE1Ri_bwN7eoeT84mZHfbA.png" /></figure><h3>Deploy Service and Deployment</h3><p>Now we will run the kubectl command to create deployment and service using the image we upload in ACR and the secret we configured above. Here is a snippet of the code in azure_deployment.yaml.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/442/1*pkPJCoOZp0hUB_MEvzkPBg.png" /></figure><p>Run the <em>kubctl apply </em>with this file:</p><pre>kubectl apply -f azure_deployment.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/728/1*BeBc_zRda-xq9YQantu8gQ.png" /></figure><p>From the service public ip, browse to the ip</p><pre># check pod status -- should see Running<br>kubectl get pod<br># check for service ip -- to get EXTERNAL-IP<br>kubectl get service</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*kICX5b1dm6CJaP66FVy3Wg.png" /></figure><p>Now you can browse to the EXTERNAL-IP of your app and you should see the screen below and if you enter the form and click Predict, it should output the “Expected Bill” line.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/536/1*vA9ygemaFKBG60pE853MMA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/516/1*O4lpAjkzcg3VXBD3fD4nug.png" /></figure><p>You can check the amount of memory it uses with below command. Mine shows 322 MB for memory usage.</p><pre>kubectl top pod azure-insurance-bd9c6555c-f52h2 -n default --containers</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kJO9ohqAoZhtnIaE" /></figure><h3>Clean up</h3><p>After you done and want to clean up, you can run this command below to delete the resource group. Since we created all the resource in this resource group, it will also delete all the resources including the Kubenetes cluster and the registry. This will take over 15 mins to complete but the command will exit right away. You can verify to make sure all the resource are delete.</p><pre>az group delete --name $RESOURCE_GROUP --yes --no-wait</pre><h3>Troubleshoot</h3><p>I will not cover any troubleshooting in detail but it took me many tries to get this working so I just want to show the basic approach. To troubleshoot mainly get the node status in this case <em>ImagePullBackOff </em>error and you check the detail with <em>kubectl describe </em>command below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/658/1*d9xUgMmWaWf4OC4Y-A8PbA.png" /></figure><pre>kubectl describe pod azure-insurance-bd9c6555c-p68bz</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DXq73VjvEEWYBSMl8AqUOw.png" /></figure><p>This is an example that I input the wrong username/password in the secret.</p><h3>Summary</h3><p>We cover how to create Azure Container Registry (ACR), Azure Kubenetes Service (AKS) and how to build and deploy the image to ACR. Then deploy the image into the AKS and see the app running. We get into Kubernetes secret and many of <em>kubectl </em>command. These are all done through the browser without the need to install any application by Cloud Shell in Azure portal.</p><p>I hope you learn something from this. Happy coding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc9e56c378d0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SSL Using Let’s Encrypt CA on AKS]]></title>
            <link>https://medium.com/@phylypo/ssl-using-lets-encrypt-ca-on-aks-78464f05f3a1?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/78464f05f3a1</guid>
            <category><![CDATA[ssl-certificate]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[ak]]></category>
            <category><![CDATA[lets-encrypt]]></category>
            <category><![CDATA[cert-manager]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Sun, 16 Jan 2022 06:57:51 GMT</pubDate>
            <atom:updated>2022-01-16T07:02:00.972Z</atom:updated>
            <content:encoded><![CDATA[<p>This tutorial is part of the series on server certificates to secure websites with HTTPS.</p><ol><li>First, we look at how to <a href="https://medium.com/@phylypo/devops-automate-certificate-process-for-iis-5ae3b6788182">automate the creation of certificates</a> from your company Certificate Authority (CA) on Windows OS.</li><li>Then we look at how to use free issuer <a href="https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0">“Let’s Encrypt” to generate the certificate</a> on Windows and Linux.</li><li>Now in this tutorial, we will look into setting up a certificate on Kubernetes.</li></ol><p>In this step-by-step tutorial, we are going to set up SSL/TLS on the Ingress Controller using Nginx-ingress to handle HTTPS traffic to the Kubernetes service running on Azure Kubernetes Service (AKS). The certificate we are using is issued by Let’s Encrypt, a free service running as an Automated Certificate Management Environment (ACME) by using cert-manager.</p><p>The code is mainly based on the tutorial by Marcel Dempers in the reference section but updated for Kubernetes running on Azure cloud or Azure Kubernetes Service (AKS) rather than running locally using miniKube or Kind.</p><p>The source code can be found here: <a href="https://github.com/phylypo/kubernetes/tree/main/cert_devops">https://github.com/phylypo/kubernetes</a></p><h3>Let’s Get Started</h3><p>We assume you have Azure account to create resources like AKS. So first, log in to the <a href="https://portal.azure.com/">Azure portal</a>. We will be using Azure API to run all of our commands by using Cloud Shell. Click on the Cloud Shell icon as highlighted below. If this is the first time running Cloud Shell, you need to set up a storage account first.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1kkgSXPIpzuKOaVln5GXAg.png" /></figure><p>After you launched Cloud Shell, you should see the terminal like below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/854/1*kt2NOM2A_3Al6fXkC7U2XQ.png" /></figure><p>Now you can clone the code from<a href="https://github.com/phylypo/kubernetes"> this project</a> in GitHub that contains the source code so you can follow along.</p><pre>git clone <a href="https://github.com/phylypo/kubernetes.git">https://github.com/phylypo/kubernetes.git</a><br>cd kubernetes/cert_devops</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5GiQIBVBCsucRbtT-k0Vhg.png" /></figure><p>The directory cert_devops contains the configuration files that are needed for this tutorial. All the commands are in cert_devops.sh file.</p><h4>Create AKS cluster</h4><p>First, we need to create an Azure Kubernetes Cluster. We are going to use a new resource group “k8rg” to place all our resources which can be easily cleaned up afterward.</p><pre>az group create --name k8rg --location westus2<br>az aks create --resource-group k8rg --name myAKSCluster --node-count 1</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/978/1*v35nk9GwPz7gv_pPoso1EA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YPbq6PkOunXVfHxCt7dLOA.png" /></figure><p>The last command can take a few minutes. Once done we want to set up the credential for <em>kubectl. </em>The get-credentials commands will ask to override or merge the configuration if the config exists. Then we can test out the <em>kubectl</em> commands.</p><pre>az aks get-credentials --resource-group k8rg --name myAKSCluster<br># test kubectl<br>kubectl get pod<br>kubectl get services</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*09PVVFbx7ICYYKckqGxnsA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/762/1*WTJRl37D9ksAUjFvzt9j3w.png" /></figure><h4>Install Cert-Manager</h4><p>Now install cert-manager to handle certificate creation. We will test with a self-signed certificate first to ensure cert-manager is working properly. Then proceed with Let’s Encrypt in the later section.</p><pre>kubectl apply --validate=false -f cert-manager.yaml<br>kubectl -n cert-manager get all</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*coTckh0QmeqFPCC6op2f-Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1002/1*ztN7jyr_IjuWC11NkwpWeQ.png" /></figure><p>Create a self-signed certificate to test the cert-manager.</p><pre># create a test namespace <br>kubectl create ns cert-manager-test</pre><pre># create a self sign issuer<br>kubectl apply -f ss_issuer.yaml<br># create certificate<br>kubectl apply -f ss_certificate.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/867/1*VV9Tr1Ds6kSRCDRTC1kEOA.png" /></figure><p>Now verify that the certificate is created.</p><pre>kubectl describe certificate -n cert-manager-test<br>kubectl get secrets -n cert-manager-test<br># cleanup by deleting the namespace and testing resources<br>kubectl delete ns cert-manager-test</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OFfAw3VxTOI5NhJFiR2pKg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/927/1*zfk3VtGn8sMV_no0YlnDnw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/869/1*IBhl2q5Lr98PYg84zO2rUg.png" /></figure><h4>Create Ingress Controller</h4><p>We are going to create an Ingress Controller in the namespace “ingress-nginx”.</p><pre>kubectl create ns ingress-nginx <br>kubectl -n ingress-nginx apply -f deploy-ingress-ctl.yaml<br># see all the different components created<br>kubectl -n ingress-nginx get all</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S_xsAfZqu3BGwRFnDpUmUA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yCe_1PeZciSGONOmRFCxYQ.png" /></figure><p>Now browse to the public IP to see if the ingress is showing the nginx reponse. From the screen above, it is in the service output under the EXTERNAL-IP which is 20.64.143.87. You should see “404 Not Found” message from nginx since we have not configured the ingress controller.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/857/1*ePFIb_zIPXj1ZaAe6YTRag.png" /></figure><h4>Setup DNS</h4><p>Now we can set up our DNS that will be used in the URL to point to this IP address. This Ingress Controller listens to both ports 80 and 443 for HTTPS.</p><p>Here is an example for my DNS cert.tovnah.com to point to this IP. This change may take some time to propagate depending on your service provider. Mine took about 15 mins. You can verify by checking <em>nslookup </em>command (<em>nslookup cert.tovnah.com</em>) and you should see the new ip address you updated.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i4vtx899epNIY9YeizZNLg.png" /></figure><h4>Setup Let’s Encrypt Issuer</h4><p>Now we will set up the certificate issuer, in this case, we use “Let’s Encrypt” that will be signing our certificate.</p><pre>kubectl apply -f cert-issuer-nginx-ingress.yaml <br>kubectl describe clusterissuer letsencrypt-cluster-issuer</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1zwIhTDaGioDPFmu0PCCFg.png" /></figure><p>Now we can deploy a test app for the ingress controller to forward the traffic.</p><pre>kubectl apply -f deployment-app.yaml<br>kubectl apply -f service-app.yaml<br>kubectl get pods</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/875/1*5f0sJQKATBlfyg25Oqxt6A.png" /></figure><p>Next, we need to point the ingress controller to this app. First edit ingress.yaml and replace “&lt;your.dns.com&gt;” with the correct hostname in my case “cert.tovnah.com”.</p><pre>code ingress.yaml<br>kubectl apply -f ingress.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*wX6bUz7pAI1CJeD1dv_MmQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*fPxlOj4NBqe_xnxRcUy0hg.png" /></figure><pre>kubectl get servies</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/934/1*aTLCPzOFIlP5JXbvtE6lrQ.png" /></figure><p>Now browse to our new app and we should see the “Hello World!” message using the public IP of the app.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/437/1*M44FQtI1s6K3S3EJN_B8cQ.png" /></figure><h4>Setup Certificate</h4><p>Now, we will create a certificate that will be issued by Let’s Encrypt issuer.</p><pre># first edit the certificate.yaml by updating the dns name<br>code certificate.yaml<br>kubectl apply -f certificate.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/759/1*cVZdOxdWNTMsSqnRBj3Puw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/848/1*nZ0PatSZjtpAUpYeKsnVUg.png" /></figure><p>Verify that the certificate is created successfully.</p><pre>kubectl describe certificate example-app</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OsrZ6tR7jV5bWo3hIFtfcg.png" /></figure><p>You should see the last entry if a successful message in the <em>Events</em> section.</p><pre>The certificate has been successfully issued</pre><p>Check secret and should see the type: kubernetes.io/tls</p><pre>kubectl get secret</pre><p>Now test browsing to the DNS name and you should see the lock and valid certificate issued by Let’s Encrypt (R3).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/344/1*cJJpdi7I25FuaT7OpdahDQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/468/1*n4RVXEezmov6liUUlXnr9Q.png" /></figure><h4>Summary</h4><p>We have looked at how to create a Kubernetes cluster, install cert-manager that allows us to use “Let’s Encrypt” to issue us a certificate. We deployed an nginx Ingress Controller and an example app in the Kubernetes cluster. Then we create a certificate to bind to the ingress controller that points to the example app. This allowed us to use HTTPS to access our app. We are using Azure API through Cloud Shell which allows us to run all the commands via a web browser.</p><p>This concludes our series on setting up server certificates. I hope this gives you a good understanding of setting up a certificate for your app.</p><p>To delete all of the resources in Azure that we have set up in this tutorial so that we don’t pay for the unused resources in Azure, we can simply delete the resource group that we initially created.</p><pre>az group delete --name k8rg --yes --no-wait</pre><p>If you follow the tutorial from Youtube below by creating your local Kubernetes cluster on your home machine, you need to make sure your router settings is forwarding the traffic on specific ports to your machine.</p><p>In the router settings, you need to open both 80 and 443 port forwarding to the machine IP. Notice that port 80 is needed for Let’s Encrypt challenges.</p><p>In my Linksys router it looks something like this under Security:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qbgSizD_tDoMOaR555dGNg.png" /></figure><p>In addition, if you have McAfee running, you will need to disable McAfee Firewall temporarily. If you have the Windows firewall as your primary service, you will need to disable that.</p><h3>Reference</h3><p>Youtube Tutorial: <a href="https://www.youtube.com/watch?v=hoLUigg4V18">https://www.youtube.com/watch?v=hoLUigg4V18</a></p><p>Github: <a href="https://github.com/marcel-dempers/docker-development-youtube-series/tree/master/kubernetes/cert-manager">https://github.com/marcel-dempers/docker-development-youtube-series/tree/master/kubernetes/cert-manager</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=78464f05f3a1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using “Let’s Encrypt” Certificate Authority]]></title>
            <link>https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/e890ecd0c9e0</guid>
            <category><![CDATA[lets-encrypt]]></category>
            <category><![CDATA[digital-certificates]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[ssltls]]></category>
            <category><![CDATA[certificate-authority]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Tue, 04 Jan 2022 05:33:43 GMT</pubDate>
            <atom:updated>2022-01-16T06:54:58.306Z</atom:updated>
            <content:encoded><![CDATA[<p>This tutorial is part of the series on server certificates to secure websites with HTTPS.</p><ol><li>First, we look at how to <a href="https://medium.com/@phylypo/devops-automate-certificate-process-for-iis-5ae3b6788182">automate the creation of certificates</a> from your company Certificate Authority (CA) on Windows OS.</li><li>Then we look at how to use free issuer <a href="https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0">“Let’s Encrypt” to generate the certificate</a> on Windows and Linux.</li><li>Lastly, we will look into <a href="https://medium.com/@phylypo/ssl-using-lets-encrypt-ca-on-aks-78464f05f3a1">setting up a certificate on Kubernetes</a>.</li></ol><p>Let’s Encrypt provides free digital certificate generation in an automated way. In addition, it provides a full life cycle certificate management as Automatic Certificate Management Environment (ACME) that automatically re-new the certificate as needed.</p><h3>Using Let’s Encrypt for Windows IIS</h3><p>The step below shows the automation of creating digital certificates without having your own Certificate Authority. Instead, we use “Let’s Encrypt” for free.</p><p>First, let see how the HTTPS with invalid sites would look like.</p><p>The first step is the create HTTPS site binding with any generic certificate. To do this, edit site binding and choose an existing certificate temporarily so you can proceed with clicking OK.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*zJMPF-4gxgY1fFeW.png" /></figure><p>You will see an invalid certificate when browsing using IE with a similar screenshot below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/519/0*asQbh4hXmKl2PYMa.png" /></figure><p>Here is a screenshot of an invalid certificate when browsing with Chrome.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*lVkaq-Kv-Jq3CO3y.png" /></figure><p>Now we will set up a process to generate a certificate from Let’s Encrypt. I follow the instruction from Youtube in the reference below. Here are the steps:</p><ol><li>Download the win-acme client from: <a href="https://www.win-acme.com/">https://www.win-acme.com/</a></li><li>Then extract into a permanent directory since the app will create a task scheduler where you run from. Now run the <em>wacs.exe</em> file and choose your site to generate the certificate.</li><li>Then set up site binding to listen to HTTPS</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/519/0*rGuQsAl5T9x4fBSz.png" /></figure><p>You can look at the scheduled renewal in Task Schedule to verify that it will get renewal when the certificate is about to expire.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*sAlCttCM2275si5e.png" /></figure><p>Now you should be able to see the secure website from the browser.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*8mty4KgKBc3aw1WH.png" /></figure><h3>Using Let’s Encrypt for Linux</h3><p>Whether you use Apache or Nginx on any flavor of Linux, Let’s Encrypt has instructions for setting it up. Just go to <a href="https://certbot.eff.org/">https://certbot.eff.org/</a> and choose your app and OS.</p><p>Here is a highlight of using Nginx on Ubuntu.</p><p><em>1.Install the certbot and the related python package for nginx</em></p><pre><em>#sudo  apt install certbot python3-certbot-nginx</em></pre><p>2.Run the certbo and specify the nginx</p><pre><em>#sudo certbot --nginx</em></pre><p>The command will prompt you for email and also determine the DNS for the certificate and output the certificate.<br>Here is an example output:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/626/0*VveGuzy_q1Qrjg2-.png" /></figure><p>It added the SSL portion in the config similar to below:</p><pre>listen 443 ssl; # managed by Certbot<br>ssl_certificate /etc/letsencrypt/live/ml.tovnah.com/fullchain.pem; # managed by Certbot<br>ssl_certificate_key /etc/letsencrypt/live/ml.tovnah.com/privkey.pem; # managed by Certbot<br>include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot<br>ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot</pre><p>It will also ask if you want to redirect your HTTP to HTTPS. I choose yes. Then the successful output should look like this:</p><pre>— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —<br>Congratulations! You have successfully enabled <a href="https://ml.tovnah.com/">https://ml.tovnah.com</a>You should test your configuration at:<a href="https://www.ssllabs.com/ssltest/analyze.html?d=ml.tovnah.com">https://www.ssllabs.com/ssltest/analyze.html?d=yourdomain.com</a><br>— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —</pre><p>I tried the test URL and it went into detail on the certificate, protocol, key exchange, and cipher strength. See the output report below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*I78kzYjJUSfGY0K4.png" /></figure><p>Note that if the server support TLS 1.1 and 1.0 the grade on the protocol will be B. Those protocols are suggested to be disabled.</p><p>The next step is to test the renewal with this command with dry-run to ensure the process is working:</p><pre># sudo certbot renew — dry-run</pre><p>You should see the “<em>Congratulations, all renewals succeeded</em>” message.</p><p>Lastly, you need to confirm that there is a cron job that kept checking for certificate expiration and renewal as needed. In my case, I can see it with this command:</p><pre># systemctl list-timers</pre><p>You should see an entry for <em>certbot.timer</em>.</p><pre>NEXT                         LEFT      LAST  PASSED  UNIT<br>Tue 2022–01–04 11:40:29 UTC  17h left  n/a   n/a     certbot.timer</pre><p>Next, we will look into <a href="https://medium.com/@phylypo/ssl-using-lets-encrypt-ca-on-aks-78464f05f3a1">setting up a certificate on Kubernetes</a>.</p><h3>Relate Notes and References</h3><p>How to Install Lets Encrypt Certificates on IIS with Autorenew: <a href="https://www.youtube.com/watch?v=vbk5kUT7GeY">https://www.youtube.com/watch?v=vbk5kUT7GeY</a></p><p><a href="https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04">How To Secure Apache with Let&#39;s Encrypt on Ubuntu 18.04 | DigitalOcean</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e890ecd0c9e0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DevOps: Automate Certificate Process for IIS]]></title>
            <link>https://medium.com/@phylypo/devops-automate-certificate-process-for-iis-5ae3b6788182?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/5ae3b6788182</guid>
            <category><![CDATA[isis]]></category>
            <category><![CDATA[ansible]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[server-certificate]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Mon, 04 Oct 2021 15:47:40 GMT</pubDate>
            <atom:updated>2022-01-16T06:55:02.907Z</atom:updated>
            <content:encoded><![CDATA[<p>This tutorial is part of the series on server certificates to secure websites with HTTPS.</p><ol><li>Here, we look at how to automate the creation of certificates from your company Certificate Authority (CA) on Windows OS.</li><li>Then we look at how to use free issuer <a href="https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0">“Let’s Encrypt” to generate the certificate</a> on Windows and Linux.</li><li>Lastly, we will look into <a href="https://medium.com/@phylypo/ssl-using-lets-encrypt-ca-on-aks-78464f05f3a1">setting up a certificate on Kubernetes</a>.</li></ol><h4>Introduction</h4><p>HTTPS is an important part of having secured communication between your site and the users. This Public Key Infrastructure (PKI) framework allows the encryption of the communication via the public and private keys. The server public key which is signed by an authoritative certificate authority (CA) is trusted by the browser. This trust system will ensure that no one else can decrypt the data except two parties that are communicating.</p><p>As we set up more and more web services on Windows IIS with HTTPS, automation becomes a time saving for DevOps to automate this process. This page detail the process to automate the digital certificate signing process using your company CA. The automation involves using Ansible to generate a certificate signing request (CSR) and get the CA to sign the certificate then import it into IIS to bind a website as HTTPS.</p><p><strong>Architecture and tools</strong></p><ol><li>Ansible server (we use AWX running on Linux)</li><li>Windows Server with IIS for web hosting</li><li>Certificate Authority on Windows server</li></ol><p>First, we will look at the manual process to create a certificate request to get it signed and then complete the certificate import and then create a binding to enable HTTPS. After that, we will look at how to automate each process using Ansible.</p><p><strong>Assumptions</strong></p><ol><li>You have your own Certificate Authority server.</li><li>You have Ansible setup for automation. The ansible code will only cover the portion related to the task.</li></ol><h3>Manual Process to Setup Https</h3><p>We will start with a summary of what the process involves.</p><ol><li>From the webserver, we first need to create a certificate signing request (CSR). This process involves creating a private key and generating CSR file with information about the server such as a common name that the CA can sign to create a certificate. This process allows only the server with the corresponding private key to use the certificate.</li><li>Take the CSR file generated and use the CA to sign and generate the certificate. The CA will output a CER file.</li><li>From the web server, we can import the CA file in the complete certificate request function. This will import to the server local store.</li><li>Now we can set up the website on IIS to bind as HTTPS using this certificate.</li></ol><p>Now let us look into the detail of each step.</p><h4>1. Creating CSR</h4><p>From the webserver, in Server Management, double click <strong>Server Certificates</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/809/1*Fu0hyL04BTvVXCbjMgRQrA.png" /></figure><p>Then select “Create Certificate Request” on the Actions tab and fill in the information.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*Q7nUfXVpbbtpqczEwfgHTA.png" /></figure><p>Click Next, then select Cryptographic Service Provider such as change Bit length to 2048 and click Next.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/671/1*wA9wpGZa3CZUbgrUIWo87Q.png" /></figure><p>Then save the file and click Finish.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/678/1*qAiwIvKOyPeDHiTCZZ8yvA.png" /></figure><p>Example output file:</p><pre>-----BEGIN NEW CERTIFICATE REQUEST-----<br>MIIEOzCCAyMCAQAwVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH<br>...<br>fbceNKxOOlIyDFYMe36tzf/+EnkjDOFiZUR2kp5KVZquPflXDPIElhhbSgo2jaO8<br>nlq6Vewcu1HxLlQSLLoGOIN9eXX/qRoNcl+H+HgsOw==<br>-----END NEW CERTIFICATE REQUEST-----</pre><h4>2. Sign the CSR and Generate a Certificate in CA</h4><p>In these steps, log in to your Certificate Authority (CA) server and import your CSR file that was created from the previous step.</p><p>First, open the CA tool from the Server Management, select the Tools menu, and then select “Certification Authority”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8uMOBrI3KIn-oPXHcwHKTg.png" /></figure><p>From the server icon, right-click and select “All Tasks”, then select “Submit new request…”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/477/1*uun_oZUpQkg70RxwfBMexA.png" /></figure><p>Then select the file created from the previous step.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/570/1*lCxDDL_RWjc29gGAYtZrcg.png" /></figure><p>Then from the “Pending Requests” folder, right-click the item, select “All Tasks” then select “Issue”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/759/1*YAbR9V4Jwd4SwUBftUO-nw.png" /></figure><p>Now the request will be moved to “Issued Certificates”. You can double-click to verify the certificate information.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/757/1*mcTdqPLotf26lR-r3sYPFg.png" /></figure><p>Now export the certificate for IIS by right-clicking on the certificate, then selecting “All Tasks” and “Export Binary Data…”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/457/1*t-Ac6eRKOBD1RKa1hbgK8w.png" /></figure><p>Now select “Binary Certificate” from the Column that contains binary data, and select “Save binary data to a file” for Export options.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/761/1*MYIgW3x82oiBAfRkhy27GA.png" /></figure><p>Then select the directory and file to save.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/667/1*ED8VajgadwThZjwvXtCBlQ.png" /></figure><h4>3. Complete Certificate request in IIS</h4><p>Now go back to the webserver and complete the certificate request. From the Server Certificate, click on “Complete Certificate Requests…”. Then choose the file from the previous step, and enter the Friendly name that will be shown in the certificate personal store, and click OK.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1011/1*ASJJh3K87iSG7NsQ7cWYTg.png" /></figure><p>Now you should see the new certificate, you are ready for the binding with your website.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/581/1*LSmXiBNTd4bo00QuQpC7uQ.png" /></figure><h4>4. Bind the certificate to HTTPS</h4><p>From your site, select Binding…, then click “Add…”. On the “Add Site Binding” screen change the Type to “https”, then add hostname. Finally, select the newly created certificate and click OK.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/533/1*XMAzwQ2AvjFZYHZbob2mWQ.png" /></figure><p>Now you should be able to have the site configured for HTTPS.</p><h3>DevOps Automation</h3><p>Now we cover the automation part with Ansible. We will divide into 4 different steps:</p><ol><li>Automate CSR Request</li><li>Automate Generation of File and Script for CA</li><li>Automate Signing and Generating Certificate</li><li>Automate Importing and Binding the Certificate in IIS</li></ol><p>With each of the steps, we want to check the state that if the certificate already exists it does not regenerate. This approach is all based on the existing share drive data that indicate if the CSR or CER file is needed.</p><p>Let’s us go into detail.</p><h4>1. Automate CSR Request</h4><p>We will be using <a href="https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certreq_1"><em>certreq.exe</em></a> to generate the CSR. The command takes in a conf file and the name of the output CSR file.</p><p>certreq.exe -new reqconfig.inf cert_csr.txt</p><p>A simple example of reqconfig.inf:</p><pre>[NewRequest]<br>; At least one value must be set in this section<br>subject = &quot;CN=test.tovnah.com&quot;<br>Exportable = TRUE<br>KeyLength = 2048<br>KeySpec = 1<br>KeyUsage = 0xf0<br>MachineKeySet = TRUE</pre><p>When you run the command you should see the output file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/473/1*7jGVrucQZJ4iYBY6XM_vDg.png" /></figure><p>Example of the output CSR file:</p><pre>-----BEGIN NEW CERTIFICATE REQUEST-----<br>MIIDpTCCAo0CAQAwGjEYMBYGA1UEAwwPdGVzdC50b3ZuYWguY29tMIIBIjANBgkq<br>hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApjsXV8PicJFrbsCgCbNai6DaPmUmwFjm<br>&lt;cut for brevity&gt;<br>gzNZn7KBFxwIW8xM+mLr1D7sLNTqodSlo0yMyXP+9BhthwIpblktLutDblh7b745<br>kdETiEodJa2qk2dIZTpNfgUs7kmB7b6AVw==<br>-----END NEW CERTIFICATE REQUEST-----</pre><p>To automate this, in Ansible we use the <em>win_command</em> module in our task. It looks like this:</p><pre>- name: &#39;Generate Certificate Signing Request (CSR)&#39;<br>  win_command: &#39;certreq -new -f {{cert_req_inf}} {{csr_file}}&#39;<br>  register: cmdout<br>  become: yes<br>  become_method: runas<br>  become_flags: logon_type=new_credentials logon_flags=netcredentials_only<br>  vars:<br>    ansible_become_user: &#39;{{admin_usr}}&#39;<br>    ansible_become_pass: &#39;{{admin_passwd}}&#39;</pre><p>Notice that we run <em>runas</em> to become the user that has permission to generate the CSR.</p><h4>2. Automation Generating File and Script for CA</h4><p>The request file config and the output CSR file are put in the share directory so it can be accessed from the webserver and the CA server. The folder structure is set up to have one server request per folder.</p><p>The <em>cert_req_inf </em>file is generated certificate to match its hostname. To accommodate this we use the <em>win_template </em>module.</p><pre>- name: Create cert_req_inf file from template<br>  win_template:<br>     src: &#39;cert_req_inf.j2&#39;<br>     dest: &#39;{{cert_req_inf_file_path}}&#39;<br>  become: yes<br>  become_method: runas<br>  become_flags: logon_type=new_credentials logon_flags=netcredentials_only<br>  vars:<br>    ansible_become_user: &#39;{{admin_usr}}&#39;<br>    ansible_become_pass: &#39;{{admin_passwd}}&#39;</pre><p>The template file will have the full content just with variables it can substitute to match the specific hostname. The template file will look something like this:</p><pre>[NewRequest]<br>Subject = &quot;CN={{ssl_cert_subject}}&quot; ; website hostname<br>Exportable = TRUE ; TRUE = Private key is exportable<br>KeyLength = 2048 ; Valid key sizes: 1024, 2048, 4096, 8192, 16384<br>KeySpec = 1 ; Key Exchange – Required for encryption<br>KeyUsage = 0xA0 ; Digital Signature, Key Encipherment<br>MachineKeySet = True<br>ProviderName = &quot;Microsoft RSA SChannel Cryptographic Provider&quot;<br>RequestType = PKCS10 ; or CMC.</pre><pre>[EnhancedKeyUsageExtension]<br>; If you are using an enterprise CA the EnhancedKeyUsageExtension section can be omitted<br>OID=1.3.6.1.5.5.7.3.1 ; Server Authentication<br>OID=1.3.6.1.5.5.7.3.2 ; Client Authentication</pre><pre>[Extensions]<br>; If your client operating system is Windows Server 2008, Windows Server 2008 R2, Windows Vista, or Windows 7<br>; SANs can be included in the Extensions section by using the following text format. Note 2.5.29.17 is the OID for a SAN extension.<br>2.5.29.17 = &quot;{text}&quot;<br>_continue_ = &quot;dns={{ssl_cert_subject}}&amp;&quot;<br>_continue_ = &quot;dns={{ssl_cert_subject}}.mycompany.com&quot;</pre><pre>[RequestAttributes]<br>; If your client operating system is Windows Server 2003, Windows Server 2003 R2, or Windows XP<br>; and you are using a standalone CA, SANs can be included in the RequestAttributes<br>; section by using the following text format.<br>&quot;SAN=&quot;dns={{ssl_cert_subject}}&amp;dns={{ssl_cert_subject}}.mycompany.com&quot;<br>; Multiple alternative names must be separated by an ampersand (&amp;).<br>CertificateTemplate = MyWebServerTemplate ; Modify for your environment by using the LDAP common name of the template.</pre><p>The same is needed to generate the batch command file that will be executed at the CA server to sign and generate the certificate.</p><pre>- name: Create sign_req.bat file from template<br>  win_template:<br>     src: &#39;sign_req.bat.j2&#39;<br>     dest: &#39;{{cert_bat_file_path}}&#39;<br>  become: yes<br>  become_method: runas<br>  &lt;same options as earlier&gt;</pre><p>The <em>sign_req.bat</em> will be using the same <em>certreq.exe</em> command with <em>submit </em>option. Make sure you get the config option correct, or you will get the prompt that needs to click which will pause and fail the automation. Test your script and ensure you don’t get the prompt.</p><p>Here is an example output of the sign_req.bat file:</p><pre>certreq ^<br>-config &quot;&lt;ca_cert_server\mycompany-ca&gt;&quot; ^<br>-attrib &quot;CertificateTemplate:MyWebServerTemplate&quot; ^<br>-submit &quot;new_ssl_cert_req.csr&quot; &quot;my_cert.cer&quot;</pre><h4>3. Automate Signing and Generating Certificate</h4><p>After the batch file is generated, we just need to run that file in the CA server. Since the host that we have been running is on the webserver, we need to give WinRm access to all of the web servers. If you need to automate a lot of the web servers, this might pose more security risks. One approach to limit the risk is by giving WinRm access to the CA server to only the ansible server and you can harden the firewall accordingly. To run a remote connection from the Ansible server, we use the <em>delete_to </em>command.</p><pre>- import_tasks: cert_gen.yml<br>  delegate_to: localhost</pre><p>The trick is that the cert_gen task will use <em>delegate_to </em>to connect to the CA server. So from localhost, which is the Ansible server, we delegate_to CA server to a batch file. In that case, the Ansible server will remote connect to CA server using WinRM and execute the batch file. The Ansible code in the cert_gen task looks like this</p><pre># tasks/cert_gen.yml  <br>- name: &#39;Execute Submit_req.bat to sign and create certificate&#39;<br>  win_command: &#39;{{cert_bat_file_path}}&#39;<br>  become: yes<br>  become_method: runas<br>  &lt;similar options as earlier&gt;<br>  delegate_to: &#39;{{ca_cert_server}}&#39;</pre><h4>4. Automate Importing and Binding the Certificate in IIS</h4><p>We can import the certificate using the <em>win_certificate_store </em>module. The Ansible code is as follow:</p><pre>- name: &#39;Importing Certificate:{{cert_cer_file_path}}&#39;<br>  win_certificate_store:<br>    path: &#39;{{cert_cer_file_path}}&#39;<br>    store_location: LocalMachine<br>    key_storage: machine <br>    key_exportable: yes<br>    state: present<br>  become: yes<br>  become_method: runas<br>  &lt;same options as early&gt;<br>  register: cert_import</pre><p>Again, the <em>cert_cer_file_path</em> is the <em>cer</em> file in the share drive that the CA and webserver have access to. The <em>runas </em>option is important since that user has access to the share drive.</p><p>Note that we register to <em>cert_import </em>variable. This is important for us to be able to get the thumbprint for the next few steps.</p><p>We also need an extra step to repair the certificate from the import process.</p><pre>- name: &#39;Repair import cert in case private key is missing&#39;<br>  win_command: &#39;certutil -repairstore my &quot;{{cert_import.thumbprints[0]}}&quot;&#39;<br>  become: yes<br>  become_method: runas<br>  &lt;same options as early&gt;<br>  when: cert_import.changed == true</pre><p>Next is to bind the HTTPS to this certificate thumbprint with <em>win_iis_webbinding </em>module.</p><pre>- name: &#39;Configure https binding&#39;<br>  win_iis_webbinding:<br>    name: &#39;&lt;my hostname&gt;&#39;<br>    protocol: &#39;https&#39;<br>    host_header: &#39;&lt;my hostname&gt;&#39;<br>    port: &#39;443&#39;<br>    state: &#39;present&#39;<br>    certificate_hash: &#39;{{cert_import.thumbprints[0]}}&#39;</pre><p>Other steps may include the DNS update <em>win_dns_record </em>module as you create a new DNS A-record for the website.</p><p>Hope this will be helpful in your process to automate certificate creating and binding. Let me know your feedback below.</p><p>Next, see how we can <a href="https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0">use a free certificate issue “Let’s Encrypt”</a> to generate certificates for us.</p><h3>Other Format and Tools</h3><p>We only cover the IIS setup above. A similar process can apply to set up the certificate on different applications and OS. But you need the right format that each application is expecting.</p><h4>PEM Encoded</h4><p>Some applications expect two files as input: a public key and a private key in PEM format. PEM or <strong>P</strong>rivacy <strong>E</strong>nhanced <strong>M</strong>ail is a Base64-encoded of the binary formatted certificate or DER. To take the certificate in our IIS and convert it to PEM format we can use <em>openssl</em> utility that is available in many OS.</p><p>To produce a format that OpenSSL needs, you will have to export the certificate into a <em>pfx</em> (Personal Information Exchange) format that has a public and a private key. From the Windows Certificate plugins in MMC, select the desired certificate and select “All Tasks”, then “Export…”. In the Certificate Export Wizard, select the “Yes, export the private key” option and enter the password when prompted.</p><p>This password is needed by the OpenSSL command below when the tool try to open the pfx file.</p><pre>openssl pkcs12 -in c:\mycert.pfx -clcerts -nokeys -out c:\mycert.pem</pre><pre>openssl pkcs12 -in c:\mycert.pfx -clcerts -nocerts -out c:\mykey.pem -nodes</pre><p>These commands will ask for the password and out the file <em>mycert.pem</em> which is the public key and <em>mykey.pem</em> which is the private key.</p><p>Other applications may require one PEM encoded file that contains a private and a public key. To produce the file from the <em>pfx</em> format above, run:</p><pre>openssl -in c:\mycert.pfx -out c:\mycert.pem<br><em>Enter Import Password:<br>Enter PEM pass phrase:<br>Verifying — Enter PEM pass phrase:</em></pre><p>This will first prompt for “Import Password” to open the pfx file, then it will prompt for “PEM pass phrase” to be set.</p><h4>Java Keystore</h4><p>For applications that use Java such as Tomcat, you may need a different tool to convert your certificate. Java has a <em>keytool</em> that can store the certificate and its key. Some options in Tomcat can import <em>crt</em> and <em>pem</em> format directly.</p><p>Here is the <em>keytool</em> command that imports the certificate and the key into a key store.</p><pre>keytool -importkeystore -deststorepass &lt;DEST_STORE_PASSWORD&gt;<br>-destkeypass &lt;DEST_KEY_PASSWORD&gt;<br>-destkeystore &lt;KEYSTORE_FILENAME&gt;<br>-srckeystore &lt;PKCS12_KEYSTORE_FILENAME&gt; -srcstoretype PKCS12<br>-srcstorepass &lt;PKCS12_KEYSTORE_PASSWORD&gt; alias tomcat</pre><p>The KEYSTORE_FILENAME defaulted under your profile directory with the name “<em>.keystore”</em> (ie. c:\Users\me\.keystore). Some use the convention of naming <em>jks</em> extension such as <em>mykeystore.jks</em>.</p><p>If you use the <em>keytool</em> to create the CSR request then you can use the <em>keytool</em> command with “<em>-importcert</em>” option to import the certificate signed by your CA. See more options using simple guide <a href="https://www.rapidsslonline.com/blog/simple-guide-java-keytool-keystore-commands/">here</a>.</p><p>In the next post, you see how you can <a href="https://medium.com/@phylypo/using-lets-encrypt-certificate-authority-e890ecd0c9e0">use a free Let’s Encrypt Certificate Authority</a> that has a complete life cycle automation.</p><h3>References</h3><ul><li><a href="https://adamtheautomator.com/iis-certificate-request/">How to Generate an IIS Certificate Request with PowerShell (and Bind)</a></li><li><a href="https://www.prajwaldesai.com/install-enterprise-root-certificate-authority/">Install Enterprise Root Certificate Authority</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5ae3b6788182" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Overview of Time Series Forecasting from Statistical to Recent ML Approaches]]></title>
            <link>https://medium.com/@phylypo/overview-of-time-series-forecasting-from-statistical-to-recent-ml-approaches-c51a5dd4656a?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/c51a5dd4656a</guid>
            <category><![CDATA[transformers]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[timeseries]]></category>
            <category><![CDATA[arima]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Sat, 05 Dec 2020 03:51:27 GMT</pubDate>
            <atom:updated>2021-10-14T21:58:20.840Z</atom:updated>
            <content:encoded><![CDATA[<h3>Overview</h3><p>Time series forecasting is an important topic for machine learning to predict future outcomes or extrapolate data such as forecasting sale targets, product inventories, or electricity consumptions. I found many general ML classes that cover specific context in detail but not in a full scope. This post hope to cover a wider scope by highlighting the different approaches to time series forecasting from statistical methods to a more recent state of the arts deep learning algorithms in late 2020.</p><p>The topics will be as follow:</p><ol><li>Statistical technique: ARIMA</li><li>Exponential smoothing approaches (MA, Holt ES, Double ES, Holt-Winter)</li><li>ML algorithms with Linear Regression and XGBoost</li><li>Deep Learn approaches with CNN, RNN, and Transformer <br>(LSTM, CNN with LSTM, TCN, LSTNet, N-BEATS, TFT)</li><li>Commercial applications: Facebook Prophet and Amazon DeepAR</li></ol><p>The full working code for each of these algorithms is in the Python notebooks here: <a href="https://github.com/phylypo/TimeSeriesPrediction">https://github.com/phylypo/TimeSeriesPrediction</a>.</p><p>In the notebook, we also cover other algorithms not mentioned here like FFT, HMM, and other State Space approaches.</p><h3>Introduction to Time Series</h3><p>Time series is a sequence of data that has some order usually with a time component in a set interval. A typical example is the stock daily closing price over time or DNA sequences.</p><p>Typical tasks involve times series includes:</p><ul><li><strong>Data Analysis</strong>: also known as exploratory data analysis (EDA) of a time series involves analyzing the data for its structure such as seasonality or nature of its temporal process.</li><li><strong>Prediction/Forecasting</strong>: Prediction of future values of time series involves using past data to predict the future.</li><li><strong>Classification</strong>: You can classify time series into different types such as detection of an ECG heartbeat graph is a normal type or not.</li><li><strong>Anomaly Detection</strong>: Another task is detecting values that are not within the expected range in the time series.</li></ul><p>We will be mainly focusing on a predicting task but partly cover some analysis in order to better understand the time series dataset.</p><h4><strong>Types of time series</strong></h4><p>There are two types of time series:</p><ol><li>univariate: time series with a single observation per time increments.</li><li>multivariate: time series that has more than one observation per time increments. These observations or time-dependent variables can capture the dynamic of multiple time series.</li></ol><p>We will be focusing on univariate in this article for simplicity. There are some example codes that use multivariate.</p><h4><strong>Dataset</strong></h4><p>To model or make prediction, we first need the dataset. These dataset are self explanatory with link to download. There are a few publicly available datasets.</p><h4>Univariate <strong>Dataset:</strong></h4><ul><li>Air passengers: number of air passenger per month over 12 years (1949–1960) <a href="https://assets.digitalocean.com/articles/eng_python/prophet/AirPassengers.csv">https://assets.digitalocean.com/articles/eng_python/prophet/AirPassengers.csv</a></li><li>Sunspot: monthly count of the number of observed sunspots for just over 230 years (1749–1983) <a href="https://storage.googleapis.com/laurencemoroney-blog.appspot.com/Sunspots.csv">https://storage.googleapis.com/laurencemoroney-blog.appspot.com/Sunspots.csv</a></li><li>Shampoo Sales: monthly sales of shampoo over a 3 year period (<a href="https://raw.githubusercontent.com/jbrownlee/Datasets/master/shampoo.csv">https://raw.githubusercontent.com/jbrownlee/Datasets/master/shampoo.csv</a>)</li><li>Milk production: average monthly milk production (in lbs) of cows from Jan/1962 to Dec/1975. (<a href="https://raw.githubusercontent.com/plotly/datasets/master/monthly-milk-production-pounds.csv">https://raw.githubusercontent.com/plotly/datasets/master/monthly-milk-production-pounds.csv</a>)</li></ul><p><strong>Multivariate Dataset:</strong></p><ul><li>Traffic: A collection of 48 months (2015–2016) hourly data from the California Department of Transportation. The data describes the road occupancy rates (between 0 and 1) measured by different sensors on the San Francisco Bay area freeways.</li><li>Solar-Energy: the solar power production records in the year 2006, which is sampled every 10 minutes from 137 PV plants in Alabama State.</li><li>Electricity: The electricity consumption in kWh was recorded every 15 minutes from 2012 to 2014</li><li>Exchange-Rate: the collection of the daily exchange rates of eight foreign countries including Australia, British, Canada from 1990 to 2016.</li></ul><p>All three above datasets can be found here: <a href="https://github.com/laiguokun/multivariate-time-series-data">https://github.com/laiguokun/multivariate-time-series-data</a>.</p><p><strong>Kaggle Tourism:</strong></p><ul><li>Part one requires competitors to predict 518 tourism-related time series. It contains 518 yearly time series. (<a href="https://www.kaggle.com/c/tourism1">https://www.kaggle.com/c/tourism1</a>)</li><li>Part two requires competitors to predict 793 tourism-related time series. It contains 793 different time series. The first 366 columns contain monthly time series. The next 427 time series contain quarterly time series. (<a href="https://www.kaggle.com/c/tourism2">https://www.kaggle.com/c/tourism2</a>)</li></ul><p><strong>Makridakis Competitions:</strong></p><ul><li>M3: A total of 3003 different time series was used.</li><li>M4: 100,000 real-life series <br><a href="https://mofc.unic.ac.cy/the-dataset/">https://mofc.unic.ac.cy/the-dataset/</a>, <a href="https://github.com/Mcompetitions/M4-methods/tree/master/Dataset">https://github.com/Mcompetitions/M4-methods/tree/master/Dataset</a></li></ul><p>We will be using the AirPassenger dataset throughout this article. Here is what the monthly count of air passengers looks like from 1949 to 1960.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZfqKKjMjevy7k2my" /><figcaption>AirPassengers</figcaption></figure><p><strong>Components of Time Series</strong></p><p>The above chart of the AirPassengers data clearly shows a linear trend and some seasonality. These are example of components in time series. Formally, time series consists of:</p><ol><li>Level: local mean of the series</li><li>Trend: the change between successive time points</li><li>Seasonality: the deviation from the local mean due to seasonality</li><li>Noise: residual components or random variation</li></ol><blockquote>𝑦 = 𝑙𝑒𝑣𝑒𝑙 + 𝑡𝑟𝑒𝑛𝑑 + 𝑠𝑒𝑎𝑠𝑜𝑛𝑎𝑙𝑖𝑡𝑦 + 𝑛𝑜𝑖𝑠𝑒<br>where 𝑦 is the observation.</blockquote><p>With the AirPassengers dataset above, it can be decomposed into trend, seasonality, and noise as below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CFE_Hc8Lk5yh4ZYk" /></figure><p><strong>Predictions and Metrics</strong></p><p>The goal of our task is to predict the future values. Then we need to measure how our predictions for different approaches performed in comparison. There are two types of prediction that we need to distinguish before we measure it.</p><ol><li>One-step ahead prediction: predicting the next one step from our last observation</li><li>Multi-horizons forecast: predicting multiple steps ahead</li></ol><p>In the multi-horizon forecast, we can accomplish this through two approaches:</p><ol><li>Iterated approaches: utilize one-step-ahead prediction and recursively feeding predictions to future inputs.</li><li>Direct approach: to explicitly generate predictions for multiple time steps at once.</li></ol><p>Before we can measure how well our algorithms predict the future values, we need to discuss how we split our data into training and test sets before running the experiment.</p><p><strong>Train and Test Split</strong></p><p>In machine learning, we need to test our algorithm on the data that we have not seen. This is done by setting aside a portion of the dataset that will not be used in the training. This set is only used for testing the model. So in our dataset, we want to train on the earlier part of the dataset and leave out the later part of the dataset to evaluate how well the model performs. We don’t want to randomly split the dataset since sequence matters. We can split the data as follow:</p><ul><li>Training set: take the early portion of the data (ie. the first 80%)</li><li>Test set: set aside the latest part of the data (ie. last 20% or the last year of monthly data, or last month of the yearly data)</li></ul><p><strong>Metrics</strong></p><p>To measure how well the algorithms perform, there are several metrics that we can use:</p><ul><li>MSE: Mean Squared Error<br>Pandas Series: <em>np.square(y_hat - y).mean()</em></li><li>RMSE: Root Mean Squared Error<br>Pandas Series: <em>np.sqrt(MSE)</em></li><li>MAE: mean absolute error<br>Pandas Series: <em>abs(y_hat - y).mean()</em></li><li>MAD: mean absolute deviation<br>Pandas Series: <em>abs(y_hat - y.mean()).mean()</em></li><li>MAPE: mean absolute percentage error<br>Pandas Series: <em>(abs(y - y_hat) / y).mean() * 100</em></li><li>sMAPE: Symmetric mean absolute percentage error (scales the error by the average between the forecast and actual)<br>Pandas Series: <em>abs(y - y_hat).sum()/(y + y_hat).sum( ) * 100</em></li><li>MASE: Mean Absolute Scaled Error — scales by the average error of the naive null model</li></ul><blockquote>where<br>y : the ground truth observation value<br>y_hat : predicted value</blockquote><p>We will be using <strong>MAE</strong> as our metric to see how well our algorithms are doing.</p><h3>Naive Approaches</h3><p>We need a baseline approach that we can compare the performance of our algorithms. There are several naïve approaches :</p><ul><li><strong>Null model</strong>: predict the next value as the previous one (persistence model)</li><li><strong>Seasonal Naive</strong>: add seasonality to the prediction by using the previous season value</li><li><strong>Mean</strong>: take an average of all previous values as the forecast value</li><li><strong>Random Walk</strong>: randomly add noise to the previous value as the next prediction</li></ul><p>Here is the illustration of the predictions of the two models (null model and seasonal naive).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/877/0*5zd2ZlQKdYIww0T0" /></figure><p>The <strong>MAE</strong> for the <strong>Null model</strong> for this dataset to predict the last 12-month is 49.95 and for the<strong> Seasonal Naive model</strong> is 45.60. We will use this as our baseline comparison.</p><h3>Smoothing</h3><p>The technique of smoothing is using the moving average or exponential smoothing as a way to filter out some of the noises in the data.</p><h4>Simple Moving Average</h4><p>Each data point is an average over <em>n </em>data points. The larger n is, the smoother the chart becomes. In <em>pandas</em>, you just call:</p><pre>pandas.DataFrame.rolling(n, center=False).mean()</pre><p>The moving average could be in the center and trailing Moving Average by specified the <em>center</em> argument</p><p>Here are examples of moving average with 3-month, 5-month moving average, and 3-month exponential moving average that will be explained below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7jMgWlVEz3_eiHfr" /></figure><h3>Exponential Smoothing</h3><h4><strong>Linear Exponential Smoothing (Holt ES)</strong></h4><p>The Linear Exponential Smoothing (Holt ES) is<strong> </strong>also known as a simple exponential weighted moving average. Whereas the simple moving average weighted the previous points equally, simple exponential MA gives more weight to the more recent values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/596/1*oA4lZO4wywR1RghekXx01A.png" /></figure><p>In <em>pandas</em>, we can use:</p><pre>pandas.DataFrame.ewm(alpha=0.12).mean()</pre><p><strong>Double Exponential Smoothing</strong></p><p>Also known as <strong>Holt-Winters Double ES</strong>, double exponential smoothing takes into account the trend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/584/1*DUKCJwjoqq6-7GPLq4m8gw.png" /></figure><p><strong>Triple Exponential Smoothing (Holts-Winters ES)</strong></p><p>Also known as <strong>Holts-Winters ES</strong>, Triple Exponential Smoothing take into account the seasonality in addition to the trend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/697/1*nIoJL-SNlQIcpZDGPw3KNQ.png" /></figure><p>Using these exponential smoothing’s to predict future value we get the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/933/0*nSdD897xn4rIYd68" /></figure><p>The MAE for these are:</p><ul><li>MAE Simple ES: 50.86</li><li>MAE Double ES: 52.62</li><li>MAE Triple ES: 18.44</li></ul><p>Notice that the linear and double exponential smoothing is doing worst than the Null model while the Holt-Winter is doing very well on this dataset.</p><h3>ARIMA</h3><p>Also known as the classical Box-Jenkins methodology, ARIMA is the statistical approach created specifically for time series.</p><p>ARIMA is part of the state-space model (SSM). SSM also includes the exponential smoothing technique we have seen earlier. It is based on a structural analysis of the problem that can be described by different components like trend, seasonality, cycle. It is suitable for an approach where the structure of the time series is well-understood.</p><p>ARIMA has 3 distinct structures as follow:</p><ul><li><strong>AR</strong> : Auto Regression — uses the dependent relationship between an observation and some number of lagged observations. The lag 𝑛 value is the previous 𝑛 value of the observation.</li><li><strong>I</strong> : Integrated — uses the differencing of raw observations in order to make the time series stationary.</li><li><strong>MA</strong> : Moving Average — uses the dependency between an observation and a residual error from a moving average model applied to lag observations.</li></ul><p>In the library that we will be using, the notation is ARIMA(p,d,q) where:</p><ul><li>p: (AR) The number of lag observations included in the model, also called the lag order.</li><li>d: (I) The number of times that the raw observations are differenced, also called the degree of differencing.</li><li>q: (MA) The size of the moving average window, also called the order of moving average.</li></ul><p>Since we will be applying the seasonality, the API we will be using is SARIMAX. The S means Seasonality where X means eXogenous which allows for the inclusion of other data besides the univariate values.</p><h4>ARIMA Parameters Search</h4><p>We can import the following library: <em>sm.tsa.statespace.SARIMAX. </em>Examples of parameter combinations for Seasonal ARIMA will have p,d,q for ARIMA, then for S in seasonality, there are p,d,q, and seasonal value. For example:</p><p><em>SARIMAX: (0, 1, 0) x (0, 1, 1, 12) where 12 is the seaonsal value.</em></p><p>You may analyze for the <em>p, d, q</em> based on the dataset or use grid search with <em>pmdarima</em> library which does the grid search for us more efficiently.</p><p>You will need to install the package first then import and run the method as the following:</p><pre># required restart of the runtime<br>#!pip install pmdarima</pre><pre># Import the library, require install and restart<br>from pmdarima import auto_arima</pre><pre>stepwise_fit = auto_arima(data[‘AirPassengers’], <br>  start_p = 1, start_q = 1,<br>  max_p = 3, max_q = 3, m = 12,<br>  start_P = 0, seasonal = True, …)</pre><p>You can also do a manual grid search yourself. The code is included in the notebook by finding the smallest AIC value.</p><p>We use the following hyperparameters as input to the ARIMA algorithm:</p><p><em>ARIMA(1, 1, 1)x(1, 1, 1, 12)12 — AIC:803.3627295936407</em></p><p>We got the following prediction with the MAE of 15.22.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/845/0*c_DxT7xQfBr_z5pn" /></figure><p>The gray area indicates the confidence level. As we predict further time steps, the range gets wider. Since this is one-step ahead prediction, at each time step we use the prediction value as the input for the next time step prediction.</p><h3>ML: Classical Supervised Learning Approaches</h3><p>We’ll explore two basic supervised learning techniques:</p><ol><li>Linear Regression</li><li>Decision Tree with XGBoost (Gradient Boosted Tree)</li></ol><h3>Generating Features</h3><p>In earlier statistical approaches like ARIMA, the system was built for time series data. We can just feed the data directly. But for these ML approaches, we need to generate features that the algorithms can use to account for time ordering. Some of the features include:</p><ul><li>lags : value at time step t-N</li><li>amplitude: amplitude from the mean value</li><li>max/min value: max or min value at that window</li><li>value &gt; 1 std : count of value great than 1 standard deviation</li></ul><p>For our case, using lag values for our features is sufficient. To generate lag features we just use the data and shift by one value per lag. As an example, we want to create 2 lags feature from this data [2, 4, 6, 8, 7, 9], we would have:</p><pre>lag2  lag1  y<br>— — — — — — -<br>nan   nan   2<br>nan   2     4<br>2     4     6<br>4     6     8<br>6     8     7<br>8     7     9</pre><h3>Linear Regression</h3><p>We will start with linear regression. We will fit the data with linear regression with 12 lags values as our features since we knew that our seasonality is 12 months. So the lags f01 to f12 are the features and y is the actual value:</p><pre> f12  f11  f10  f09  f08  f07  f06  f05  f04  f03  f02  f01    y<br>------------------------------------------------------------------<br>[nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 112],<br>[nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 112, 118],<br>[nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 112, 118, 132],<br>[nan, nan, nan, nan, nan, nan, nan, nan, nan, 112, 118, 132, 129],<br>[nan, nan, nan, nan, nan, nan, nan, nan, 112, 118, 132, 129, 121],<br>[nan, nan, nan, nan, nan, nan, nan, 112, 118, 132, 129, 121, 135],<br>[nan, nan, nan, nan, nan, nan, 112, 118, 132, 129, 121, 135, 148],<br>[nan, nan, nan, nan, nan, 112, 118, 132, 129, 121, 135, 148, 148],<br>[nan, nan, nan, nan, 112, 118, 132, 129, 121, 135, 148, 148, 136],<br>[nan, nan, nan, 112, 118, 132, 129, 121, 135, 148, 148, 136, 119],<br>[nan, nan, 112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104],<br>[nan, 112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118],<br><strong><em>[112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115],<br>[118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126],<br>[132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141],</em></strong></pre><pre>…</pre><p>Our first input will start with the 13th row that has the complete 12 feature values without <em>nan</em>.</p><pre>from sklearn import linear_model</pre><pre>model = linear_model.LinearRegression()<br>model.fit(trainX, trainy)</pre><pre># make a one-step prediction<br>yhat = model.predict(asarray([testX]))</pre><p>We see the result with MAE of 17.69.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/0*x3h_RrNBmRwrNIUW" /></figure><h3>XGBoost</h3><p>With the same technique, we can replace the algorithm with XGBoost.</p><pre>from xgboost import XGBRegressor<br>model = XGBRegressor(objective=’reg:squarederror’, n_estimators=500)<br>model.fit(trainX, trainy)</pre><pre># make a one-step prediction<br>yhat = model.predict(asarray([testX]))</pre><p>We get an MAE of 25.58.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/0*19lMPsbSwfhb1nSI" /></figure><p>This shows that the linear regression is pretty good with this simple dataset. Although XGBoost is known to do very well in many of Kaggle competition datasets.</p><h3>Deep Learning with RNN — LSTM</h3><p>We now look at deep learning approaches with RNN. Instead of using the plain RNN, we will use Long Short-Term Memory (LSTM). LSTM improved over the plain RNN by helping to mitigate the vanishing and exploding gradient issue.</p><p>In the preprocessing step, we also added MinMaxScaler to ensure our data is in the same range (0–1). This seems to improve our prediction.</p><pre>from sklearn.preprocessing import MinMaxScaler<br>scaler = MinMaxScaler()<br>scaler.fit(x_train)</pre><pre>x_train = scaler.transform(x_train)<br>x_valid = scaler.transform(x_valid)</pre><p>Model:</p><pre>tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(260,<br>  activation=’relu’, return_sequences=True)),<br>  tf.keras.layers.Dropout(0.15),<br>  tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(248)),<br>  tf.keras.layers.Dropout(0.05),<br>  tf.keras.layers.Dense(1), ...)</pre><p>With Adam optimizer:</p><pre>optimizer = tf.keras.optimizers.Adam()<br>model.compile(loss=”mse”, optimizer=optimizer, metrics=[“mae”])<br>model.fit(dataset,epochs=100,verbose=1)</pre><pre>Epoch 100/100</pre><pre>20/20 [==============================] — 3s 134ms/step — loss: 0.0039 — mae: 0.0507</pre><p>The latest result in the notebook, our MAE is 47.37.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*p1IVgew93Y27VYjx" /></figure><p>After tweaking some parameters and architecture, we were able to get the MAE on the test set to be 33.39.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*JRrPez1tVR8qIIgk" /></figure><p>References:</p><ul><li><a href="https://github.com/gianfelton/12-Month-Forecast-With-LSTM/blob/master/12-Month%20Forecast%20With%20LSTM.ipynb">https://github.com/gianfelton/12-Month-Forecast-With-LSTM/blob/master/12-Month%20Forecast%20With%20LSTM.ipynb</a></li><li><a href="https://colab.research.google.com/github/lmoroney/dlaicourse/blob/master/TensorFlow%20In%20Practice/Course%204%20-%20S%2BP/S%2BP%20Week%203%20Lesson%204%20-%20LSTM.ipynb">https://colab.research.google.com/github/lmoroney/dlaicourse/blob/master/TensorFlow%20In%20Practice/Course%204%20-%20S%2BP/S%2BP%20Week%203%20Lesson%204%20-%20LSTM.ipynb</a></li></ul><h3>CNN and LSTM</h3><p>We can add a CNN layer in front of LSTM to help encode the input. This showed an improvement of LSTM alone.[]</p><p>For optimizer, we use momentum.</p><pre>tf.keras.layers.Conv1D(filters=60, kernel_size=5,<br>  strides=1, padding=”causal”,<br>  activation=”relu”,<br>  input_shape=[None, 1]),<br>  tf.keras.layers.LSTM(200, return_sequences=True), #60<br>  tf.keras.layers.LSTM(200, return_sequences=True),<br>  tf.keras.layers.Dropout(0.15),<br>  tf.keras.layers.Dense(200, activation=”relu”),<br>  tf.keras.layers.Dense(10, activation=”relu”),<br>  tf.keras.layers.Dense(1),</pre><p>Output:</p><pre>Epoch 150/150</pre><pre>5/5 [==============================] — 0s 53ms/step — loss: 23.7124 — mae: 24.2093</pre><p>The MAE for the test set is 40.25. The error is larger than LSTM above. We used a scaler to improve the performance in the LSTM approach.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*rXu18CMjttLVHcxh" /></figure><p>Reference: <a href="https://colab.research.google.com/github/lmoroney/dlaicourse/blob/master/TensorFlow%20In%20Practice/Course%204%20-%20S%2BP/S%2BP%20Week%204%20Lesson%205.ipynb#scrollTo=tP7oqUdkk0gY">https://colab.research.google.com/github/lmoroney/dlaicourse/blob/master/TensorFlow%20In%20Practice/Course%204%20-%20S%2BP/S%2BP%20Week%204%20Lesson%205.ipynb</a></p><h3>TCN</h3><p>Temporal Convolutional Networks (TCN) is a variation of Convolutional Neural Networks for sequence modeling tasks, by combining aspects of RNN and CNN architectures. This model performs a multi-horizon prediction.</p><p>TCN is based on two principles:</p><ol><li>the network produces an output of the same length as the input</li><li>there can be no leakage from the future into the past.</li></ol><p>To accomplish the first point, the TCN uses a 1D fully-convolutional network (FCN) architecture.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/990/1*DqbhDovSL9uEgeu7-BpNBg.png" /><figcaption>“An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling”, Shaojie Bai, J. Zico Kolter, Vladlen Koltun, 2018.</figcaption></figure><p>The paper showed improved performance over LSTM, GRU, and RNN in many of the datasets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/732/1*5pZTVbitor6p0aEYxHPwOA.png" /></figure><p>TCN implementations for different ML libraries can be found here:</p><ul><li>Pytorch: <a href="http://github.com/locuslab/TCN">http://github.com/locuslab/TCN</a></li><li>Keras: <a href="https://github.com/philipperemy/keras-tcn">https://github.com/philipperemy/keras-tcn</a></li><li>Tensorflow: <a href="https://github.com/Baichenjia/Tensorflow-TCN">https://github.com/Baichenjia/Tensorflow-TCN</a></li></ul><p>Our code uses the keras-tcn library as follow:</p><pre># installing tcn<br>#!pip install keras-tcn</pre><pre>from tcn import TCN, tcn_full_summary</pre><pre>i = Input(shape=(lookback_window, 1))<br>m = TCN()(i)<br>m = Dense(1, activation=&#39;linear&#39;)(m)</pre><pre>model = Model(inputs=[i], outputs=[m])<br>model.summary()<br>model.compile(&#39;adam&#39;, &#39;mae&#39;)</pre><pre>model.fit(x_train, y_train, epochs=150, verbose=0)</pre><p>Output:</p><pre>Model: &quot;functional_25&quot;<br>_________________________________________________________________<br>Layer (type)                 Output Shape              Param #<br>=================================================================<br>input_13 (InputLayer)        [(None, 12, 1)]           0<br>_________________________________________________________________<br>tcn_12 (TCN)                 (None, 64)                91136<br>_________________________________________________________________<br>dense_12 (Dense)             (None, 1)                 65<br>=================================================================</pre><pre>Total params: 91,201<br>Trainable params: 91,201<br>Non-trainable params: 0</pre><p>We got the MAE of 15.01 for the AirPassenger dataset.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/0*e7xRBD2ybJydJmcQ" /></figure><p><em>References:</em></p><ul><li>“An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling”, Shaojie Bai, J. Zico Kolter, Vladlen Koltun (<a href="https://arxiv.org/abs/1803.01271">https://arxiv.org/abs/1803.01271</a>)</li><li><a href="https://towardsdatascience.com/farewell-rnns-welcome-tcns-dd76674707c8">https://towardsdatascience.com/farewell-rnns-welcome-tcns-dd76674707c8</a></li><li><a href="https://dida.do/blog/temporal-convolutional-networks-for-sequence-modeling">https://dida.do/blog/temporal-convolutional-networks-for-sequence-modeling</a></li></ul><h3>Long- and Short-Term Temporal Network (LSTNet)</h3><p>Multivariate time series forecasting often faces a major research challenge, that is, how to capture and leverage the dynamics dependencies among multiple variables.</p><p>The shortcoming of classical ARIMA:</p><ul><li>ARIMA models are adaptive to various exponential smoothing techniques and flexible enough to subsume other types of time series models. However, ARIMA models, are rarely used in high dimensional multivariate time series forecasting.</li><li>vector autoregression (VAR) is arguably the most widely used models in multivariate time series due to its simplicity. The model capacity of VAR grows linearly over the temporal window size and quadratically over the number of variables.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*i3AlLdyUTq-SpaZl" /><figcaption>“Modeling Long- and Short-Term Temporal Patterns with Deep Neural Networks”, Lai et al., SIGIR 2018.</figcaption></figure><p>LSTNet Components:</p><ol><li>CNN with k-th filter with RELU</li><li>RNN (GRU) — with RELU</li><li>RNN Skip Connection</li><li>Temporal Attention Layer</li><li>Autoregression with highway</li></ol><p>Model consisted of: (CNN, and RNN(GRU) and dropout layer)</p><pre>class LSTNet(nn.Module):</pre><pre>  def __init__(self, args, data):<br>    super(LSTNet, self).__init__()<br>    self.P = args.window;<br>    self.m = data.m<br>    self.hidR = args.hidRNN;<br>    self.hidC = args.hidCNN;<br>    self.hidS = args.hidSkip;<br>    self.Ck = args.CNN_kernel;<br>    …<br>    self.conv1 = nn.Conv2d(1, self.hidC, kernel_size = (self.Ck, self.m));<br>    self.GRU1 = nn.GRU(self.hidC, self.hidR);<br>    self.dropout = nn.Dropout(p = args.dropout);</pre><p>The MAE is 13.96 for the AirPassengers dataset.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/0*VPjY4J8mXVr6OobX" /></figure><p><em>References:</em></p><ul><li><a href="https://modelzoo.co/model/lstnet">https://modelzoo.co/model/lstnet</a></li><li><a href="https://opringle.github.io/2018/01/05/deep_learning_multivariate_ts.html">https://opringle.github.io/2018/01/05/deep_learning_multivariate_ts.html</a></li><li>“Modeling Long- and Short-Term Temporal Patterns with Deep Neural Networks”, Lai et al., SIGIR 2018 (<a href="https://arxiv.org/pdf/1703.07015.pdf">https://arxiv.org/pdf/1703.07015.pdf</a> ) Code: <a href="https://github.com/laiguokun/LSTNet">https://github.com/laiguokun/LSTNet</a></li></ul><h3>N-BEATS</h3><p>Neural Basis Expansion Analysis for Interpretable Time Series (N-BEATS) is built for:</p><ul><li>multi-horizons</li><li>multiple series</li><li>interpretabilities: seasonality and trend.</li></ul><p>“Pure DL using no time-series specific components outperforms well-established statistical approaches on M3, M4 and TOURISM datasets (on M4, by 11% over statistical benchmark, by 7% over the best statistical entry, and by 3% over the M4 competition winner),” N-BEATS.</p><p>Architectural design:</p><ul><li>simple and generic, yet expressive (deep).</li><li>not rely on time series specific feature engineering or input scaling for pure DL architecture in time series forecasting.</li><li>explore interpretability, extendable towards making its outputs human interpretable.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/855/1*yUexOUjM1f6ZhMw-Obu6jg.png" /><figcaption>N-BEATS: Neural Basis Expansion Analysis for Interpretable Time Series Forecasting, Oreshkin, et al.,2020.</figcaption></figure><p>Model types in the notations:</p><ul><li>I : interpretability</li><li>G : general</li><li>G+I : ensembles with I and G</li></ul><p>Interpretabilities is provided with graph of trend and seasonality like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/704/1*xPYuz7oPDIi_eUE2DqW65Q.png" /><figcaption>N-BEATS: Neural Basis Expansion Analysis for Interpretable Time Series Forecasting, Oreshkin, et al.,2020.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/741/1*6LdCMZt7mBuNwL6THUq7cw.png" /></figure><pre># install the libraries<br>#!pip install pytorch_lightning<br>#!pip install pytorch_forecasting</pre><pre>import pytorch_lightning as pl<br>from pytorch_lightning.callbacks import EarlyStopping</pre><pre>from pytorch_forecasting import TimeSeriesDataSet, NBeats, Baseline<br>from pytorch_forecasting.data import NaNLabelEncoder<br>from pytorch_forecasting.data.examples import generate_ar_data<br>from pytorch_forecasting.metrics import SMAPE</pre><pre>trainer = pl.Trainer(<br>  max_epochs=100,<br>  gpus=0,<br>  weights_summary=&quot;top&quot;,<br>  gradient_clip_val=0.1,<br>  callbacks=[early_stop_callback],<br>  limit_train_batches=30,<br>)</pre><pre>net = NBeats.from_dataset(training, learning_rate=4e-3,<br>  log_interval=10, log_val_interval=1, weight_decay=1e-2, <br>  widths=[32, 512], backcast_loss_ratio=1.0)</pre><pre>trainer.fit(net, train_dataloader=train_dataloader,  <br>  val_dataloaders=val_dataloader,<br>)</pre><p>Performance on AirPassengers dataset,</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/0*b_6m-9Rlm9Ro4bkv" /></figure><p>We have to finetune a lot of hyper parameters. We added monthly hint and show a little improvement.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/0*upSpjytwSXIO8kE5" /></figure><p>After some finetune we get the MAE of 26.42.</p><p><em>References:</em></p><ul><li>Paper: “N-BEATS: Neural Basis Expansion Analysis for Interpretable Time Series Forecasting”, Boris N. Oreshkin, Dmitri Carpov, Nicolas Chapados, Yoshua Bengio, May 2019, ICLR 2020 (<a href="https://arxiv.org/abs/1905.10437">https://arxiv.org/abs/1905.10437</a>)</li><li><a href="https://medium.com/@kshavgupta47/n-beats-neural-basis-expansion-analysis-for-interpretable-time-series-forecasting-91e94c830393">https://medium.com/@kshavgupta47/n-beats-neural-basis-expansion-analysis-for-interpretable-time-series-forecasting-91e94c830393</a></li><li><a href="https://github.com/philipperemy/n-beats">https://github.com/philipperemy/n-beats</a></li></ul><h3>Temporal Fusion Transformers (TFT)</h3><p>“By interpreting attention patterns, TFT can provide insightful explanations about temporal dynamics, and do so while maintaining state-of-the-art performance on a variety of datasets,” Lim et al.,2019.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/713/1*_AesML_OiEziZnGcdqqy1Q.png" /><figcaption>Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting, Lim et al., 2019.</figcaption></figure><p>For interpretability, TFT uses the attention mechanism as follow:</p><ul><li>Attention mechanisms are used to identify salient portions of input for each instance using the magnitude of attention weights.</li><li>TFT uses separate encoder-decoder attention for static features at each time step on top of the self-attention to determine the contribution time-varying inputs.</li></ul><p>Here are the performance cited in the paper.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/675/1*uN3PafwKgFUdxC33qgXUgQ.png" /></figure><p>The paper compares to other models (ARIMA, ETS, TRMF, DeepAR, DSSM, ConvTrans, Seq2Seq, and MQRNN). Here is some information on the different models.</p><ul><li>ETS (Error, Trend, Seasonal) method is an approach method for forecasting time series univariate. (<a href="https://otexts.com/fpp2/arima-ets.html">https://otexts.com/fpp2/arima-ets.html</a>)</li><li>DeepAR uses stacked LSTM layers to generate parameters of one-step-ahead Gaussian predictive distributions. This will be described later.</li><li>Deep State-Space Models (DSSM) utilize LSTMs to generate parameters of a predefined linear state-space model with predictive distributions produced via Kalman filtering — with extensions for multivariate time series data.</li><li>ConvTrans: the Transformer-based architecture with the use of convolutional layers for local processing and a sparse attention mechanism to increase the size of the receptive field during forecasting. (<a href="https://arxiv.org/abs/1907.00235">https://arxiv.org/abs/1907.00235</a>)</li><li>The Multi-horizon Quantile Recurrent Forecaster (MQRNN) uses LSTM as convolutional encoders to generate context vectors that are fed into multi-layer perceptrons (MLPs) for each horizon.</li></ul><p>Here is the main part of the code. See the notebook for a complete working code.</p><pre>!pip install pytorch_lightning<br>!pip install pytorch_forecasting</pre><pre>import pytorch_lightning as pl<br>from pytorch_forecasting import TimeSeriesDataSet, TemporalFusionTransformer, Baseline<br>from pytorch_forecasting.data import GroupNormalizer<br>from pytorch_forecasting.metrics import PoissonLoss, QuantileLoss, SMAPE<br>from pytorch_forecasting.models.temporal_fusion_transformer.tuning import optimize_hyperparameters</pre><pre>…</pre><pre>trainer = pl.Trainer( gpus=0, gradient_clip_val=0.1)</pre><pre>tft = TemporalFusionTransformer.from_dataset(<br>  training,<br>  learning_rate=0.03,<br>  hidden_size=16,  # most important hyperparameter<br>  attention_head_size=1,<br>  dropout=0.1,  # between 0.1 and 0.3 are good value<br>  hidden_continuous_size=8,  # set to &lt;= hidden_size<br>  output_size=7,  # 7 quantiles by default<br>  loss=QuantileLoss(),<br>  # reduce learning rate if no improvement in validation loss<br>  reduce_on_plateau_patience=4,<br>)</pre><p>I tried to use AirPassengers dataset but it didn’t turn out well. There are several parameters that might have not tuned properly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/430/0*anmU_p3aBDSFKAm2" /></figure><p><em>References:</em></p><ul><li>“Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting” Bryan Lim, Sercan O. Arık, Nicolas Loeffb, Tomas Pfister, Dec 2019 (<a href="https://arxiv.org/abs/1912.09363.pdf">Paper</a>)<a href="https://arxiv.org/abs/1912.09363.pdf">https://arxiv.org/abs/1912.09363.pdf</a></li><li><a href="https://github.com/google-research/google-research/tree/master/tft">https://github.com/google-research/google-research/tree/master/tft</a></li><li><a href="https://github.com/louisyuzhe/deeplearning_forecast">https://github.com/louisyuzhe/deeplearning_forecast</a></li><li><a href="https://pytorch-forecasting.readthedocs.io/en/latest/tutorials/stallion.html">https://pytorch-forecasting.readthedocs.io/en/latest/tutorials/stallion.html</a></li></ul><h3>Commercial Applications</h3><h3>Facebook Prophet</h3><p>In 2017, Facebook open sourced a project called Prophet. “Prophet is a modular regression model with interpretable parameters that can be intuitively adjusted by analysts”. It decomposed the series into three main model components:</p><ol><li>trend</li><li>seasonality</li><li>holidays</li></ol><p>Use only time as a regressor but possibly several linear and nonlinear functions of time as components.</p><p>Has a number of advantages:</p><ul><li>Flexibility: We can easily accommodate seasonality with multiple periods</li><li>Fitting is very fast</li><li>Has easily interpretable parameters</li></ul><pre>from fbprophet import Prophet</pre><pre>my_model = Prophet(interval_width=0.98, daily_seasonality=False, weekly_seasonality=False, yearly_seasonality=True,)</pre><pre>my_model.fit(train_data)</pre><pre>future_dates = my_model.make_future_dataframe(periods=12, freq=’MS’)</pre><pre>forecast = my_model.predict(future_dates)</pre><p>With the AirPassenger dataset, we get an MAE of 33.92.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/455/0*yx4gDfBejwiFmHYc" /></figure><p>You can see the explainability aspect with these:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/0*7AyNdoSDw9T0GTHn" /></figure><p><em>References:</em></p><ul><li>Paper: <a href="https://peerj.com/preprints/3190/">https://peerj.com/preprints/3190/</a></li><li>Code: <a href="https://github.com/facebookincubator/prophet">https://github.com/facebookincubator/prophet</a></li><li>Tutorial: <a href="https://www.digitalocean.com/community/tutorials/a-guide-to-time-series-forecasting-with-prophet-in-python-3">https://www.digitalocean.com/community/tutorials/a-guide-to-time-series-forecasting-with-prophet-in-python-3</a></li></ul><h3>Amazon DeepAR</h3><p>“DeepAR, a forecasting method based on autoregressive recurrent networks, which learns such a global model from historical data of all the time series in the data set,” Salinas et al., 2019. It uses a similar LSTM-based recurrent neural network architecture. This only runs on Amazon Sagemaker but there is an implementation in PyTorch in the link below. We did not get to try out the PyTorch code.</p><p>Classical Techniques Problem:</p><ul><li>there is a need for forecasting thousands or millions of related time series</li><li>Examples: forecasting the load for servers in a data center, or forecasting the demand for all products of a large retailer</li><li>related time series can be leveraged for making a forecast for an individual time series.</li><li>allows fitting more complex (and hence potentially more accurate) models without overfitting</li><li>eliminate manual feature engineering and model selection steps</li></ul><p>Features:</p><ul><li>the model learns seasonal behavior and dependencies on given covariates across time series</li><li>by learning from similar items, it can provide forecasts for items with little or no history at all</li></ul><p><em>References:</em></p><ul><li>“DeepAR: Probabilistic Forecasting with Autoregressive Recurrent Networks”, Salinas et al., 2019. (<a href="https://arxiv.org/abs/1704.04110">https://arxiv.org/abs/1704.04110</a>)</li><li>Implementation in PyTorch: <a href="https://github.com/zhykoties/TimeSeries">https://github.com/zhykoties/TimeSeries</a></li><li><a href="https://towardsdatascience.com/prophet-vs-deepar-forecasting-food-demand-2fdebfb8d282">https://towardsdatascience.com/prophet-vs-deepar-forecasting-food-demand-2fdebfb8d282</a></li></ul><h3>Conclusion</h3><p>Time series fits well with a structural approach such as ARIMA which shows the interpretability with trend and seasonality. Holt-Winters triple exponential smoothing can account for trend and seasonality and give a similar result for the simple dataset we used.</p><p>Then in the machine learning approach, it required the input to be formatted with features. The typical linear regression is not that bad for our dataset. We also tried XGBoost which is frequently used by the Kaggle competition winners.</p><p>In deep learning, the sequence to sequence approaches like RNN and LSTM does show some promise. New architectures started to emerge just beyond CNN and RNN. TCN and LSTNet showed great performance surpassing ARIMA.</p><p>Then TFT and N-BEATS are the latest approaches that are the current state of the arts. While TFT outperformed previous approaches, N-BEATS outperformed previous winner approaches in the M4 competition.</p><p>Please see the link to Colab notebooks in Github here:<br><a href="https://colab.research.google.com/github/phylypo/TimeSeriesPrediction">https://colab.research.google.com/github/phylypo/TimeSeriesPrediction</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c51a5dd4656a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Visualizing Covid-19 Data in Cambodia using Google Map API with React JS]]></title>
            <link>https://medium.com/@phylypo/visualizing-covid-19-data-in-cambodia-using-google-map-api-with-react-js-163ec5a87518?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/163ec5a87518</guid>
            <category><![CDATA[cambodia]]></category>
            <category><![CDATA[covid19]]></category>
            <category><![CDATA[google-map-api]]></category>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[visualizing]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Thu, 01 Oct 2020 05:27:22 GMT</pubDate>
            <atom:updated>2020-10-01T05:27:22.061Z</atom:updated>
            <content:encoded><![CDATA[<p>Cambodia is impacted by Covid-19 just like many countries. Although the number of active cases on September 12, 2020 was down to zero, in an earlier month, the number of positive cases was increasing at a high rate. The goal is to visualize these increases by region in Cambodia with time series.</p><p>We will be using Google map API to display the map. The end result would look something like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/591/0*JEC7dBFymSZIfkVA" /></figure><p>I am going to detail each step that I took to set up and implement this. You can see the full code in an online IDE <em>repl.it</em> at the end.</p><ol><li>Covid-19 data collection</li><li>Map data collection</li><li>Google map API key setup</li><li>Development tool</li><li>Code structure with Google map API</li><li>Implementing in React JS</li></ol><h3>1. Covid-19 data collection</h3><p>First, we need the time-series data of Covid-19 for each province in Cambodia. The best place to start is John Hopkin dataset (<a href="https://github.com/CSSEGISandData/COVID-19">https://github.com/CSSEGISandData/COVID-19</a>). This dataset contains daily updates of Covid-19 for the whole world by date. Unfortunately, it does not contain a detailed breakdown by provinces in Cambodia.</p><p>The next source that I look at is the Cambodia Ministry of Health (<a href="https://covid19-map.cdcmoh.gov.kh/">https://covid19-map.cdcmoh.gov.kh/</a>). Although the page has a breakdown by region, it does not have the time-series data.</p><p>The last source I found is Wikipedia (<a href="https://en.wikipedia.org/wiki/COVID-19_pandemic_in_Cambodia">https://en.wikipedia.org/wiki/COVID-19_pandemic_in_Cambodia</a>) which breaks down by region and detail for each case in a table. The data is not easily formatted for use but this is what we need.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/787/0*3JK-7Qky_C8UDDN8" /><figcaption>(<a href="https://en.wikipedia.org/wiki/COVID-19_pandemic_in_Cambodia">https://en.wikipedia.org/wiki/COVID-19_pandemic_in_Cambodia</a>)</figcaption></figure><p>Now we can enter this into our dataset. I manually enter it in Excel first then export it to a database. For our final dataset, we need something like this in Javascript with positive case count day by day that breakdown by provinces.</p><pre>var dataHeader = [&#39;Date&#39;, &#39;Banteay Meanchey&#39;, &#39;Battambang&#39;, &#39;Kampong Cham&#39;, &#39;Kampong Chhnang&#39;, &#39;Kampot&#39;, &#39;Kandal&#39;, &#39;Kep&#39;, &#39;Koh Kong&#39;, &#39;Phnom Penh&#39;, &#39;Preah Vihear&#39;, &#39;Siem Reap&#39;, &#39;Preah Sihanouk&#39;, &#39;Tboung Khmum&#39;];</pre><pre>var data = [<br>  [&#39;Jan-26&#39;, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],<br>  [&#39;Jan-27&#39;, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],<br>  [&#39;Mar-13&#39;, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0],<br>  [&#39;Mar-15&#39;, 0, 0, 3, 0, 0, 0, 0, 0, 5, 2, 1, 1, 0],<br>  [&#39;Mar-17&#39;, 2, 4, 3, 3, 0, 0, 4, 1, 9, 2, 2, 1, 2],<br>  [&#39;Mar-19&#39;, 2, 6, 9, 3, 2, 1, 4, 1, 10, 2, 2, 1, 4],<br>  [&#39;Mar-20&#39;, 2, 8, 10, 3, 2, 1, 4, 1, 11, 2, 2, 1, 4],<br>  …<br>]</pre><p>Now that we have Covid-19 data, we will look at the map data next.</p><h3>2. Map data collection: Provinces in Cambodia</h3><p>Although Google map API provides the tool to display maps, it does not provide coordinate data to draw. So we need coordinates to tell the API to show a specific location and to draw borders by province. Openstreetmap (<a href="https://www.openstreetmap.org/#map=5/41.035/-96.064">https://www.openstreetmap.org/</a>) provides the region data for free.</p><p>To search for a province, just provide the name and specify the output format like ‘json’ like the following:</p><blockquote><a href="https://nominatim.openstreetmap.org/search.php?q=%E1%9E%81%E1%9F%81%E1%9E%8F%E1%9F%92%E1%9E%8F%E1%9E%98%E1%9E%8E%E1%9F%92%E1%9E%8C%E1%9E%9B%E1%9E%82%E1%9E%B7%E1%9E%9A%E1%9E%B8&amp;polygon_geojson=1&amp;format=json">https://nominatim.openstreetmap.org/search.php?q=ខេត្តមណ្ឌលគិរី&amp;polygon_geojson=1&amp;format=json</a></blockquote><p>You will the output like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1001/0*CzwUQkyKoASM6lci" /></figure><p>This has the “lat” and “lon” which is the coordinate for the center of the region that we can use. The main data we need is the “geojson” of “Polygon” which has the list of coordinates. This is what we need to draw the region for each province.</p><p>I save each of the provinces into a data file that can be loaded by the script. We don’t want to hit the website for each request. It is also faster to read from the local file system too.</p><p>So I would have a js file that would look like this for all the regions I needed.</p><pre>var coordMondulkiri = [[106.3385777, 13.1342029],…]<br>var coordBonteayMeanchey = [[102.3338282, 13.537473],…]</pre><p>This is a pretty big data file. Some provinces have over 5K of coordinates. This may affect our development tool as we will look in the later section.</p><h3>3. Google Map API Key setup</h3><p>Before we can start coding, we need to create a Google map API key. You can follow the instruction here: <a href="https://developers.google.com/maps/documentation/javascript/get-api-key">https://developers.google.com/maps/documentation/javascript/get-api-key</a></p><p>After you create the key, you need to enable your billing. Or else you get this error below:</p><blockquote><em>“Google Maps JavaScript API error: ApiNotActivatedMapError</em></blockquote><blockquote><em>https://developers.google.com/maps/documentation/javascript/error-messages#api-not-activated-map-error&quot;</em></blockquote><p>The Maps JavaScript API is not activated on your API project yet after creation. You need to enable the billing for your account in the Google Cloud Platform Console. Google allows you to use $200/month of usage before charging you. See pricing for detail (<a href="https://cloud.google.com/maps-platform/pricing">https://cloud.google.com/maps-platform/pricing</a>).</p><p><strong>Security</strong></p><p>The key can be seen by anyone who inspects your code. So you need to restrict the use of the key just on your site. To set the restriction, go to Google Cloud Platform, then Credentials, select your API project, and then under Application restrictions, enter url with wildcard if needed similar to below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/841/0*whrZ74eYpViL42wL" /></figure><p>If you test your map and see a similar screen like below, that means some setting is not correct. In Chrome, go to the Developer tool and see the detail of the error. If this is related to the URL restriction, the error will mention the url that you can add. Don’t forget to click on “Save” on the bottom of the screen in your Google Cloud Platform screen.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/817/0*6GRp74gf-NqMRJDd" /></figure><h3>4. Development Tool</h3><p>I want to quickly try out the Google Map API before I design for React JS used on our website.</p><p>I started the development in codepen.io just to get the map up. Then as I added the coordinate data to test the drawing the border, I started seeing issues with big files and unresponsiveness for long lines. So I started looking into other online JS editing tools. Here is a summary of what I found.</p><ol><li><a href="https://codepen.io/">https://codepen.io/</a>: can’t save after 1mb, more responsive than some</li><li>JSFiddle: froze after long text — ok for big file than 1MB</li><li>Jsbin: seem responsive <a href="https://jsbin.com/?html,js,output">https://jsbin.com/?html,js,output</a><br>Can’t save too large file — smaller than codepen</li><li><a href="https://codesandbox.io/">https://codesandbox.io/</a> — online IDE, has nodejs and hosting</li><li><a href="https://repl.it/@phylypo/">https://repl.it/@phylypo/</a> — node support, provide hosting</li></ol><p>I chose repl.it as the online IDE development tool. The basic code structure is as follow:</p><p><strong>HTML: index.htm</strong></p><pre>&lt;html&gt;<br>&lt;head&gt;<br>  &lt;link href=”style.css” rel=”stylesheet” type=”text/css” /&gt;<br>  &lt;script<br>src=”<a href="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&amp;callback=initMap&amp;libraries=&amp;v=weekly">https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&amp;callback=initMap&amp;libraries=&amp;v=weekly</a>&quot; defer&gt; <br>  &lt;/script&gt;<br>  &lt;script src=”my-map.js”&gt;&lt;/script&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>  &lt;div id=”map”&gt;&lt;/div&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;</pre><p>Change “YOUR_API_KEY” to the value of your Google Map API key. The callback=initMap is the method that will be called when the API is ready. The div id=”map” is where the map goes. You want to style the map using the css similar to below.</p><p><strong>CSS: style.css</strong></p><pre>#map {<br>  height: 90%;<br>  position: relative;<br>  z-index: 1;<br>}</pre><p><strong>JS: my-map.js</strong></p><pre>var map;</pre><pre>function initMap() {<br>  map = new google.maps.Map(document.getElementById(“map”), {<br>    zoom: 8,<br>    center: { lat: 12.467471, lng: 105.12 }<br>  });<br>}</pre><p>In your Javascript, you can call Google map as shown. Here set the zoom level of the map and center the map to a latitude and longitude.</p><h3>5. Code structure with native API</h3><p>I won’t go over the full code since you can see yourself in the link below but I want to highlight a few features.</p><p>For the GUI, I added a button for the start/stop the time series. There is a date and total positive cases up to that date. In addition, I added the input of type range so the user can slide to a specific date at their own speed.</p><p>The interface allows the user to click on the boundary map to see an information windows with display the number of positive cases for that province.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/591/0*BT2MHkWumIueXi4G" /></figure><p><strong>Create UI Elements</strong></p><p>We can create a DIV and add to map.controls as below.</p><pre>startStopDiv = document.createElement(“div”);<br>startStopDiv.index = 1;<br>displayStartStop(startStopDiv, “Start”)<br>map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(<br>  startStopDiv<br>);</pre><p>The displayStartStop function sets the style for the DIV and adds an event listener.</p><pre>function displayStartStop(ccdiv, str){<br>  ccdiv.style.backgroundColor = “#FFDC00”;<br>  ccdiv.style.border = “2px solid #fff”;<br>  ...<br>  ccdiv.innerHTML = str;<br>  ccdiv.addEventListener(“click”, animationClick);<br>}</pre><p>We will go over animationClick function below.</p><p><strong>Create Info Window</strong></p><p>The Info window popup is provided by the API. The InfoWindow object is initialized once in the initMap method and then add to the maps through the “click” event listener as below. The “content” is the html text to be displayed. So as you click on the bMap drawing, the InfoWindow will pop up at the bMap.center location. We will go over bMap object next.</p><pre>var infoWindow;<br>infoWindow = new google.maps.InfoWindow();<br>var content = getInfoBubbleStr(name, infected, date)<br>google.maps.event.addListener(<br>  bMap,’click’, (function(bMap,content,infoWindow) {<br>    return function() {<br>      infoWindow.setContent(content);<br>      infoWindow.setPosition(bMap.center);<br>      infoWindow.open(map, bMap);<br>    };<br>  })(bMap, content, infoWindow));</pre><p><strong>Draw the border</strong></p><p>To draw the border, we use the Polygon object. This object needs the coordinates to draw. Each coordinate has the latitude and longitude numbers. The polygon object has a stroke color for the border and a fill color to color the area of the polygon.</p><pre>var bMap = new google.maps.Polygon({<br>  paths: coords,<br>  strokeColor: color,<br>  strokeOpacity: 0.65,<br>  strokeWeight: 3,<br>  fillColor: color,<br>  fillOpacity: 0.5,<br>  center: pcenter,<br>});<br>bMap.setMap(map);</pre><p>The variable “map” is google.maps.Map object that we initialized in the initMap method.</p><p><strong>Animation</strong></p><p>To animate, we use the method animationClick which calls beginAnimate using the window.setInterval or window.clearInterval to stop. Each step we just call createBorders which draws the border at a specific date. The create border draw Polygon as showed earlier.</p><pre>function animationClick() {<br>  if (startAnimation) {<br>    startAnimation = false;<br>    beginAnimate(200);<br>  } else {<br>    startAnimation = true;<br>    window.clearInterval(animation);<br>  }<br>};</pre><pre>function beginAnimate(timeout) {<br>  animation = window.setInterval(function () {<br>    createBorders(curStep);<br>    curStep++;<br>    if (curStep &gt;= maxStep) {<br>      window.clearInterval(animation);<br>    }<br>  }, timeout);<br>}</pre><p><strong>Get Live Data from DB</strong></p><p>The basic dataset is a list of dates followed by positive cases per province which can be seen in the timeseries.js. The timeseries.js output was statically entered for testing. But this file is not used at the end since we want to get up to date data from the database.</p><p>I enhanced to call from our Graphql server which outputs JSON data from our database. The JSON output is the record of each patient. The sample data can be seen in domnung_ts.js. The actual fetch method does not work due to cross-site scripting. This will only work when I deploy to our website. So I hardcoded the output from the Graphql as an example. Then I need to process the raw data and output to a format similar to timeseries.js. I won’t go into that detail. You can see the full code here: <a href="https://repl.it/@phylypo/cambodia-covid-19-boundary-map#index.html">https://repl.it/@phylypo/cambodia-covid-19-boundary-map#index.html</a></p><h3>6. Debugging</h3><p>With the Chrome development tool, it is very convenient to debug by adding breakpoints and see the output in addition to inspecting and testing code in the console.</p><p>From the console tab, you can click on the file to the right of the log and see the code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/884/0*XvRbj8PHfKVwBgFj" /></figure><p>Then you can add a breakpoint and click refresh to stop on the breakpoint.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/888/0*vA9ViNcK2LqTrAvd" /></figure><p>Now you can mouse over totalcaseVal to see the value or type in the console. Now you can step through each line of code if needed.</p><p>Once I’m happy with the code, I will continue to React JS next.</p><h3>7. Implementing in React JS</h3><p>The next part is to move the code to React JS. With the React JS component, there are quite a few packages to choose from for Google map API.</p><p>React JS components for Google Map API:</p><ol><li><a href="https://github.com/google-map-react/google-map-react">google-map-react</a> : has a small set of components (4.6K stars)</li><li><a href="https://www.npmjs.com/package/react-google-map">React-google-map</a> : a component to for maps and markers. (23 stars)</li><li><a href="https://github.com/fullstackreact/google-maps-react">Google-maps-react</a> : use of “lazy” loading of dependencies (1.3K stars)<br>Simple and clean set up with straight forward api</li><li><a href="https://tomchentw.github.io/react-google-maps/">react-google-maps</a> : large number of react components (4.4K stars)<br>Lots of components to draw, complicated setup, do most of the drawing, hard with overlay UI</li></ol><p>I started with google-maps-react (#3) which seems pretty straightforward with a detailed tutorial. Then as I started to add more components and drawings, I ran into issues. So tried another one. “React-google-maps” seems to have a lot of components for drawing circle and polygon but run into issues with text UI that display date and total cases.</p><p>I decided to use the Google native API to draw and add UI components. So I went back to use <a href="https://github.com/fullstackreact/google-maps-react">Google-maps-react</a> which has a clean setup. At the end of the development, I did not have to change much. I added the react component for the map and then use the native Google map API to do the rest of the drawing as done earlier.</p><p><strong>React JS Code</strong></p><p>At this step, I assume you already have a React JS running. We will just add a map component to your existing project. First, we start the React JS development by setup the package.json with the package “google-maps-react”. Then you need to install the package with your favorite package tool such as <em>npm</em>. In your module, I show some code structure for the Google map API.</p><p><strong>Package</strong>: package.json</p><pre>“google-maps-react”: “².0.6”,</pre><p><strong>Module</strong>: MapCovid.js</p><pre>import { Map, GoogleApiWrapper } from &#39;google-maps-react&#39;;</pre><pre>export class MapCovid extends Component {<br>  // callback when getting timeseries data is completed<br>  startMapCallback = (totaldata) =&gt; {<br>    this.createBubbles(data.length-1);<br>    this.createNavButton(map);<br>  }</pre><pre>  onMapReady = (mapProps, map) =&gt; {<br>    this.map = map;<br>    loadJsonApi(this.startMapCallback);<br>  }</pre><pre>  render() {<br>    return (<br>      &lt;div&gt;<br>        &lt;Map<br>          google={this.props.google}<br>          onReady={this.onMapReady}<br>          zoom={7}<br>          style={mapStyles}<br>          initialCenter={phnompenh}<br>        &gt;<br>        &lt;/Map&gt;<br>      &lt;/div&gt;<br>    );<br>  }<br>}</pre><pre>export default GoogleApiWrapper({<br>  apiKey: &#39;YOUR_GOOGLE_API_KEY&#39;<br>})(MapCovid);</pre><p><strong>Loading Process</strong></p><p>When the map is ready, it calls the onMapReady method which sets the map context to this.map and calls a method to load the JSON data from the database.</p><p><strong>Drawing Components</strong></p><p>I used the same code from the earlier JS code with minor syntax changes. For example:</p><p>To access google map use window.google:</p><pre>var bMap = new window.google.maps.Polygon({…})</pre><p>I can’t add an event handler the same way as in html for inner div for nav object in the map. Normally we can do this:</p><pre>&lt;input id=”play-range” type=”range” oninput=”this.playRange(this.value)”&gt;</pre><p>Here we need to iterate to object to add an event listener. Also we can’t pass in the parameters directly. We have to use one of the following approaches:</p><pre>var rangeinput = ccdiv.firstElementChild.firstElementChild;<br>rangeinput.addEventListener(“input”, this.playRange, false); <br>…</pre><pre>playRange = (evt) =&gt; {<br>  var val = evt.currentTarget.value<br>  …<br>}</pre><p>You can see the final integration with React JS here:</p><ul><li><a href="https://domnung.com/t/covid-19-map">https://domnung.com/t/covid-19-map</a> (circle map)</li><li><a href="https://domnung.com/t/covid-19-map-boundary">https://domnung.com/t/covid-19-map-boundary</a> (region map)</li></ul><h3>Conclusion</h3><p>Google map API provides a range of tools to draw on the map. To use it you need to enable the Google map API with billing enabled. You will need to restrict the usage to specific sites to avoid unrelated charges.</p><p>This post also covers the JS online editing IDE that can be used for free. Converting the code to be used in React JS was a challenge at first but I was able to use the native Google map API to complete the integration.</p><p>We accomplished our goal of visualizing the spread of Covid-19 in Cambodia at the province level through Google Map API and data from Wikipedia and OpenStreetMap.</p><p>You can see the full code here:<br><a href="https://repl.it/@phylypo/cambodia-covid-19-boundary-map#index.html">https://repl.it/@phylypo/cambodia-covid-19-boundary-map#index.html</a></p><p>Note that this does not have the React JS version since I didn’t set up React JS on repl.it.</p><p>I hope this gives you a high-level implementation with some specific detail that can get you started. Happy coding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=163ec5a87518" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating a Khmer Language Model using BERT]]></title>
            <link>https://medium.com/@phylypo/creating-a-khmer-language-model-using-bert-9a12d3f12b03?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/9a12d3f12b03</guid>
            <category><![CDATA[bert]]></category>
            <category><![CDATA[pre-training]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[from-scratch]]></category>
            <category><![CDATA[khmer]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Sat, 11 Apr 2020 06:42:15 GMT</pubDate>
            <atom:updated>2020-05-31T21:55:30.986Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>An Introduction to NLP for Non-Technical</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*PHb2d_1PX8edFCzrTuhNEA.png" /></figure><p>I have been spending some time experimenting with machine learning with Khmer languages and started to play with one of the latest advances in artificial intelligence called BERT. In this article, I write about the history and an introduction related to natural language processing (NLP) to give you an idea of what the algorithm is but more importantly I detailed the process that it involves in its learning of the language.​ You can read more detailed technical approaches about the different algorithms <a href="https://medium.com/@phylypo/a-survey-of-the-state-of-the-art-language-models-up-to-early-2020-aba824302c6">here</a>.</p><p>This article is also available in <a href="https://medium.com/@phylypo/%E1%9E%80%E1%9E%B6%E1%9E%9A%E1%9E%94%E1%9E%84%E1%9F%92%E1%9E%9A%E1%9F%80%E1%9E%93bert%E1%9E%B2%E1%9F%92%E1%9E%99%E1%9E%99%E1%9E%9B%E1%9F%8B%E1%9E%97%E1%9E%B6%E1%9E%9F%E1%9E%B6%E1%9E%9A%E1%9E%81%E1%9F%92%E1%9E%98%E1%9F%82%E1%9E%9A-4e9b3e326035">Khmer</a>.</p><h3><strong>Introduction</strong></h3><p>Computer scientists have been trying to create an artificial intelligence (AI) program that can understand human language. We had seen progress in which a machine challenged humans in a game of Jeopardy in 2011. Watson, a program that was made by IBM, won Jeopardy games against the two human champions. This signified how the machine can learn the nuance of the English language well enough to play the game. The creators of this system took many years to train and refine the algorithms to specifically play this game.</p><h3><strong>BERT</strong></h3><p>One of the recent progress in this area is a generalized approach that an algorithm can learn a language without explicitly program-specific rules of the language. Advancement in this approach is known as <strong>BERT</strong> created by Google in 2018 that can perform questions and answers tasks better than humans. BERT, in this case, is not a Sesame Street character, but a machine learning (ML) algorithm that stands for “Bidirectional Encoder Representation for Transformers” which uses an underlying algorithm called “<strong>transformer</strong>”. This approach can train on a very large amount of text from Wikipedia and books. We just feed all these texts into the algorithm. With the data, the machine is able to learn the lexical (vocabulary), syntactic (structure of the text), and semantic (content or meaning of the text) of the language without us telling it what it is.</p><p>We won’t go into detail about how the algorithm works, but mention the structure of the algorithm. This type of machine learning approach is called “<strong>deep learning</strong>” which refers to an architecture that mimics how we think our brain works at the neuron level. A set of neurons in our brain take in some information and trigger other neurons downstream in multiple layers. Known as the father of deep learning, Jeffrey Hinton, a professor from the University of Toronto, started to popularize this type of machine learning in 2012 in computer vision with AlexNet algorithm that was able to identify objects in an image more accurately than before on the ImageNet competition. This competition regularly took place to highlight the improvement in new algorithms.</p><p>A popular approach used in computer vision is to first train the model on a large set of images. These images are already labeled such as ImageNet which has 14 million images with 20,000 different classes (different objects in the images). Then use this partly algorithm to train on images that you want to analyze. This increases the accuracy of just training on the final images of data. This approach is called <strong>transfer learning</strong>.</p><p>BERT uses this same transfer learning approach by pre-train the model on a large amount of text. The text is easy to get from the Internet such as Wikipedia without having to do any work to label the data as we see in the computer vision approach where a human has to identify what the object is in the image.</p><p>With this large amount of text (800 million words from books and 2.5 billion words from English Wikipedia), BERT creates its own task by feeding each sentence into the algorithm by eliminating some words. These missing words are called “masking” words. Then it tries to predict the missing words. By masking some input words and learning how to predict them, the algorithm learned the structure of the sentence and some form of the word’s meaning.</p><p>The advancement in this approach is due to faster computers that are able to run on larger amounts of text. In addition, the underlying algorithm “transformer” allows the algorithm to parallelize the processing better than earlier algorithms. With these combinations including the deep architecture that uses many layers with over 300 million parameters, this algorithm became the state of the art during its time.</p><p>This BERT architecture can apply to many languages besides English as long as you have enough text to train. In fact, Google has pre-trained models of about 100 languages. These languages are the top 100 languages with the largest Wikipedias. Khmer is not one of them since the number of articles written in Khmer in Wikipedia was ranked 155th of all the languages.</p><h4><strong>SQuAD</strong></h4><p>BERT was shown to be able to perform a question and answer tasks based on a given text better than humans. The dataset that we used is called Stanford Question Answering Dataset (SQuAD) with a score of 87% accuracy versus humans with 82% accuracy for exact match answer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/646/0*qQiCyiSzb32O3SAl" /><figcaption>SQuAD 1.1 Leaderboard. Retrieved January 20, 2019, from <a href="https://rajpurkar.github.io/SQuAD-explorer/">https://rajpurkar.github.io/SQuAD-explorer/</a></figcaption></figure><p>The SQuAD is a dataset created by Stanford University for the AI community to test how well a machine can understand the text. Based on a given text, there are several questions that are asked. To be able to answer correctly, the human or program has to understand the structure of the text.</p><p>For example: (Text passage on left, questions and the correct answers are on the right).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lxaf1Hv2ZxLLls1Q" /></figure><p>In this example of the second question, the answer is not in the same sentence as the question. So the computer has to figure out the answer from the previous sentence.</p><h3><strong>BERT on the Khmer Language</strong></h3><p>Now, we will train this algorithm on the Khmer language. We are going to evaluate whether the computer understands the text using a task called <strong>document classification</strong>. Given a document, the computer has to identify which class or category of a document​ belongs to. A popular example is for the algorithm to predict if an email is a spam or not.</p><p>Earlier, we created a Khmer news portal website that takes headlines from many Khmer sites and showed them on one page. In the process, we realized that there are so many traffic accident-related articles that overwhelm other important headlines. As a result, we created an ML classification task to identify each of the Khmer news articles they are traffic accidents. Then group them into a section so it will overwhelm the front page. So we will use the same task to see if the Khmer BERT algorithm can classify those articles well or not.</p><p>We have 820 articles that we chose and label each of them as ‘1’ if it is about a traffic accident or ‘0’ if it is not. This will be our training dataset.</p><p>Example text and its label as ‘accident’ or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/730/0*g592KBjjo1cYBY3p" /></figure><p>In this process, we have 2 steps. In step one, we feed a lot of Khmer text into the algorithm BERT so that it can learn the Khmer language structure. This process is called pre-train the language model. In step two, we feed the news articles that we chose with the labels that tell the algorithm to learn to distinguish between class 0 or class 1. This step is called <strong>finetune</strong> for a <strong>classification task</strong>.</p><h4><strong>Step 1: Pre-train the Language Model</strong></h4><p>In step 1, we feed a large corpus of Khmer text into the algorithm. The text must allow the algorithm to split the text into words. Since Khmer does not use spaces to separate words, we need an extra step to process the text that helps the computer to determine which series of letters to form a word. This is called “<strong>word segmentation</strong>”. We will use an algorithm called “CRF” that has shown to perform well for the Khmer language. See my previous article for detail.</p><p>At this point, all of our text has spaces between words. The algorithm then generates a list of all the different words​ that are seen in the articles. Each of the words will be assigned to a unique number that the algorithm will use.</p><p>For example:</p><blockquote>Input Text: “ឃាត់​ ⁣ជនសង្ស័យ ⁣ម្នាក់ ⁣បន្ទាប់ពី”<br>Tokenized: [‘ឃាត់’, ‘ជនសង្ស័យ’, ‘ម្នាក់’, ‘បន្ទាប់ពី’]<br>Token IDs: [1585, 1438, 1062, 1482]</blockquote><p>In the example above, we first split the text into 4 words by our segmentation process. Then it turns into series numbers with each word corresponding to the word in the dictionary we generated previously. These series of numbers become the inputs to the algorithm.</p><p>In this pre-train phase, it first chooses 15% of the word and indicates it as a “<strong>mask</strong>”. Then it learns to predict the mask word. As it compares the prediction to the actual word, it goes back and adjusts its weights or parameters (values in its connections) so that the prediction would be correct. It tries the next input and readjusts its weights again. It does this again and again until all the text was processed.</p><p>This is the part that takes a long time to run when you have a lot of data. The pre-train BERT model by Google for English runs over 3 billion words which took about 54 hours on Google hardware (TPUs) to complete. In our case, we only feed a small set of data in comparison. It took us only a few minutes for 334 thousand words of 1000 Khmer news articles.</p><p>This training process allows the system to learn the contextual structure of the sentence and how the word related to each other.</p><h4><strong>Step 2: Finetune BERT for Classification Task</strong></h4><p>In step 2, we will use our label data of 820 news articles we label as traffic accidents or not. Label 1 implies it is traffic accident-related and label 0 implies that it is not. We feed them the article text and its label. We update the model with extra architecture to be able to do the classification tasks.</p><p>We do not program anything specific about traffic accidents. The machine does not know anything about what label 1 or 0. It has to infer what are the differences between articles labeled as 0 and those with the label 1.</p><p>I can introduce a possible approach that the computer might try to solve this task. It may learn that articles of category 1 have the words “car” or “motorcycle”. But we know that some articles about “car show” or “motorcycles on sale” do not have the labeled 1. So it needs to learn to distinguish that “car show” or “motorcycle sell” related articles that contain the words “car” or “motorcycle” are not labeled as 1. It might find that articles of label 1 contain death or injury, but we know that articles about robbery and murder are labeled as 0. So it has to distinguish those as label 0. The algorithm will try to learn the features in the sentence, not just words as identified above, in order to make the distinction between the categories.</p><p>In fact, the approach mentioned of just looking at words is an older approach called “bag of words” where the program uses the different word counts in each article to make the classification. This approach does not perform well since it does not take into account the word orders or sentence structure that can be important in document classification.</p><p>To continue with our training​ process, the first step is to separate our articles into a <strong>training set</strong> and a <strong>validation set</strong>. The goal of the validation set is to set aside some articles so that the algorithm does use them during training. This can be used at the end to verify how well the algorithm performs. We saved 10% of the articles as a validation set. We use 90% of the total data of 820 documents. So the total number of articles is 738 for training and 82 for validation sets.</p><blockquote>Training set: 738<br>Validation set: 82<br>Total Documents: 820</blockquote><p>In the first step, it takes a set of input data and tries to adjust its weights to make the predictions better. After it goes through all 738 training data, the amount of error (loss) result is about 0.7 or 70% as shown in the blue line below. The process of going through the whole dataset is known as one <strong>epoch</strong>. With the current state, we test and see how it predicts the validation set. We see that the accuracy is about 50% as indicated as the red line in the chart below. This is not good. This accuracy is the same as if we were to randomly guess the answer.</p><p>Now we let it go through the same data again and readjust its weights and got about the same loss in the next 5 epochs. It performs about the same on a validation set of around 50% accuracy.</p><p>Then the sixth epoch shows a little better prediction. The validation set shows about 70% accuracy. This is a lot better than before but not great yet. Then in the seventh epoch, the accuracy went up to over 90%. Then in 9 epochs, it goes up to close 99%. As it goes through we see in the 17th epoch, it reaches 100% then 99% on the rest of the epoch. This accuracy beat our previous models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/0*5W6qf1N5y0F5cv1G" /></figure><h3><strong>Conclusion</strong></h3><p>We have seen that in 2018, the BERT algorithm has surpassed human capability in question and answer tasks in SQuAD 1.1 dataset. We see that we can pre-train BERT with Khmer text so it can learn the structure of the language. Then we finetune the algorithm with news articles data that we label as a traffic accident-related. Our result shows that the model can predict whether it is a traffic-related accident article with very high accuracy.</p><p>We may not know the exact approach that the algorithm used to distinguish whether an article is a traffic accident or not. But from our results, it was able to distinguish with high accuracy of 99%. It only misclassified about 1 for every 100 articles.</p><p>Does this mean that the algorithm understands the Khmer text? That depends on how you look at it. All we feed into the algorithm are just numbers that reference the Khmer word in our dictionary list. You can say it does not know anything about any of the Khmer words. But as we feed a lot of these numbers that signify Khmer words and its order. The algorithm knows some structure of those numbers that corresponded to our Khmer words. It knows enough about the structure to be able to distinguish if an article is a traffic accident-related or not.</p><p>You can see the full code which includes how we train Khmer language model from scratch:</p><p><a href="https://github.com/phylypo/khmer-text-data/tree/master/bert-pretrain-from-scratch">https://github.com/phylypo/khmer-text-data/tree/master/bert-pretrain-from-scratch</a></p><p>You can find other datasets that you can use here: <a href="https://github.com/phylypo/khmer-text-data">https://github.com/phylypo/khmer-text-data</a>.</p><h4><strong>Other Notes</strong></h4><p>It would be a better illustration to have the algorithm generate Khmer text to illustrate its understanding of the language. Unfortunately, BERT is not meant for that. Other another algorithm ULMFiT that I trained uses a similar dataset and is able to generate text. Give the algorithm some words, it will predict the next few words that will make sense and even grammatically correct. See this site that I made from another algorithm here: <a href="http://ml.tovnah.com/khmer-ulmfit/">http://ml.tovnah.com/khmer-ulmfit/</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9a12d3f12b03" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ការបង្រៀនBERTឲ្យយល់ភាសារខ្មែរ]]></title>
            <link>https://medium.com/@phylypo/%E1%9E%80%E1%9E%B6%E1%9E%9A%E1%9E%94%E1%9E%84%E1%9F%92%E1%9E%9A%E1%9F%80%E1%9E%93bert%E1%9E%B2%E1%9F%92%E1%9E%99%E1%9E%99%E1%9E%9B%E1%9F%8B%E1%9E%97%E1%9E%B6%E1%9E%9F%E1%9E%B6%E1%9E%9A%E1%9E%81%E1%9F%92%E1%9E%98%E1%9F%82%E1%9E%9A-4e9b3e326035?source=rss-bac53c544b44------2</link>
            <guid isPermaLink="false">https://medium.com/p/4e9b3e326035</guid>
            <category><![CDATA[bert]]></category>
            <category><![CDATA[ខ្មែរ]]></category>
            <category><![CDATA[បញ្ញា]]></category>
            <category><![CDATA[សិប្បនិមិត្ត]]></category>
            <category><![CDATA[khmer]]></category>
            <dc:creator><![CDATA[Phylypo Tum]]></dc:creator>
            <pubDate>Sat, 11 Apr 2020 03:27:14 GMT</pubDate>
            <atom:updated>2023-02-17T22:36:28.928Z</atom:updated>
            <content:encoded><![CDATA[<h4>សេចក្តីណែនាំអំពី​ NLP⁣ ⁣ជាសាមញ្ញ</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*PHb2d_1PX8edFCzrTuhNEA.png" /></figure><p>ខ្ញុំ​បាន​ចំណាយ​ពេល​ខ្លះ​ដើម្បី​ពិសោធន៍​ ⁣”របៀប​ដែល⁣​ម៉ាស៊ីន​រៀន” ⁣⁣ជាមួយ​និង​ភាសាខ្មែរ​ ⁣ហើយ​ចាប់​ផ្តើម​សាកល្បង​ជាមួយ​ការ​ជឿនលឿន​ចុង​ក្រោយ​នៃ​បញ្ញា​សិប្បនិម្មិត ដែល​គេ​ហៅ​ថា បឺត ⁣(BERT) ។ នៅ​ក្នុង​អត្ថបទ​នេះ ខ្ញុំ​សរសេរ​អំពី​ប្រវត្តិ​ខ្លះៗ និង​ការណែនាំ​ ទាក់ទង​ទៅ​នឹង ដំណើរ​ការ​ភាសា​ធម្មជាតិ (NLP) ដើម្បី​ផ្តល់​ឱ្យ​អ្នក​យល់​ពី​ក្បួន​ដោះស្រាយ ប៉ុន្តែ​សំខាន់​ជាង​នេះ​ទៅទៀត ខ្ញុំ​បាន​រៀបរាប់​លម្អិត​អំពី​ដំណើរការ ដែល​ពាក់ព័ន្ធ​នឹង​របៀប​ម៉ាស៊ីន​រៀន​ភាសា​យើង។​ ⁣អ្នក​អាច​អាន​បន្ថែម វិធីសាស្ត្រ​លម្អិត​ផ្សេង ⁣នៅ​<a href="https://medium.com/@phylypo/a-survey-of-the-state-of-the-art-language-models-up-to-early-2020-aba824302c6">ទីនេះ</a>ជា​ភាសា​អង្គ្លេស។</p><h3><strong>សេចក្តីផ្តើម</strong></h3><p>អ្នក​វិទ្យាសាស្ត្រ​ខាង​កុំព្យូទ័រ​កំពុង​ព្យាយាម​បង្កើត​កម្មវិធី​សិប្បនិម្មិត (AI) ដែល​អាច​យល់​ពី​ ⁣ភាសា​របស់​មនុស្ស។ ⁣យើង​បាន​ឃើញ​វឌ្ឍនភាព​ដែល​ម៉ាស៊ីន ⁣បាន​ប្រកួត​ប្រជែង​ជាមួយ​មនុស្ស ⁣នៅ​ក្នុង​ល្បែង Jeopardy ក្នុងឆ្នាំ២០១១⁣។​ ⁣​ វ៉ាតសុន​ ⁣(Watson) ⁣​ដែល​ជា​កម្មវិធី ⁣ដែល​បង្កើត​ឡើង​ដោយ ⁣ក្រុមហ៊ុន IBM បាន​ឈ្នះ​ល្បែង Jeopardy ប្រឆាំង​នឹង​អ្នក​ជើងឯក​ពីរ​រូប។ នេះ​ជា​សញ្ញា​បង្ហាញ​ពី​របៀប​ ⁣ដែល​ម៉ាស៊ីន​អាច​រៀន​ពី​ភាសា​អង់គ្លេស⁣​បាន​ល្អ​គ្រប់គ្រាន់​ ⁣ដើម្បី​នឹង​លេងល្បែង​នេះ។ អ្នកបង្កើត ⁣ប្រព័ន្ធ​នេះ ⁣បាន​ចំណាយ​ពេល​ជា​ច្រើន​ឆ្នាំ ⁣ដើម្បី​បណ្តុះបណ្តាល​និង​កែ​លម្អ​ក្បួន​ដោះស្រាយ ⁣ដើម្បី​លេង​ល្បែង​នេះ។</p><h3><strong>បឺត​ ⁣(BERT)</strong></h3><p>ការ​រីក​ចម្រើន​ថ្មី​មួយ​នៅ​ក្នុង​ផ្នែក​នេះ ⁣គឺ​ជា​វិធីសាស្ត្រ​មួយ​ ⁣ដែល​ម៉ាស៊ីន​អាច​រៀន​ភាសា​បាន ⁣ដោយ​មិន​ចាំបាច់​ ⁣សរសេរ⁣​ច្បាប់​ជាក់លាក់ ⁣របស់​ភាសា​នោះ។ ការ​ជឿនលឿន​នៃ​វិធីសាស្ត្រ​នេះ ⁣ត្រូវ​បាន​គេ​ស្គាល់​ថា BERT បង្កើត​ដោយ​ហ្គូហ្គល ⁣(Google) ⁣ក្នុងឆ្នាំ២០១៨ ដែល​អាច​ ⁣ឆ្លើយ​សំណួរ​បាន ⁣ប្រសើរ​ជាង​មនុស្ស។ ក្នុង​ករណី​នេះ ⁣BERT មិនមែន​ជា​តួអង្គ Sesame Street ទេ ⁣តែ​ជា​ឈ្មោះ​នៃ​កម្មវិធី​របស់​ម៉ាស៊ីន​ដែល​រៀន (ML) ⁣ដែល​មាន​នៃ​ថា ⁣“Bidirectional Encoder for Transformers” ។ ⁣គេ​អាច​បណ្តុះបណ្តាល​វិធីសាស្ត្រ​នេះ​ដោយ​ប្រើ ​អត្ថបទ​ជា​ច្រើន​ពី​វីគីភីឌៀ​ ⁣(Wikipedia) ⁣និង​សៀវភៅ។ យើង​គ្រាន់តែ​បញ្ចូល​អត្ថបទ​ទាំងអស់​នេះ ⁣ទៅ​ក្នុង​ក្បួន​កម្មវិធី​⁣ប៉ុណ្ណោះ ⁣ហើយ​វា​និង​រៀន​ដោយ​ខ្លួន​វា។ ជា​មួយ​អត្ថបទ​ជា​ច្រើន​នោះ ⁣ម៉ាស៊ីន​អាច​រៀន​ពី​វាក្យស័ព្ទ​ ⁣ រចនាសម្ព័ន្ធ​នៃ​អត្ថបទ និង​ខ្លឹមសារ ⁣ឬ​អត្ថន័យ​នៃ​អត្ថបទ ⁣ដោយ​មិន​ប្រាប់​ពី​ក្បួន​ជាក់លាក់​អ្វី​ទេ។</p><p>យើង​នឹង​មិន​និយាយ​លម្អិត​អំពី​របៀប​ដែល​កម្មវិធី​ដំណើរ​ការ​នោះ​ទេ ⁣ប៉ុន្តែ​យើង​និយាយ​អំពី​រចនាសម្ព័ន្ធ​នៃ​វិធីសាស្ត្រ​នេះ។ ⁣ម៉ាស៊ីន​ដែល​រៀន​របៀប​នេះ ⁣ត្រូវ​បាន​គេ​ហៅ​ថា ⁣“ការ​រៀន​ស៊ី​ជម្រៅ”​ ⁣(<strong>deep learning</strong>) ដែល​សំដៅ​ទៅលើ ⁣ស្ថាបត្យកម្ម​ដែល​ធ្វើ​តាម​របៀប​ដែល​ខួរក្បាល​មនុស្ស ⁣ តាម​កម្រិត​ណឺរ៉ូន ⁣(neuron) ⁣ដំណើរការ។ ពេល​ដែល​សំណុំ​នៃ​ណឺរ៉ូន ⁣⁣នៅ​ក្នុង​ខួរក្បាល​របស់​យើង​ទទួល​ព័ត៌មាន ⁣ពី​ភ្នែក​ឬ​ត្រចៀក វា​ផ្ញើ​បន្ត ⁣​ទៅ​ណឺរ៉ូន​ផ្សេង​ទៀត ជា​ច្រើន​សន្ទាប់​ជា​បន្តបន្ទាប់។ លោក Jeffrey Hinton ជា​សាស្ត្រាចារ្យ មកពី ⁣សាកលវិទ្យាល័យ​តូរ៉ុនតូ ⁣(Toronto) ⁣បាន​ចាប់ផ្តើម ⁣ធ្វើ​ឲ្យ​មាន​⁣ប្រជាប្រិយភាព ⁣លើ​ម៉ាស៊ីន​ដែល​រៀន ⁣ប្រភេទ​នេះ​ ⁣ក្នុង​ឆ្នាំ ២០១២ នៅ​ក្នុង​ចក្ខុវិស័យ​នៃ​កុំព្យូទ័រ​ ⁣(computer vision) ⁣ជាមួយ​កម្មវិធី ⁣អាឡិចណិត​ ⁣(AlexNet) ⁣ដែល​ឈ្នះ​ការប្រកួតប្រជែង របៀប​ដែល​ម៉ាស៊ីន​អាច​មើល​រូបភាព ⁣បាន​ល្អ​ប្រសើរ​ជាង​មុន ។ ការប្រកួតប្រជែង ⁣ImageNet Competition នេះ ⁣បាន​ធ្វើឡើង​ជា​ទៀងទាត់ ⁣ដើម្បី​បង្ហាញ​ពី​ភាព​ប្រសើរ​ឡើង​នៃ​កម្មវិធី​ថ្មីៗ។</p><p>វិធីសាស្ត្រ​ប្រជាប្រិយ​មួយ​⁣ដែល​ត្រូវ​បាន​ប្រើ​នៅក្នុង​ចក្ខុវិស័យ​កុំព្យូទ័រ ⁣គឺ​ដំបូង​ត្រូវ​បណ្តុះបណ្តាល​កម្មវិធី​ដោយ​ប្រើ​រូបភាព​យ៉ាង​ច្រើន។ ⁣ការ​ធ្វើ​បែប​នេះ ⁣អនុញ្ញាត​ឲ្យ​​ ⁣កម្មវិធី​រៀន​ពី​ទ្រង់ទ្រាយ​នៃ​រូបភាព។ ⁣ ⁣រូបភាព​ទាំងនេះ​ត្រូវ​បាន​ដាក់​ស្លាក​រួច​ហើយ ⁣នូវ​អ្វី​ដែល​ជា​វត្ថុ​ ⁣ក្នុង​រូបភាព​នោះ ⁣ដូចជា ImageNet ដែល​មាន​រូបភាព​ចំនួន ១៤ លាន​រូប ⁣និង ២០,០០០ ថ្នាក់ (វត្ថុ​ផ្សេងៗ​ក្នុង​រូបភាព) ។ បន្ទាប់មក គេ​យក​កម្មវិធី​នេះ​ ⁣ទៅ​ហ្វឹកហាត់​លើ​រូបភាព​ដែល​គេ​ចង់​វិភាគ។ របៀប​នេះ​បង្កើន​លទ្ធផល​ត្រឹមត្រូវ​ច្រើន​ជាង​ការ​បណ្តុះបណ្តាល​ត្រឹម​តែ​លើ​រូបភាព​ដែល​អ្នក​ចង់​វិភាគ។ វិធីសាស្ត្រ​នេះ​ត្រូវ​បាន​គេ​ហៅ​ថា​ការ​រៀន​ផ្ទេរ ⁣(<strong>transfer learning</strong>)។</p><p>BERT ប្រើ​វិធីសាស្ត្រ​រៀន​ផ្ទេរ​ដូចគ្នា ⁣ដោយ​បណ្តុះបណ្តាល​លើ​ចំនួន​អត្ថបទ​ដ៏​ច្រើន។ អត្ថបទ​ងាយ​រក​បាន​ពី​អ៊ីនធឺណិត (Internet) ⁣ដូច​ជា​ទំព័រ​វីគីភីឌៀ ⁣(Wikipedia) ⁣ដោយ​មិន​ចាំបាច់​ធ្វើការ​ដាក់​ស្លាក ⁣ដូច​ជា​វិធីសាស្ត្រ​ចក្ខុវិស័យ​កុំព្យូទ័រ ⁣ដែល​មនុស្ស​ ⁣ត្រូវ​កំណត់​ថា​នៅ​ក្នុង​រូបភាព​នោះ​មាន​វត្ថុ​អ្វី។</p><p>ជា​មួយ​អត្ថបទ​ដ៏​ច្រើន​នេះ (៨០០ លាន​ពាក្យ​ពី​សៀវភៅ​និង ២,៥ ពាន់​លាន​ពាក្យ​ពី​វីគីភីឌៀ​អង់គ្លេស) បឺត​មាន​ភារកិច្ច​ផ្ទាល់​ខ្លួន​ដោយ​បញ្ចូល​ប្រយោគ​នីមួយៗ​ទៅ​ក្នុង​ក្បួន​ដោះស្រាយ ⁣ដោយ​លុប​បំបាត់​ពាក្យ​ខ្លះ។ ពាក្យ​ដែល​បាត់​ទាំងនោះ​ត្រូវ​បាន​គេ​ហៅ​ថា ⁣ពាក្យ“លាក់បាំង” (masking)។ បន្ទាប់​មក ⁣វា​ព្យាយាម​ទាយ​ពាក្យ​ដែល​បាត់​នោះ។ ⁣ដោយ​ការ​លាក់បាំង​ពាក្យ​មួយ​ចំនួន ⁣វា​ប្រឹង​រៀន​ពី​របៀប⁣​ទស្សន៍ទាយ​ពាក្យ​ទាំង​នោះ ។​ ⁣⁣ក្បួន​នេះ​បាន​បង្រៀន​វា​ ពី​រចនាសម្ព័ន្ធ​នៃ​ភាសា ⁣ទម្រង់​របស់​អត្ថបទ ⁣និង​អត្ថន័យ​របស់​ពាក្យ។</p><p>ការ​ជឿនលឿន​ក្នុង​វិធីសាស្ត្រ​នេះ ⁣គឺ​ដោយសារ​តែ​កុំព្យូទ័រ​មាន​ល្បឿន​លឿន​ជាង​មុន ⁣ដែល​អាច​ដំណើរ​ការ​លើ​អត្ថបទ​បាន​កាន់តែ​ច្រើន។ លើស​ពី​នេះ​ទៀត ⁣ក្បួន​មូលដ្ឋាន ⁣“transformer” អនុញ្ញាត​ឱ្យ​កម្មវិធី​ជា​ច្រើន​ដំណើរការ​ស្រប​ជា​មួយ​គ្នា​យ៉ាង​លឿន​ប្រសើរ​ជាង​ក្បួន​មុនៗ។ ជា​មួយ​គ្នា​នេះ ⁣ស្ថាបត្យកម្ម​ប្រើ​ស្រទាប់​ជា​ច្រើន​ដែល​មាន​ប៉ារ៉ាម៉ែត្រ​ជាង ៣០០ លាន ⁣ធ្វើ​ ⁣ឲ្យ​ក្បួន​នេះ​បាន​ក្លាយ​ជា​ក្បួន​ល្អ​បំផុត​ក្នុង​កំឡុង​ពេល​នោះ​ក្នុង​ឆ្នាំ​២០១៨។</p><p>ស្ថាបត្យកម្ម BERT នេះ​អាច​អនុវត្ត​បាន​ចំពោះ​ភាសា​ណា​ក៏​បាន​ដែរ ⁣ដរាប​ណា​ភាសា​នោះ ⁣មាន​អត្ថបទ​គ្រប់គ្រាន់​សម្រាប់​ហ្វឹកហាត់។ តាម​ពិត​ហ្គូហ្គល​បាន​ហ្វឹកហាត់​ភាសា​គំរូ​មុន​ប្រមាណ ១០០ ភាសា។ ភាសា​ទាំងនេះ​គឺ​ជា​ភាសា១០០ ដែល​មាន​ចំនួន​អត្ថបទ​នៅ​វីគីភីឌៀ​ច្រើន​ជាង​គេ។ ភាសា​ខ្មែរ​មិន​ត្រូវ​បាន⁣​ហ្គូហ្គល​​ហ្វឹកហាត់​ទេ ⁣ព្រោះ​ចំនួន​អត្ថបទ ⁣ដែល​សរសេរ​ជា​ភាសា​ខ្មែរ ⁣នៅ​ក្នុង​វីគីភីឌៀ ⁣បាន​ជាប់​ចំណាត់​ថ្នាក់​ទី ១៥៥ នៃ​ភាសា​ទាំងអស់។ ⁣នេះ​ជាមូល​ហេតុ​ដ៏​សំខាន់​មួយ​​ ⁣ដែល​យើង​ត្រូវ​បញ្ចូល​អត្ថបទ​ ⁣ជា​ភាសា​ខ្មែរ​ឲ្យ​បាន​ច្រើន​នៅ​ទំព័រ​វីគីភីឌៀ។</p><h3>ស្គ្វ៉ដ (<strong>SQuAD</strong>)</h3><p>គេ​បាន​បង្ហាញ​ថាBERT អាច​ឆ្លើយ​សំណួរ​តាម​អត្ថបទ​បាន​ប្រសើរ​ជាង​មនុស្ស។ សំណុំ​ទិន្នន័យ​ដែល​បាន​ប្រើ​មាន​ឈ្មោះថា ស្គ្វ៉ដ (SQuAD) ⁣មាន​ឈ្មោះ​សម្រាយ​គឺ ⁣⁣Stanford Question Answering Dataset ដែល ⁣BERT ⁣បាន​ពិន្ទុ ៨៧% ទល់​នឹង​មនុស្ស​ដែល​បាន​ពិន្ទុ ៨២% សំរាប់​ចម្លើយ​ត្រូវ​គ្រប់​ពាក្យ។</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/646/0*1N-bHSvaFJltpF8w" /><figcaption>SQuAD 1.1 Leaderboard retrieved January 20, 2019 from <a href="https://rajpurkar.github.io/SQuAD-explorer/">https://rajpurkar.github.io/SQuAD-explorer/</a></figcaption></figure><p>SQuAD ⁣គឺជាសំណុំទិន្នន័យដែលបង្កើតឡើងដោយ ⁣សាកលវិទ្យាល័យស្ទែនហ្វត​ ⁣(Stanford University) ⁣សម្រាប់សហគមន៍បញ្ញាសិប្បនិម្មិត ដើម្បីសាកល្បងថាតើ ម៉ាស៊ីនអាចយល់អត្ថបទ បានល្អប៉ុណ្ណា។ ផ្អែកលើអត្ថបទដែលបានផ្តល់ឱ្យ វាមានសំណួរជាច្រើនដែលត្រូវសួរ។ ដើម្បីអាចឆ្លើយបាន កុំព្យូទ័រត្រូវតែយល់ពីរចនាសម្ព័ន្ធរបស់អត្ថបទខ្លះ។</p><p>ឧទាហរណ៍ៈ (អត្ថបទនៅខាងឆ្វេង ⁣សំណួរនិងចម្លើយត្រឹមត្រូវគឺនៅខាងស្តាំ) ។</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xxhcUqYUaQx9C4z-" /></figure><p>ដើម្បីបកប្រែអត្ថបទនេះ៖</p><blockquote>កាលីហ្វ័រញ៉ាភាគខាងត្បូង ជាញឹកញាប់ហៅកាត់ថា SoCal គឺជាតំបន់ភូមិសាស្ត្រនិងវប្បធម៌ ដែលជាទូទៅមានស្រុកចំនួន ១០ នៅខាងត្បូងបំផុតរបស់រដ្ឋ California ។ តំបន់នេះ ត្រូវបានពិពណ៌នាថាជា “ស្រុក ៨” ដោយផ្អែកលើប្រជាសាស្ត្រ និងទំនាក់ទំនង សេដ្ឋកិច្ច៖ Imperial, Los Angeles, Orange, Riverside, San Bernardino, San Diego, Santa Barbara, និង Ventura ។ និយមន័យនៃតំបន់ចំនួន ១០ ដែលទូលំទូលាយជាងនេះរួមមានរដ្ឋ Kern និង San Luis Obispo ក៏ត្រូវបានប្រើដោយផ្អែកលើការបែងចែកនយោបាយ ជាប្រវត្តិសាស្ត្រ ផងដែរ។ កាលីហ្វ័រញ៉ាខាងត្បូង គឺជាមជ្ឈមណ្ឌលសេដ្ឋកិច្ចដ៏សំខាន់មួយ សម្រាប់រដ្ឋកាលីហ្វ័រញ៉ា និងសហរដ្ឋអាមេរិក។</blockquote><blockquote><strong>សំនួរ​:</strong>ទោះបីជាត្រូវបានគេពិពណ៌នាជាប្រពៃណីថាជា“ ស្រុក ៨” តើតំបន់នេះមានស្រុកប៉ុន្មានដែរ?</blockquote><blockquote><strong>ចំលើយ</strong>: ១០</blockquote><p>ក្នុងឧទាហរណ៍នេះ ⁣ដូចដែលអ្នកបានឃើញហើយ ⁣ចម្លើយមិនមាន ⁣នៅក្នុងប្រយោគ ⁣ជាមួយនឹងសំណួរនោះទេ។ ដូច្នេះកុំព្យូទ័រត្រូវរកចម្លើយពីប្រយោគមុន។</p><h3>ប្រើភាសាខ្មែរក្នុងBERT ⁣</h3><p>ឥឡូវយើងនឹងបណ្តុះបណ្តាលកម្មវិធីនេះដោយ​បញ្ចូលភាសាខ្មែរ។ យើងនឹងវាយតំលៃថាតើកម្មវិធីនេះយល់ពីអត្ថបទខ្មែរឬទេ ⁣ដោយឲ្យវាបែងចែក<strong>ឯកសារ ⁣(document classification)</strong>។ កុំព្យូទ័រ នឹងពិនិត្យមើលថា ⁣តើ⁣ឯកសារនិមួយៗ ត្រូវជាប្រភេទឯកសារ​ណាមួយ។ ⁣ឧទាហរណ៏ដែលគេនិយមប្រើគឺឲ្យកម្មវិធីសម្រាច់ថា ⁣តើអ៊ីម៉ែលនិមួយៗ ⁣គឺជាអ៊ីម៉ែលឥតបានការ ⁣(spam) ⁣ឬអត់។</p><p>មុននេះយើងបានបង្កើត<a href="https://domnung.com/">គេហទំព័រព័ត៌មានខ្មែរ</a> ដែលយកចំណងជើងពីគេហទំព័រខ្មែរជាច្រើន ហើយបង្ហាញរួមលើទំព័រមួយ។ នៅក្នុងដំណើរការនេះ ⁣យើងបានឃើញថា​ ⁣មានអត្ថបទ ទាក់ទងនឹងគ្រោះថ្នាក់ចរាចរណ៍ច្រើន ⁣ដែលនាំឲ្យពិបាកមើល​ ⁣ចំណងជើងសំខាន់ៗផ្សេងទៀត។ ជាលទ្ធផល ⁣យើងបានបង្កើតកម្មវិធី AI មួយ ⁣ដើម្បីរកអត្ថបទដែលមានគ្រោះថ្នាក់ចរាចរណ៍ ⁣ហើយ​ទុកដើយឡែក ⁣ពី​អត្ថបទដ៏ទៃ ⁣ដើម្បីកុំឲ្យនៅជាន់ ⁣លើអត្ថបទនៅទំព័រដើម។ ដូច្នេះយើងនឹងប្រើកិច្ចការដូចគ្នានេះ ⁣ដើម្បីមើលថាតើកម្មវិធី ⁣BERT នេះអាចបែងចែកអត្ថបទទាំងនោះបានល្អឬទេ។</p><p>យើងមានអត្ថបទ ៨២០ មាត្រាដែលយើងបានជ្រើសរើសនិងដាក់ស្លាកនីមួយៗថា​ ⁣“១” ប្រសិនបើវានិយាយអំពីគ្រោះថ្នាក់ចរាចរណ៍ ⁣ឬ “០” ប្រសិនបើវា ⁣មិនមែនជាអត្ថបទ ⁣គ្រោះថ្នាក់ចរាចរណ៍ទេ។ នេះជាសំណុំអត្ថបទ ⁣ដែល​យើង​និង​ប្រើ​​ឲ្យ⁣កម្មវិធីបឹតបែងចែក​អត្ថបទ។​</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/730/0*KvAoS65y4Zl6a5GV" /><figcaption>នេះជាអត្ថបទឧទាហរណ៍និងស្លាករបស់វាថា “គ្រោះថ្នាក់” ឬអត់។</figcaption></figure><p>នៅក្នុងដំណើរការនេះ យើងមាន ២ ជំហាន។ នៅជំហានទី ១ យើងបញ្ចូលអត្ថបទជាភាសាខ្មែរជាច្រើនទៅក្នុងក្បួនដោះស្រាយ BERT ដើម្បី​ឲ្យ​វា⁣អាចរៀន ⁣រចនាសម្ព័ន្ធភាសាខ្មែរ។ ដំណើរការនេះត្រូវបានគេហៅថាការហ្វឹកហាត់ជាមុន ⁣(<strong>pre-train</strong>) ⁣នៃគំរូភាសា។ ក្នុងជំហ៊ានទី ២ យើងបញ្ចូលអត្ថបទ ⁣ដែលយើងបានជ្រើសរើសជាមួយស្លាក ⁣ដែលប្រាប់ពីក្បួនដោះស្រាយ ⁣ដើម្បីរៀនបែងចែករវាងថ្នាក់ ០ ឬថ្នាក់ទី ១ ។ ជំហ៊ាននេះ ⁣ត្រូវបានគេហៅថា ការកែរតំរូវ ⁣(<strong>finetune)</strong> សំរាប់កិច្ចការបែងចែក​អត្ថបទ។</p><h4><strong>ជំហានទី ១: ⁣</strong>ការហ្វឹកហាត់<strong>ភាសាគំរូ</strong>ជាមុន</h4><p>ក្នុងជំហានទី ១ យើងបញ្ចូលអត្ថបទជាភាសាខ្មែរទៅក្នុងក្បួនដោះស្រាយ។ អត្ថបទត្រូវតែអនុញ្ញាតឱ្យ ក្បួនដោះស្រាយ បំបែកអត្ថបទទៅជាពាក្យ។ ដោយសារខ្មែរមិនប្រើ អក្សរដកឃ្លារវាងពាក្យ ⁣យើងត្រូវធ្វើកិច្ច​ការមួយដែល​ត្រូវបានគេហៅថា ⁣“ការបែងចែកពាក្យ” (<strong>word segmentation</strong>)។ យើងនឹងប្រើក្បួនដែលហៅថា CRF ដែលមានដំណើរការល្អ​ ⁣សម្រាប់ភាសាខ្មែរ។ សូមមើល<a href="https://medium.com/@phylypo/segmentation-of-khmer-text-using-conditional-random-fields-3a2d4d73956a">អត្ថបទមុន</a>របស់ខ្ញុំសម្រាប់ព័ត៌មានលម្អិត។</p><p>ដល់ចំណុចនេះ យើងបាន​ដាក់ចន្លោះរវាងពាក្យដល់​គ្រប់អត្ថបទរួចហើយ។ បន្ទាប់មក ⁣ក្បួនដោះស្រាយ⁣ត្រូវបង្កើតបញ្ជីពាក្យទាំងអស់ ⁣ដែល​មាន​នៅគ្រប់​អត្ថបទ⁣។​ ពាក្យនីមួយៗនឹងត្រូវមានតំណាងលេខមួយៗ ⁣ដែលក្បួនដោះស្រាយអាចយក​ទៅប្រើ។</p><blockquote>Input Text: “ឃាត់​ ⁣ជនសង្ស័យ ⁣ម្នាក់ ⁣បន្ទាប់ពី”<br>Tokenized: [‘ឃាត់’, ‘ជនសង្ស័យ’, ‘ម្នាក់’, ‘បន្ទាប់ពី’]<br>Token IDs: [1585, 1438, 1062, 1482]</blockquote><p>ក្នុងឧទាហរណ៍ខាងលើ ⁣ដំបូងយើងបែងចែកអត្ថបទជា ៤ ពាក្យដោយ ⁣កម្មវិធី​បែងចែកពាក្យ ⁣របស់យើង។ បន្ទាប់មកវាប្រែទៅជាលេខចំពោះពាក្យ​និមួយៗ ​ដែលត្រូវនឹងពាក្យនៅក្នុងវចនានុក្រម ⁣ដែលយើងបានបង្កើតពីមុននេះ។ លេខទាំងនេះនឹង​ត្រូវបញ្ចូលទៅក្នុងក្បួនដោះស្រាយ។</p><p>នៅក្នុងតំណាក់កាល pretrain នេះ ⁣ដំបូងវាជ្រើសរើស 15% នៃពាក្យហើយ​ដាក់ជាពាក្យ ⁣“របាំង” ។ បន្ទាប់មកវារៀនទាយពាក្យរបាំងនេះ។ នៅពេលវាប្រៀបធៀបការទាយទៅនឹងពាក្យរបាំង ⁣វាកែសម្រួលទម្ងន់ឬប៉ារ៉ាម៉ែត្ររបស់វា ដើម្បីឲ្យការទាយ​នោះបានប្រសើលើក​ក្រោយ។ វានឹងបញ្ចូលប្រយោគបន្ទាប់ហើយកែទំងន់របស់វាម្តងទៀត។ វាធ្វើម្តងហើយម្តងទៀត ⁣រហូតទាល់តែអត្ថបទទាំងអស់ត្រូវបានដំណើរការ។</p><p>នេះគឺជាផ្នែកមួយ ⁣ដែលចំណាយពេលយូរក្នុងដំណើរការ ⁣នៅពេលមានអត្ថបទច្រើន។ ហ្គូហ្គោល ⁣បង្រៀន BERT សម្រាប់ភាសាអង់គ្លេសដោយ​ប្រើអត្ថបទដែល​មានជាង ៣ ពាន់លានពាក្យ ⁣ហើយចំណាយពេលប្រហែល ៥៤ ម៉ោងដោយ​ប្រើ​កុំព្យុទ័រហ្គូហ្គល TPUs ។ ក្នុងករណីរបស់យើង ⁣យើងមានអត្ថបទតិចោះ​ ⁣ចូច្នេះយើងចំណាយពេលតែពីរបីនាទីប៉ុណ្ណោះ ⁣សម្រាប់អត្ថបទ⁣ព័ត៌មានខ្មែរ​ចំនួន ១០០០ អត្ថបទ ⁣ដែល​មានពាក្យចំនួន ៣៣៤ ពាន់ពាក្យ។</p><p>ដំណើរការបណ្តុះបណ្តាលនេះ ⁣អនុញ្ញាតឲ្យ⁣កម្មវិធីយើងរៀនពីរចនាសម្ព័ន្ធនៃប្រយោគ ⁣និងវិធីដែលពាក្យទាក់ទងគ្នា។</p><h4>ជំហានទី ២៖ កែរតំរូវ ⁣BERT សម្រាប់ការបែងចែកប្រភេទឯកសារ</h4><p>ក្នុងជំហ៊ានទី ២ យើងនឹងប្រើអត្ថបទរបស់យើងដែលមានចំនួន ៨២០ ដែលយើងដាក់ស្លាក ⁣ថាជាគ្រោះថ្នាក់ចរាចរណ៍ឬអត់។ ស្លាកលេខ ១ បញ្ជាក់ថាវាជាគ្រោះថ្នាក់ចរាចរណ៍ ⁣ហើយស្លាកលេខ ០ បញ្ជាក់ថាមិនមែនទេ។ យើងបញ្ចូលអត្ថបទនិងស្លាករបស់វាទៅក្នុង​ក្បួនដោះស្រាយ ⁣ដែលមានស្ថាបត្យកម្មបន្ថែមដើម្បីឲ្យវាអាចធ្វើការបែងចែកប្រភេទឯកសារ។</p><p>យើងមិនបានដាក់កម្មវិធីអ្វីជាក់លាក់អ្វីអំពីគ្រោះថ្នាក់ចរាចរណ៍ទៅ​ក្នុងក្បួនដោះស្រាយយើង​ទេ។ ម៉ាស៊ីនមិនដឹងថាអ្វីជាស្លាកលេខ ១ ឬ ០ទេ​ក្រៅពីអត្ថបទ​ដែល​យើង​ពញ្ចូល។ វាត្រូវតែសន្និដ្ឋាន ⁣អំពីអ្វីដែលជាភាពខុសគ្នា ⁣រវាងអត្ថបទដែលមានស្លាកលេខ ០ និងអត្ថបទដែលមានស្លាកលេខ ១ ។</p><p>ខ្ញុំអាចណែនាំវិធីសាស្រ្តដែលកុំព្យូទ័រអាចដោះស្រាយបញ្ហានេះ។ វាអាចរកឃើញថាអត្ថបទនៃជំពូកទី ១ មានពាក្យ ⁣“ឡាន” ឬ ⁣“ម៉ូតូ” ។ ប៉ុន្តែយើងដឹងថាអត្ថបទមួយចំនួនអំពី ⁣“ការបង្ហាញរថយន្ត” ឬ ⁣“ម៉ូតូសម្រាប់លក់” មិនមែនជាស្លាក ⁣១ទេ។ ដូច្នេះវាចាំបាច់ត្រូវរៀនសម្គាល់ថាអត្ថបទអំពី ⁣“ការបង្ហាញរថយន្ត” ឬ“ ការលក់ម៉ូតូ” ដែល​មាន​ពាក្យ​ ⁣ឡាន ⁣ឬ​ ⁣ម៉ូតូ ⁣មិនមែនជាជំពូកទី ១ ទេ។ វាអាចរកឃើញថាអត្ថបទរបស់ ស្លាកទី ១ មាន​ពាក្យ ⁣“⁣ការស្លាប់” ⁣ឬ “⁣របួស” ⁣ប៉ុន្តែយើងដឹងថា អត្ថបទអំពីអំពើចោរប្លន់ ⁣និងឃាតកម្ម ⁣ជាស្លាកថា ០ ដែល​មិន​ទាក់​ទង​នឹង​ចរាចរណ៍ទេ។ ដូច្នេះវាត្រូវបែងចែកចំណុចទាំងនោះ ⁣ជាស្លាកលេខ ០។ កម្មវិធីក្បួនដោះស្រាយយើង នឹងព្យាយាមរៀនពីលក្ខណៈពិសេស ⁣នៅក្នុងប្រយោគ ⁣មិនគ្រាន់តែមើលពាក្យ ⁣ដូចដែលបាននិយាយខាងលើទេ ⁣ ក្នុងគោលបំណង ⁣ដើម្បី​អាចរក ភាពខុសគ្នា រវាងអត្ថបទនិមួយៗ។</p><p>តាមពិតវិធីសាស្រ្តដែលបានលើកឡើង ដោយគ្រាន់តែមើលពាក្យ គឺជាវិធីសាស្រ្តចាស់មួយ ដែលមានឈ្មោះថា “ថង់ពាក្យ” (bag of words) ដែលកម្មវិធីប្រើ ចំនួនពាក្យនៅក្នុងអត្ថបទនីមួយៗ ដើម្បីធ្វើការបែងចែកប្រភេទឯកសារ។ វិធីសាស្រ្តនេះមិនមានដំណើរការល្អទេ ⁣ព្រោះវាមិនគិតពីលំដាប់លំដោយរបស់ពាក្យ ⁣ឬរចនាសម្ព័ន្ធរបស់​ប្រយោគ ⁣ដែលអាចមានសារៈសំខាន់ ⁣ក្នុងការបែងចែកប្រភេទឯកសារ។</p><p>ដើម្បីបន្តដំណើរការបណ្តុះបណ្តាលរបស់យើង ជំហានដំបូង គឺត្រូវបំបែកអត្ថបទរបស់យើង ទៅជាសំណុំបណ្តុះបណ្តាល (<strong>training set</strong>) និងសំណុំសុពលភាព (<strong>validation set</strong>)។ គោលដៅនៃសំណុំសុពលភាព គឺត្រូវទុកអត្ថបទខ្លះៗដើម្បីកុំឲ្យក្បួនដោះស្រាយដឹង ⁣នៅពេលបណ្តុះបណ្តាល។ សំណុំនេះនឹងត្រូវបានប្រើនៅចុងបញ្ចប់ ⁣ដើម្បីផ្ទៀងផ្ទាត់ ⁣ថាតើក្បួនដោះស្រាយអាចបែងចែកប្រភេទឯកសារបាន​ល្អប៉ុណ្ណា។ យើងបានរក្សាទុកអត្ថបទ ១០ ភាគរយជាសំណុំសុពលភាព។ យើងប្រើអត្ថបទ ៩០% សម្រាប់ការបណ្តុះបណ្តាល ⁣ឯកសារក្នុងចំនួនសរុប ៨២០ អត្ថបទ។ ដូច្នេះចំនួនអត្ថបទសំរាប់ ⁣ការបណ្តុះបណ្តាលមានចំនួន ៧៣៨ និងសំណុំសុពលភាពមានចំនួន ៨២ ។</p><blockquote>សំណុំបណ្តុះបណ្តាល:738<br>សំណុំសុពលភាព: 82<br>ឯកសារសរុប: 820</blockquote><p>នៅជំហានដំបូង កម្មវិធី​យកអត្ថបទ​មកបញ្ចូលហើយព្យាយាម​កែសម្រួល​ទម្ងន់របស់វាដើម្បីធ្វើឱ្យការទាយកាន់តែប្រសើរឡើង។ បន្ទាប់ពីវាបានឆ្លងកាត់គ្រប់ទិន្នន័យបណ្តុះបណ្តាលទាំងអស់ម​ក​ដែល​មានចំនួន ៧៣៨ ចំនួនកំហុស(ការបាត់បង់) លទ្ធផលគឺប្រហែល ០,៧ ឬ ៧០% ដូចដែលបានបង្ហាញក្នុងខ្សែពណ៌ខៀវខាងក្រោម។ ដំណើរការនៃការឆ្លងកាត់សំណុំទិន្នន័យទាំងមូលត្រូវបានគេស្គាល់ថាជាអ៊ីប៉ក់ ⁣(<strong>epoch) ⁣</strong>មួយ។ ក្នុងពេលនេះ ⁣⁣យើងសាកទាយសំណុំសុពលភាពម្ដង​ថា​តើវាមានភាពត្រឹមត្រូវប៉ុណ្ណា។ ⁣យើង​ឃើញថា​វា​បានត្រូវប្រហែល ⁣50% ⁣ដូចតាមបន្ទាត់ក្រហមនៅក្នុងតារាងខាងក្រោម។ លទ្ធិផលនេះ​គី​មិនល្អ​ទេ។ លទ្ធិផលនេះគឺដូចនឹងយើងត្រូវទាយចម្លើយដោយចៃដន្យ។</p><p>ឥឡូវយើងអនុញ្ញាតឱ្យវាឆ្លងកាត់ទិន្នន័យដូចគ្នាម្តងទៀតនិងកែទំងន់របស់វាហើយទទួលបានការបាត់បង់ដូចគ្នាក្នុងរវាង៥ អ៊ីប៉ក់ខាងមុខទៀត។ វាបានទាយ​ត្រូវ ⁣លើសំណុំសុពលភាពប្រហែល 50% ។</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/0*LrON9jyAozkcY1Ad" /></figure><p>បន្ទាប់មក ⁣ដល់អ៊ីប៉ក់ទី ៦ យើងឃើញការទាយបានល្អជាងមុនបន្តិច។ សំណុំសុពលភាព ⁣បង្ហាញអំពីភាពត្រឹមត្រូវប្រហែល 70% ។ នេះល្អប្រសើរជាងមុន ⁣តែមិនទាន់អស្ចារ្យទេ។ បន្ទាប់មកនៅក្នុងអ៊ីប៉ក់ទី៧ ⁣ភាពត្រឹមត្រូវបានកើនឡើងដល់ជាង 90% ។ បន្ទាប់មក ⁣ក្នុងអ៊ីប៉ក់ទាំង ៩ វាឡើងដល់ ៩៩% ។ ⁣មក ⁣ដល់អ៊ីប៉ក់ទី ១៧ វាឈានដល់ ១០០% បន្ទាប់មក ៩៩% នៅលើអ៊ីប៉ក់ក្រោយៗ។ លទ្ធិផលនេះបានល្អ​ជាងកម្មវិធីចាស់ៗរបស់យើង។</p><h3><strong>សេចក្ដីបញ្ចប់</strong></h3><p>នៅក្នុងឆ្នាំ ២០១៨ ក្បួនដោះស្រាយរបស់ BERT បានកើន​លើសសមត្ថភាពរបស់មនុស្ស ⁣ក្នុងបញ្ហាសំណួរនិងចម្លើយ ⁣ក្នុងសំណុំទិន្នន័យ SQuAD១.១ ។ យើងឃើញថា ⁣យើងអាចបង្រៀន​ ⁣BERT ⁣ទុកជាមុន ដោយប្រើអត្ថបទជាភាសាខ្មែរ ⁣ដើម្បីឲ្យវារៀនពី ⁣រចនាសម្ព័ន្ធនៃភាសា។ បន្ទាប់មក ⁣យើងកែរកម្មវិធីដោះស្រាយ ⁣ជាមួយអត្ថបទព័ត៌មាន ⁣ដែលយើងដាក់ស្លាកជាគ្រោះថ្នាក់ចរាចរណ៍ឬអត់។ លទ្ធផលរបស់យើងបង្ហាញថា ⁣កម្មវិធីអាចទាយយ៉ាង⁣ត្រឹមត្រូវ ⁣ថាតើអត្ថបទនេះមានទាក់ទងនឹងគ្រោះថ្នាក់ចរាចរណ៍ឬអត់ ។</p><p>យើងប្រហែលជាមិនដឹងជាក់លាក់ ⁣ពី​របៀបដែលក្បួនដោះស្រាយ ក្នុងការបែងចែក​⁣​អត្ថបទនោះទេ។ ប៉ុន្តែតាមលទ្ធផល យើង​ដឹងថា⁣⁣វាអាចបែងចែកយ៉ាងត្រឹមត្រូវល្អ ⁣បានដល់ ៩៩% ។ វាទាយខុសតែ ១ ឯកសាប៉ុណ្ណោះ ក្នុងចំនួន ១០០ ឯកសា។</p><p>តើនេះមានន័យថាBERT ⁣បានយល់ពីភាសាខ្មែរឬ? ⁣នោះអាស្រ័យលើរបៀប ⁣ដែលអ្នកគិតមើល។ អ្វីដែលយើងបញ្ចូលទៅក្នុងក្បួនដោះស្រាយនេះ ⁣គឺគ្រាន់តែជាលេខយោង ⁣របស់ពាក្យដែលមានក្នុងបញ្ជីវចនានុក្រមរបស់យើងប៉ុណ្ណោះ។ អ្នកអាចនិយាយថា ⁣វាមិនដឹងអ្វីទាំងអស់ពីពាក្យខ្មែរ។ ប៉ុន្តែនៅពេលយើងចិញ្ចូលលេខទាំងនោះជាច្រើន ⁣វាអានរៀនពីទ្រង់ទ្រាយពាក្យខ្មែរនិងលំដាប់របស់វា។ BERT ដឹងពីរចនាសម្ព័ន្ធមួយចំនួន​⁣នៃលេខទាំងនោះ ⁣ដែលត្រូវនឹងពាក្យខ្មែរយើង។ វាដឹងគ្រប់គ្រាន់ ⁣អំពីរចនាសម្ព័នរបស់ពាក្យខ្មែរ ដែលអាចបែងចែកបាន⁣ថាអត្ថបទណាមួយដែលទាក់ទងនិងគ្រោះថ្នាក់ចរាចរណ៍។</p><p>អ្នកអាចមើលកូដនៃវិធីដែលយើងបណ្តុះបណ្តាលក្បួនដោះស្រាយនៅទីនេះជាមួយសំណុំទិន្នន័យផ្សេងទៀតដែលអ្នកអាចពិសោធន៍បាន: <a href="https://github.com/phylypo/khmer-text-data">https://github.com/phylypo/khmer-text-data</a>.</p><h4>កំណត់ចំណាំផ្សេងទៀត</h4><p>យើង​អាចបង្ហាញប្រសើរជាងនេះ ⁣បើក្បួនដោះស្រាយនេះអាចសរសេរអត្ថបទជាភាសាខ្មែរ ⁣ដើម្បីបង្ហាញការយល់ដឹងអំពីភាសា។ ប៉ុន្តែ BERT មិនធ្វើ​សម្រាប់សរសេរអត្ថបទទេ។ ខ្ញុំបានបណ្តុះបណ្តាល ⁣កម្មវិធីៈULMFiT ផ្សេងទៀតដែល ដោយប្រើសំណុំទិន្នន័យ ⁣ស្រដៀងគ្នា ⁣និងអាចសរសេរពាក្យខ្លះបាន។ ដោយផ្តល់⁣ពាក្យមួយចំនួន ⁣វានឹងសរសេរពាក្យពីរបីបន្ទាប់ ⁣ដែលមាន​អត្ថន័យសមស្រប ⁣និងអាច​ត្រឹមត្រូវ​តាមវេយ្យាករណ៍ខ្មែរ ⁣ ដើម្បីបង្ហាញថាវាយល់អំពីភាសា។ សូមមើល​ទំព័រដែលខ្ញុំបានធ្វើពីវិធីនេះ៖ <a href="http://ml.tovnah.com/khmer-ulmfit/">http://ml.tovnah.com/khmer-ulmfit/</a> ។</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/735/0*GBT1MiKk86CiIOUR.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4e9b3e326035" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>