편집 거리 탐색기를 사용하여 사용자 지정 철자 교정 함수 만들기
이 예제에서는 편집 거리 탐색기와 알려진 단어로 구성된 단어집을 사용하여 철자를 교정하는 방법을 보여줍니다.
normalizeWords
와 word2vec
를 사용해 표제어를 추출하려면 철자가 올바로 입력된 단어가 필요합니다. 텍스트의 단어 철자를 손쉽게 교정하려면 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
참고 항목
correctSpelling
| editDistanceSearcher
| editDistance
| tokenizedDocument
| tokenDetails
| knnsearch
| docfun