Main Content

편집 거리 탐색기를 사용하여 사용자 지정 철자 교정 함수 만들기

이 예제에서는 편집 거리 탐색기와 알려진 단어로 구성된 단어집을 사용하여 철자를 교정하는 방법을 보여줍니다.

normalizeWordsword2vec를 사용해 표제어를 추출하려면 철자가 올바로 입력된 단어가 필요합니다. 텍스트의 단어 철자를 손쉽게 교정하려면 correctSpelling 함수를 사용하십시오. 편집 거리 탐색기를 사용해 철자 교정 함수를 처음부터 만드는 방법을 알아보려면 이 예제를 일종의 지침으로 활용하십시오.

텍스트 모음에 단어를 잘못 입력한 경우 편집 거리 탐색기를 사용하여 지정된 단어집에 가장 근접한 올바른 철자의 단어를 찾을 수 있습니다. 문서에서 철자가 잘못된 단어를 교정하려면 해당 단어를 단어집에 있는 최근접이웃으로 바꾸십시오. 편집 거리 탐색기를 사용하여 철자가 잘못된 단어에 가장 근접한 올바른 철자의 단어를 편집 거리에 따라 찾을 수 있습니다. 예를 들어 인접 문자소 바꾸기, 문자소 삽입, 삭제, 치환이 발생하는 횟수를 사용할 수 있습니다.

데이터 불러오기

알려진 단어로 구성된 단어집을 만듭니다. https://sourceforge.net/projects/wordlist/에서 SCOWL(Spell Checking Oriented Word List)을 다운로드하고 현재 디렉터리의 폴더에 압축을 풉니다. 지원 함수 scowlWordList를 사용하여, 다운로드된 데이터에서 단어를 가져옵니다. 다운로드하는 단어 목록의 버전과 일치하도록 폴더 이름을 업데이트합니다.

folderName = "scowl-2020.12.07";
maxSize = 60;
vocabulary = scowlWordList(folderName,"english",maxSize);

단어집에 포함된 단어 개수를 표시합니다.

numWords = numel(vocabulary)
numWords = 98285

간단한 철자 교정기 만들기

가져온 단어집을 사용하여 최대 거리가 2인 편집 거리 탐색기를 만듭니다. 보다 정확한 결과를 위해 SwapCost 옵션을 1로 설정하여 인접 문자소 바꾸기를 허용합니다. 대형 단어집의 경우 이 작업에 몇 분 정도 소요될 수 있습니다.

maxDist = 2;
eds = editDistanceSearcher(vocabulary,maxDist,SwapCost=1);

이 편집 거리 탐색기는 대/소문자를 구분합니다. 즉, 문자의 대/소문자를 변경하면 편집 거리에 영향을 주게 됩니다. 예를 들어, 편집 거리 탐색기는 단어 "tseting"에 대해 이웃 "testing"을 찾을 수 있습니다. 이 단어의 편집 거리가 1(1번 바꾸기)이기 때문입니다. 하지만 단어 "TSeTiNG"은 찾지 못할 수 있습니다. 이 단어의 편집 거리는 6이기 때문입니다.

철자 교정하기

철자가 잘못된 단어를 선택하고 편집 거리 탐색기에서 최근접이웃을 찾는 방법으로, 토큰화된 문서로 구성된 배열에서 철자가 잘못된 단어를 교정할 수 있습니다.

오타와 철자 오류가 있는, 토큰화된 문서 객체를 만듭니다.

str = "An exmaple dccoument with typos and averyunusualword.";
document = tokenizedDocument(str)
document = 
  tokenizedDocument:

   8 tokens: An exmaple dccoument with typos and averyunusualword .

string 함수를 사용하여 문서를 단어로 구성된 string형 배열로 변환합니다.

words = string(document)
words = 1×8 string
    "An"    "exmaple"    "dccoument"    "with"    "typos"    "and"    "averyunusualword"    "."

교정해야 할 단어를 찾습니다. 철자가 올바른 단어를 무시하기 위해 단어집에 이미 있는 단어의 인덱스를 찾습니다. 문장 부호와 복합 토큰(예: 이메일 주소)을 무시하기 위해 토큰 유형이 "letters""other"가 아닌 단어의 인덱스를 찾습니다. tokenDetails 함수를 사용하여 문서에서 토큰 세부 정보를 가져옵니다.

tdetails = tokenDetails(document);
idxVocabularyWords = ismember(tdetails.Token,eds.Vocabulary);

idxComplexTokens = ...
    tdetails.Type ~= "letters" & ...
    tdetails.Type ~= "other";

idxWordsToCheck = ...
    ~idxVocabularyWords & ...
    ~idxComplexTokens
idxWordsToCheck = 8×1 logical array

   1
   1
   1
   0
   0
   0
   1
   0

단어의 숫자형 인덱스를 찾고 해당 단어를 표시합니다.

idxWordsToCheck = find(idxWordsToCheck)
idxWordsToCheck = 4×1

     1
     2
     3
     7

wordsToCheck = words(idxWordsToCheck)
wordsToCheck = 1×4 string
    "An"    "exmaple"    "dccoument"    "averyunusualword"

단어 "An"이 확인해야 할 단어로 플래그가 지정되었음을 알 수 있습니다. 이 단어에 플래그가 지정된 이유는 단어집에 대문자 "A"로 된 단어 "An"이 없기 때문입니다. 대/소문자를 구분하지 않는 철자 교정기를 만드는 방법에 대해서는 이 예제의 뒷부분 섹션에 나와 있습니다.

편집 거리 탐색기와 knnsearch 함수를 사용하여 가장 가까운 단어를 찾고 그 거리를 구합니다.

[idxNearestWords,d] = knnsearch(eds,wordsToCheck)
idxNearestWords = 4×1

         165
        1352
        1151
         NaN

d = 4×1

     1
     1
     2
   Inf

탐색기에서 아무런 단어가 발견되지 않으면 이 함수는 거리 Inf를 갖는 인덱스 NaN을 반환합니다. 단어 "averyunusualword"의 경우 편집 거리 2 내에서 일치 항목이 없기 때문에 이 함수는 이 단어에 대해 인덱스 NaN을 반환합니다.

유한한 양의 편집 거리를 갖는 단어의 인덱스를 찾습니다.

idxMatches = ~isnan(idxNearestWords)
idxMatches = 4×1 logical array

   1
   1
   1
   0

탐색기에서 일치 항목이 있는 단어의 인덱스를 가져오고 단어집에서 그에 해당하는 교정된 단어를 표시합니다.

idxCorrectedWords = idxNearestWords(idxMatches)
idxCorrectedWords = 3×1

         165
        1352
        1151

correctedWords = eds.Vocabulary(idxCorrectedWords)
correctedWords = 1×3 string
    "an"    "example"    "document"

철자가 잘못된 단어 중 일치 항목이 있는 단어를 교정된 단어로 바꿉니다.

idxToCorrect = idxWordsToCheck(idxMatches);
words(idxToCorrect) = correctedWords
words = 1×8 string
    "an"    "example"    "document"    "with"    "typos"    "and"    "averyunusualword"    "."

이들 단어의 토큰화된 문서를 만들기 위해 tokenizedDocument 함수를 사용하고 TokenizedMethod"none"으로 설정합니다.

document = tokenizedDocument(words,TokenizeMethod="none")
document = 
  tokenizedDocument:

   8 tokens: an example document with typos and averyunusualword .

다음 섹션에서는 사용자 지정 철자 교정 함수를 만들고 docfun을 사용하여 여러 문서에서 철자를 한 번에 교정하는 방법을 보여줍니다.

철자 교정 함수 만들기

여러 문서에서 철자를 한 번에 교정하기 위해 이전 섹션의 코드를 기반으로 사용자 지정 함수를 만들고 이 함수를 docfun 함수와 함께 사용합니다.

편집 거리 탐색기, 단어로 구성된 string형 배열 및 해당 토큰 세부 정보 테이블을 입력값으로 받고 교정된 단어를 출력하는 함수를 만듭니다. 예제 끝에 나와 있는 correctSpelling 함수는 해당 토큰 세부 정보와 편집 거리 탐색기를 사용하여 단어로 구성된 string형 배열의 철자를 교정합니다.

이 함수와 함께 docfun 함수를 사용하기 위해 단어로 구성된 string형 배열과 해당 토큰 세부 정보 테이블을 입력값으로 받는 함수 핸들을 만듭니다.

func = @(words,tdetails) correctSpelling(eds,words,tdetails);

docfun과 함수 핸들 func를 사용하여, 토큰화된 문서로 구성된 배열의 철자를 교정합니다.

str = [
    "Here is some reallyu badly wrirten texct."
    "Some moree mitsakes here too."];
documents = tokenizedDocument(str);
updatedDocuments = docfun(func,documents)
updatedDocuments = 
  2×1 tokenizedDocument:

    8 tokens: here is some really badly written text .
    6 tokens: come more mistakes here too .

대문자가 다른 소문자로 교정될 수 있음을 알 수 있습니다. 예를 들어 단어 "Some""come"으로 교정될 수 있습니다. 편집 거리 탐색기 단어집에서 입력값에 대한 편집 거리가 동일한 단어가 여러 개 있는 경우 이 함수는 처음 발견한 결과를 출력합니다. 예를 들어 단어 "come""some" 모두 단어 "Some"과의 편집 거리가 1입니다.

다음 섹션에서는 대/소문자를 구분하지 않는 철자 교정기를 만드는 방법을 보여줍니다.

대/소문자를 구분하지 않는 철자 교정기 만들기

대/소문자의 차이로 인해 다른 단어로의 치환이 충돌되지 않도록 하려면 소문자로 된 단어집을 갖는 편집 거리 탐색기를 만든 후 편집 거리 탐색기를 사용하기 전에 문서를 소문자로 변환하십시오.

단어집을 소문자로 변환합니다. 이 작업을 수행하면 중복 단어가 생길 수 있습니다. 고유한 값만 취하여 중복 단어를 제거합니다.

vocabularyLower = lower(vocabulary);
vocabularyLower = unique(vocabularyLower);

이전과 동일한 옵션을 사용해 소문자 단어집을 사용하는 편집 거리 탐색기를 만듭니다. 이 작업은 실행하는 데 몇 분 정도 소요될 수 있습니다.

maxDist = 2;
eds = editDistanceSearcher(vocabularyLower,maxDist,SwapCost=1);

편집 거리 탐색기를 사용하여, 토큰화된 문서의 단어 철자를 교정합니다. 대/소문자를 구분하지 않는 철자 교정기를 사용하기 위해 문서를 소문자로 변환합니다.

documentsLower = lower(documents);

이전과 동일한 단계로 새 편집 거리 탐색기를 사용하여 철자를 교정합니다.

func = @(words,tdetails) correctSpelling(eds,words,tdetails);
updatedDocuments = docfun(func,documentsLower)
updatedDocuments = 
  2×1 tokenizedDocument:

    8 tokens: here is some really badly written text .
    6 tokens: some more mistakes here too .

여기서 원래 텍스트의 단어 "Some"은 철자 교정기에 입력되기 전에 "some"으로 변환되었습니다. 그에 대응하는 단어 "some"은 단어집에 존재하기 때문에 탐색기의 영향을 받지 않습니다.

철자 교정 함수

correctSpelling 함수는 해당 토큰 세부 정보와 편집 거리 탐색기를 사용하여 단어로 구성된 string형 배열의 철자를 교정합니다. 이 함수를 docfun과 함께 사용하여 여러 문서에서 철자를 한 번에 교정할 수 있습니다.

function words = correctSpelling(eds,words,tdetails)

% Get indices of misspelled words ignoring complex tokens.
idxVocabularyWords = ismember(tdetails.Token,eds.Vocabulary);

idxComplexTokens = ...
    tdetails.Type ~= "letters" & ...
    tdetails.Type ~= "other";

idxWordsToCheck = ...
    ~idxVocabularyWords & ...
    ~idxComplexTokens;

% Convert to numeric indices.
idxWordsToCheck = find(idxWordsToCheck);

% Find nearest words.
wordsToCheck = words(idxWordsToCheck);
idxNearestWords = knnsearch(eds,wordsToCheck);

% Find words with matches.
idxMatches = ~isnan(idxNearestWords);

% Get corrected words.
idxCorrectedWords = idxNearestWords(idxMatches);
correctedWords = eds.Vocabulary(idxCorrectedWords);

% Correct words.
idxToCorrect = idxWordsToCheck(idxMatches);
words(idxToCorrect) = correctedWords;

end

참고 항목

| | | | | |

관련 항목