마르코프 분석으로 문장을 만들다

이번에는 마르코프 분석을 이용해 문장을 만드는 데 도전해 보았다.실시해야 하기 때문에 일정한 프로그래밍 언어의 경험이 필요하다.
마르코프 프로세스와 마르코프 체인
마르코프 과정은 러시아 수학자 안드레 마르코프(1856~1922)가 설계한 확률 과정이다.앞으로 일어날 사건의 확률은 현재 상태에만 의존하고 과거 상태에는 전혀 의존하지 않는다는 내용이다.(숫자대사천'마르코프 과정'참조).
또 마르코프 과정에서 미래 상태를 결정하는 모델을 마르코프 체인이라고 부른다.
문장의 마르코프 분석
개요
마르코프 연쇄로 영어 문장(이하 마르코프 분석이라고 부른다)을 분석할 때의 모델의 한 예를 들어 보자.

보시다시피 위의 그림은 단어나 기호를 노드로 하는 유방향도입니다.이 도표에서 각 노드는 상태를 표시하고 한 노드에서 다른 노드로의 가장자리를 무작위로 선택할 때 현재 노드의 상태에만 의존하며 과거 노드의 상태에 의존하지 않는다.
실제로 위 도표의 가장자리 입력 순서가 0인 노드("I", "You", "He", "She", "Mike") 중 어느 하나부터 터미널의 노드(".")가 된다.화살표에 따라 랜덤으로 노드를 이동해 통과한 노드에 적힌 단어를 순서대로 배열하면 올바른 글이 된다는 것을 알 수 있다.
이 논리를 사용하면 문법적으로 정확한 문장을 만들 수 있을 것이다.
이루어지다
이번에는 위의 예와 같이 단어를 노드로 하는 유방향 도표를 이용하여 해석한다.구체적으로 Value가 Set(Pythn3에서 set)인 HashMap(Pythn3에서 dict)을 사용하여 도표를 나타낸다.(Set에 저장된 단어는 다음 단어군으로 이동할 수 있음)
언어는 Pythhon3을 사용하여 설치됩니다.그러나 특별한 라이브러리를 사용하지 않고 원시 요소만 활용하기 위해서는 다른 언어를 사용해도 쉽게 실현할 수 있다.
또한 차트 구축을 위한 데이터 그룹으로서 불가사의한 나라의 앨리스(Project Gunterberg에서 온 Alice's Adventeures in Wonderland by Lewis Carollhttps://www.gutenberg.org/ebooks/11, 셜록 홈즈(Project Guteenberg에서 온 The Adventeurs of Sherlock Holmes by Arthur Conan Doylehttps://www.gutenberg.org/ebooks/1661를 활용할 수 있도록 허락해 주십시오.각 파일은 프로그램이 설정된 디렉터리와 같은 디렉터리에 "alice.txt", "sherlock.txt"같은 파일 이름으로 설정됩니다.
설치는 다음과 같습니다.
import re
import random
import os

class MarkovModel:
    # Delimiters
    SPLIT_CHARS = "\n\s\t\r\f"
    # Strip characters
    STRIP_CHARS = "\"'()[]{}"
    # End of sentences
    EOS_CHARS = ".!?"
    # Symbols to recognize as a word
    SYMBOL_CHARS = ",;:" + EOS_CHARS

    __model = dict()

    def construct(self, filename):
        """
        Construct a model from the specified dataset.
        """
        words = self.__read_words(filename)
        self.__add_words(words)

    def __read_words(self, filename):
        """
        Returns a word list from a file with the specified path.
        """
        buf = ""
        with open(filename, encoding="ascii", errors="ignore") as istream:
            buf = istream.read()
        return self.__extract_words(buf)

    def __extract_words(self, buf):
        """
        Extracts words from the specified string and returns them as a list.
        """
        chunks = re.split(f"[{self.SPLIT_CHARS}]", buf)
        words = list()
        for chunk in chunks:
            chunk = chunk.strip(self.STRIP_CHARS).lower()
            if len(chunk) > 0 and chunk[-1] in self.SYMBOL_CHARS:
                words.append(chunk[:-1])
                words.append(chunk[-1])
            else:
                words.append(chunk)
        words = filter(lambda word: len(word) > 0, words)
        return list(words)

    def __add_words(self, words):
        """
        Add the specified word list to the model.
        """
        for i in range(len(words) - 1):
            if not words[i] in self.EOS_CHARS:
                self.__add_word(words[i], words[i + 1])

    def __add_word(self, key, word):
        """
        Connect 'key' and 'word' with an edge extending from 'key'.
        """
        if key in self.__model:
            self.__model[key].append(word)
        else:
            self.__model[key] = [word]

    def clear(self):
        """
        Clear the model.
        """
        self.__model.clear()

    def generate_sentence_at_random(self, current_word):
        """
        Randomly generate sentence with 'current_word' as first word.
        """
        current_word = current_word.lower()
        words = list()
        while current_word in self.__model:
            words.append(current_word)
            current_word = random.choice(list(self.__model[current_word]))
        words.append(current_word)
        return ' '.join(words)

    def __str__(self):
        """
        For debugging.
        """
        chunks = list()
        for k, v in self.__model.items():
            chunks.append(f"{k}:[{','.join(v)}]")
        return os.linesep.join(chunks)

if __name__ == "__main__":
    model = MarkovModel()
    model.construct('alice.txt')
    model.construct('sherlock.txt')
    for i in range(6):
        print(model.generate_sentence_at_random('i'))
자세한 내용은 절차를 읽고 이해해 주십시오.실행하기 시작하면 다음과 같은 여섯 편의 문장이 있다.
i beg that you mean , heres another question the cat .
i must have asked him credit card donations to france , what i should or not a small streets which lined with the work appears from grosvenor square which i shall certainly speak severely tried to reason for this mean that no one crazy !
i see no doubt of the official detective in in one side of making such as well !
i felt quite forgot that i think i turned with cotton wadding and good-night .
i saw the duchess , too , you scoundrel .
i shall be connected with extras ?
이 결과는 무작위로 변화하는 것이기 때문에 반드시 위의 결과가 되는 것은 아니지만 어떤 문장을 출력하든지 문법에 초점을 맞추면 정확하다는 것을 알 수 있을 것이다.
의미의 부분은 어때요?위의 출력은 Google 번역https://translate.google.co.jp/?hl=ja으로 일본어를 번역해 보았고 다음 글이 돌아왔습니다.
私はあなたが意味することをお願いします、ここに猫の別の質問があります。
私は彼にフランスへのクレジットカードの寄付を頼んだに違いありません、私がすべきかどうかは、作品が並ぶ小さな通りがグロブナースクエアから現れます。
作り方の片側にもオフィシャル探偵に疑いの余地はありません!
綿の詰め物とおやすみで向きを変えたと思うのをかなり忘れてしまいました。
私も公爵夫人を見ました、あなたは悪党です。
私はエクストラと接続しますか?
뜻이 분명하지 않다.이번에 쓴 해석 프로그램은 단어 간의 관계만 분석할 수 있기 때문에 의미와 관련된 설익은 글을 충분히 만들 수 있다.그러나 문장을 반복적으로 만들면 문법이 정확하고 뜻이 매끄러운 문장이 만들어진다는 것도 희한하지 않다.
최후
이번에는 마르코프 분석으로 간단한 영어 문장을 만들어 보았다.물론 마르코프 분석은 문장의 분석뿐만 아니라 다른 광범위한 분야에도 응용될 수 있다.또 이 알고리즘을 확장하면 더욱 높은 정밀도를 가진 글을 만들 수 있다.나는 이렇게 간단하고 확장성도 높으며 매우 재미있는 알고리즘이라고 생각한다.앞으로 생성된 문장의 정밀도를 높이는 데 도전해 다른 분야에서 이 알고리즘을 응용해 보고 싶습니다.
나는 마지막으로 여기까지 읽은 독자들에게 감사를 표하고 이 보도를 닫고 싶다.
참고 자료
・ThinkPythhon: How to Think Like a Computer Scientist(제2판 Edition) 일본어 번역
  https://cauldron.sakura.ne.jp/thinkpython/

좋은 웹페이지 즐겨찾기