PythonでTextBlobを使ったスペルチェッカー

スペルミスはよくあることで、多くの人はソフトウェアにミスがないかどうかを表示させることに慣れています。携帯電話のオートコレクトからテキストエディタの赤い下線まで、スペルチェックは様々な製品に不可欠な機能である。

スペルチェックを実装した最初のプログラムは、1971年にDEC PDP-10向けに書かれました。SPELL」と呼ばれたこのプログラムは、単語の簡単な比較と1文字か2文字の違いのみを検出するものだった。ハードウェアとソフトウェアの進歩に伴い、スペルチェッカーも進歩した。最近のスペルチェッカーは形態素を扱うことができ、統計を使って候補を改善することができます。

Pythonはこの目的のために多くのモジュールを提供しており、簡単なスペルチェッカーを書くのに20分程度の試練を与えてくれます。

TextBlobは自然言語処理に使われるライブラリで、直感的に操作できるAPIを提供しています。

今回は、PythonでTextBlobを使ってスペルチェッカーを実装する方法を紹介します。

インストール

まず、TextBlobはプリインストールされていないので、インストールする必要があります。コンソールを開き、pipでインストールします。

$ pip install textblob


これで、このプロジェクトに必要なものがすべてインストールされるはずです。インストールが終わると、コンソールに次のような出力が表示されるはずです。

Successfully installed click-7.1.2 joblib-0.17.0 nltk-3.5 regex-2020.11.13 textblob-0.15.3


TextBlobはNLTKの上に構築されているので、インストール時に一緒に提供されます。

correct()関数

入力されたテキストを修正する最も簡単な方法は、correct() メソッドを使用することです。今回使用するテキストは、Charles Darwin の “On the Origin of Species” の一節で、パブリックドメインとして text.txt というファイルに格納されています。

さらに、意図的なスペルミスを追加します。

As far as I am abl to judg, after long attnding to the sbject, the condiions of lfe apear to act in two ways—directly on the whle organsaton or on certin parts alne and indirectly by afcting the reproducte sstem. Wit respct to te dirct action, we mst bea in mid tht in every cse, as Profesor Weismann hs latly insistd, and as I have inidently shwn in my wrk on "Variatin undr Domesticcation," thcere arae two factrs: namly, the natre of the orgnism and the natture of the condiions. The frmer sems to be much th mre importannt; foor nealy siimilar variations sometimes aris under, as far as we cn juddge, disimilar conditios; annd, on te oter hannd, disssimilar variatioons arise undder conditions which aappear to be nnearly uniiform. The efffects on tthe offspring arre ieither definnite or in definite. They maay be considdered as definnite whhen allc or neearly all thhe ofefspring off inadividuals exnposed tco ceertain conditionas duriing seveal ggenerations aree moodified in te saame maner.


ほとんどすべての単語がスペルミスに満ちている。TextBlobを使って、これらの誤りを訂正してコンソールに出力する簡単なスクリプトを書いてみましょう。

from textblob import TextBlob


with open("text.txt", "r") as f:        # Opening the test file with the intention to read
    text = f.read()                     # Reading the file
    textBlb = TextBlob(text)            # Making our first textblob
    textCorrected = textBlb.correct()   # Correcting the text
    print(textCorrected)


TextBlobを使ったことがある人なら、この流れは見慣れたものでしょう。ファイルとその中のコンテンツを読み込んで、コンストラクタにコンテンツを渡して TextBlob インスタンスを構築しています。

そして、そのインスタンスに対して correct() 関数を実行し、スペルチェックを行なっています。

上記のスクリプトを実行すると、次のような出力が得られるはずです。

Is far as I am all to judge, after long attending to the subject, the conditions of life appear to act in two ways—directly on the while organisation or on certain parts alone and indirectly by acting the reproduce system. It respect to te direct action, we must be in mid the in every case, as Professor Weismann he lately insisted, and as I have evidently shown in my work on "Variation under Domesticcation," there are two facts: namely, the nature of the organism and the nature of the conditions. The former seems to be much th are important; for nearly similar variations sometimes arms under, as far as we in judge, similar condition; and, on te other hand, disssimilar variations arise under conditions which appear to be nearly uniform. The effects on the offspring are either definite or in definite. They may be considered as definite when all or nearly all the offspring off individuals exposed to certain conditions during several generations are modified in te same manner.


TextBlobのスペルチェックはどの程度正しいのでしょうか?

見ての通り、このテキストにはまだスペルミスがあります。abl”のような単語は、"all"ではなく、”able”`であるべきでした。しかし、これらを差し引いても、原文よりはましです。

さて、問題はどの程度良くなったかです。

&gt

以下のコードスニペットは、TextBlobがどの程度エラー訂正に優れているかを、この例に基づいてテストする簡単なスクリプトです。

from textblob import TextBlob


# A function that compares two texts and returns 
# the number of matches and differences
def compare(text1, text2):  
    l1 = text1.split()
    l2 = text2.split()
    good = 0
    bad = 0
    for i in range(0, len(l1)):
        if l1[i] != l2[i]:
            bad += 1
        else:
            good += 1
    return (good, bad)


# Helper function to calculate the percentage of misspelled words
def percentageOfBad(x):
    return (x[1] / (x[0] + x[1])) * 100


では、この2つの関数を使って、簡単な分析をしてみましょう。

with open("test.txt", "r") as f1: # test.txt contains the same typo-filled text from the last example 
    t1 = f1.read()


with open("original.txt", "r") as f2: # original.txt contains the text from the actual book 
    t2 = f2.read()


t3 = TextBlob(t1).correct()


mistakesCompOriginal = compare(t1, t2)
originalCompCorrected = compare(t2, t3)
mistakesCompCorrected = compare(t1, t3)


print("Mistakes compared to original ", mistakesCompOriginal)
print("Original compared to corrected ", originalCompCorrected)
print("Mistakes compared to corrected ", mistakesCompCorrected, "
")


print("Percentage of mistakes in the test: ", percentageOfBad(mistakesCompOriginal), "%")
print("Percentage of mistakes in the corrected: ", percentageOfBad(originalCompCorrected), "%")
print("Percentage of fixed mistakes: ", percentageOfBad(mistakesCompCorrected), "%", "
")


実行すると、以下のように出力されます。

Mistakes compared to original  (126, 194)
Original compared to corrected  (269, 51)
Mistakes compared to corrected  (145, 175)


Percentage of mistakes in the test:  60.62499999999999 %
Percentage of mistakes in the corrected:  15.937499999999998 %
Percentage of fixed mistakes:  54.6875 %


見てわかるように、correctメソッドはスペルミスの割合を60.6%から15.9%に減らすことができました。54.7%の単語を修正したのに、なぜ15.9%も間違いがあるのでしょうか?

答えは、「過修正」です。例えば、例文の最初の単語「”As”」が「"Is"」に修正されたように、正しいスペルの単語が変更されることがあります。また、単語と文脈に関する十分な情報を持っていないために、ユーザがどの単語を入力しようとしたのかを判断できず、「”whole”」ではなく「"while"」に置き換えるべきと判断してしまうこともあります。

話し言葉の多くは文脈に左右されるため、完璧なスペルチェックは存在しないことを念頭に置いてください。ほとんどの場合、この例ほど間違いはないでしょうから、TextBlobは一般的なユーザーにとって十分な機能を備えていると思います。

カスタムデータセットによるTextBlobの学習

TextBlobが対応していない言語のスペルチェックをしたい場合、どうすればいいでしょうか?あるいは、もう少し精度を上げたい?そんなとき、こんな方法があります。それはTextBlobのスペルチェックの仕組みによります。

TextBlobは英語の単語使用量の統計を使って、どの単語を修正すべきか賢く提案します。この統計は en-spelling.txt というファイルに保存されますが、自分で単語使用量の統計ファイルを作ることもできます。

では、Darwinの例で作ってみましょう。ここでは、「種の起源」に出てくるすべての単語を学習用に使います。どのようなテキストを使ってもかまいませんが、修正したいテキストに関連する単語が十分に含まれていることを確認してください。

この場合、この本の残りの部分は、TextBlobがより正確に修正するために必要な、すばらしい文脈や追加情報を提供してくれることでしょう。

スクリプトを書き換えてみましょう。

from textblob.en import Spelling        
import re


textToLower = ""


with open("originOfSpecies.txt","r") as f1:           # Open our source file
    text = f1.read()                                  # Read the file                 
    textToLower = text.lower()                        # Lower all the capital letters


words = re.findall("[a-z]+", textToLower)             # Find all the words and place them into a list    
oneString = " ".join(words)                           # Join them into one string


pathToFile = "train.txt"                              # The path we want to store our stats file at
spelling = Spelling(path = pathToFile)                # Connect the path to the Spelling object
spelling.train(oneString, pathToFile)                 # Train


train.txt`ファイルを覗いてみると

a 3389
abdomen 3
aberrant 9
aberration 5
abhorrent 1
abilities 1
ability 4
abjectly 1
able 54
ably 5
abnormal 17
abnormally 2
abodes 2
...


これは、"a"という単語が3389回出現し、"ably"という単語は5回しか出現していないことを示している。この学習済みモデルをテストするために、correct(text)の代わりに suggest(text) を使ってみましょう。このモデルは単語の信頼度を表すタプルのリストです。このリストの最初の要素が最も自信のある単語になるので、 suggest(text)[0][0] を使ってアクセスすることができます。

大量のデータをダンプするとクラッシュする可能性があるので、スペルチェックをしながら単語単位で行ってください。

from textblob.en import Spelling        
from textblob import TextBlob


pathToFile = "train.txt" 
spelling = Spelling(path = pathToFile)
text = " "


with open("test.txt", "r") as f: 
    text = f.read()


words = text.split()
corrected = " "
for i in words :
    corrected = corrected +" "+ spelling.suggest(i)[0][0] # Spell checking word by word


print(corrected)


そして、今度は、この結果

As far as I am all to judge after long attending to the subject the conditions of life appear to act in two ways—directly on the whole organisation or on certain parts alone and indirectly by acting the reproduce system It respect to the direct action we most be in mid the in every case as Professor Weismann as lately insisted and as I have incidently shown in my work on "Variatin under Domesticcation," there are two facts namely the nature of the organism and the nature of the conditions The former seems to be much th are important for nearly similar variations sometimes arise under as far as we in judge dissimilar conditions and on the other hand dissimilar variations arise under conditions which appear to be nearly uniform The effects on the offspring are either definite or in definite They may be considered as definite when all or nearly all the offspring off individuals exposed to certain conditions during several generations are modified in the same manner.


これでスペルミスの3つのうち2つは修正されました。

結論

この記事では、TextBlobを使って基本的なスペルチェック機能を実装してみました。

人為的なスペルミスを修正することは、ソフトウェア開発者にとって一般的なタスクになっています。データマイニングによってより簡単に、より効率的になったとはいえ、多くのスペルミスは修正するために文脈が必要です。

結論として、校正者がすぐに自動化されることはないだろうが、いくつかの基本的な修正は自動化することで時間と労力を節約することができる。

タイトルとURLをコピーしました