GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

jsvine

markovify – シンプルで拡張可能なマルコフチェーンジェネレータ

投稿日:

シンプルで拡張可能なマルコフチェーンジェネレータ。

Markovify

Markovifyは、シンプルで拡張可能なマルコフチェーンジェネレータです。 現在、主な用途は、テキストの大量コーパスのマルコフモデルを構築し、そこからランダムな文を生成することです。 しかし、理論的には、 他のアプリケーションにも使用できます

なぜMarkovifyですか?

いくつかの理由:

  • シンプルさ。 「電池は付属していますが、重要な方法を無効にするのは簡単です。

  • モデルはJSONとして保存することができ、結果をキャッシュして後で保存することができます。

  • テキスト解析と文生成メソッドは非常に拡張性が高く、独自のルールを設定することができます。

  • 純粋なPythonライブラリのみに依存し、それらのライブラリはほとんどありません。

  • Python 2.7,3.4,3.5、および3.6でテストされています。

インストール

pip install markovify

基本的な使用法

import markovify

# Get raw text as string.
with open("/path/to/my/corpus.txt") as f:
    text = f.read()

# Build the model.
text_model = markovify.Text(text)

# Print five randomly-generated sentences
for i in range(5):
    print(text_model.make_sentence())

# Print three randomly-generated sentences of no more than 140 characters
for i in range(3):
    print(text_model.make_short_sentence(140))

ノート:

  • ここでの使用例は、テキストをマークアップしようとしていると仮定しています。 テキスト固有のmarkovify.Chainクラスを使用する場合は、(注釈付きの)ソースコードをチェックしください。

  • Markovifyは、大きな、句読点付きのテキストで最も効果的です。 あなたのテキストが使用しない場合. それぞれの文を改行し、 markovify.NewlineTextクラスの代わりにmarkovify.Textクラスを使用します。

  • 間違って1つの長い文章としてテキストを読むと、markovifyは開始区切りと終了区切りがないため、新しい文を生成できなくなります。 これは、 markovify.Text代わりにmarkovify.NewlineTextコマンドを使用して改行で区切られたファイルを読み込んだ場合に発生します。 これを確認するには、 [key for key in txt.chain.model.keys() if "___BEGIN__" in key]コマンドの[key for key in txt.chain.model.keys() if "___BEGIN__" in key]コマンドで[key for key in txt.chain.model.keys() if "___BEGIN__" in key]コマンドを実行すると、可能なすべての文頭の単語が返され、複数の結果が返されます。

  • デフォルトでは、 make_sentenceメソッドは、呼び出しごとに最大10回試行して、元のテキストとあまり重複しない文を作成します。 成功した場合、メソッドは文を文字列として返します。 そうでない場合は、 None返します。 試行回数を増減するには、キーワード.make_sentence(tries=100)呼び出すなどのキーワード試行回数を使用します。

  • デフォルトでは、 markovify.Textは元のテキストのチャンクを単純にmarkovify.Textさせない文を生成しようとします。 デフォルトの規則は、元のテキストと15単語または文の単語数の70%が正確に重なる生成されたすべての文を抑制することです。 このルールを変更するには、 max_overlap_ratioおよび/またはmax_overlap_totalmake_sentenceメソッドにmake_sentenceます。 あるいは、 test_outputをFalseとして渡すことで、このチェックを完全に無効にすることもできます。

高度な使用法

モデルの状態サイズを指定する

デフォルトでは、 markovify.Textは2の状態サイズを使用しますが、異なる状態サイズのモデルをインスタンス化できます。 例えば、:

text_model = markovify.Text(text, state_size=3)

モデルの結合

markovify.combine(...)を使用すると、2つ以上のマルコフ連鎖を組み合わせることができます。 この関数は2つの引数を受け取ります。

  • models :結合するmarkovifyオブジェクトのリスト。 markovify.Chainまたはmarkovify.Text (またはそのサブクラス)のインスタンスになることができますが、すべて同じ型でなければなりません。
  • weights :オプション。 intまたはfloatのリスト( modelsの正確な長さ) – 各ソースにどれだけ相対的な強調を置くべきかを示します。 デフォルト: [ 1, 1, ... ]

例えば:

model_a = markovify.Text(text_a)
model_b = markovify.Text(text_b)

model_combo = markovify.combine([ model_a, model_b ], [ 1.5, 1 ])

model_amodel_bを結合しますが、 model_aからの接続の重みを50% model_aます。

markovify.Text拡張

markovify.Textクラスは高度に拡張可能です。 ほとんどのメソッドはオーバーライドできます。 たとえば、次のPOSifiedTextクラスでは、NLTKの品詞タグを使用して、ナイーブモデルよりも優れた文章構造に従うマルコフモデルを生成します。 (動作しますが、警告: pos_tagは非常に遅いです。)

import markovify
import nltk
import re

class POSifiedText(markovify.Text):
    def word_split(self, sentence):
        words = re.split(self.word_split_pattern, sentence)
        words = [ "::".join(tag) for tag in nltk.pos_tag(words) ]
        return words

    def word_join(self, words):
        sentence = " ".join(word.split("::")[0] for word in words)
        return sentence

または、 より高速な spaCyを使用することもできます。

import markovify
import re
import spacy

nlp = spacy.load("en")

class POSifiedText(markovify.Text):
    def word_split(self, sentence):
        return ["::".join((word.orth_, word.pos_)) for word in nlp(sentence)]

    def word_join(self, words):
        sentence = " ".join(word.split("::")[0] for word in words)
        return sentence

上書きできる最も有用なmarkovify.Textモデルは次のとおりです。

  • sentence_split
  • sentence_join
  • word_split
  • word_join
  • test_sentence_input
  • test_sentence_output

彼らが何をするかの詳細については、(注釈付きの)ソースコードを参照してください。

エクスポート

大きなコーパスからマルコフモデルを生成するには、しばらく時間がかかります。 場合によっては、一度生成して後で再利用したい場合もあります。 生成されたmarkovify.Textモデルをエクスポートするには、 my_text_model.to_json()使用します。 例えば:

corpus = open("sherlock.txt").read()

text_model = markovify.Text(corpus, state_size=3)
model_json = text_model.to_json()
# In theory, here you'd save the JSON to disk, and then read it back later.

reconstituted_model = markovify.Text.from_json(model_json)
reconstituted_model.make_short_sentence(140)

>>> 'It cost me something in foolscap, and I had no idea that he was a man of evil reputation among women.'

my_text_model.chain.to_json()を使用して、元のコーパスとstate_sizeメタデータを除いて、独自のマルコフチェーンを独自にエクスポートすることもできます。

非常に大きなコーパスからmarkovify.Textモデルを生成する

デフォルトでは、 markovify.Textクラスは、生成された文と元の文を比較できるように、テキストコーパスをロードして保持します( markovify.Textのみを出力します)。 しかし、非常に大規模なコーパスでは、テキスト全体を一度にロードする(および保持する)ことは、メモリを大量に消費する可能性があります。 これを克服するには、 (a) Markovifyにオリジナルを保持しないように伝える:

with open("path/to/my/huge/corpus.txt") as f:
    text_model = markovify.Text(f, retain_original=False)

print(text_model.make_sentence())

そして、 (b)コーパスをラインごとにまたはファイルごとに読み込み、各ステップで1つのモデルに結合する。

combined_model = None
for (dirpath, _, filenames) in os.walk("path/to/my/huge/corpus"):
    for filename in filenames:
        with open(os.path.join(dirpath, filename)) as f:
            model = markovify.Text(f, retain_original=False)
            if combined_model:
                combined_model = markovify.combine(models=[combined_model, model])
            else:
                combined_model = model

print(combined_model.make_sentence())

ワイルド・イン・ザ・マルコビフ

他の例がありますか? プルの要求は大歓迎です。

ありがとう

コードやアイデアを寄稿してくださったGitHubユーザに感謝します。

当初はBuzzFeedで開発されました。







-jsvine

執筆者: