주로 항목 목록이 포함 된 텍스트 문서가 있습니다.
각 항목은 이름, 성, 생년월일, 전화 번호, 도시, 직업 등 여러 유형의 여러 토큰 그룹입니다. 토큰은 단어 그룹입니다.
항목은 여러 줄에있을 수 있습니다.
문서의 항목은 거의 동일한 토큰 구문을 갖지만 반드시 반드시 동일 할 필요는 없습니다.
그것들은 아이템들 사이뿐만 아니라 아이템들 사이에 더 많거나 적은 토큰 일 수 있습니다.
FirstName LastName BirthDate PhoneNumber
Occupation City
FirstName LastName BirthDate PhoneNumber PhoneNumber
Occupation City
FirstName LastName BirthDate PhoneNumber
Occupation UnrecognizedToken
FirstName LastName PhoneNumber
Occupation City
FirstName LastName BirthDate PhoneNumber
City Occupation
목표는 사용 된 문법을 식별하는 것입니다.
Occupation City
결국 모든 항목을 식별하고 심지어 정확히 일치하지 않는다고 생각했습니다.
짧고 읽기 쉬운 상태를 유지하기 위해 A, B, C, D 등의 별칭을 대신 사용하여 해당 토큰 유형을 지정해 봅시다.
예 :
A B C
D F
A B C
D E F
F
A B C
D E E F
A C B
D E F
A B D C
D E F
A B C
D E F G
여기서 우리는 Item 구문이
A B C
D E F
시퀀스와 가장 일치하는 것이기 때문입니다.
구문 (토큰 유형 및 순서)은 문서마다 크게 다를 수 있습니다. 예를 들어 다른 문서에 해당 목록이있을 수 있습니다.
D A
D A
D
D A
B
D A
목표는 사전 지식없이 해당 구문을 파악하는 것 입니다.
이제부터 새 줄도 토큰으로 간주됩니다. 그런 다음 문서는 1 차원 토큰 시퀀스로 표현 될 수 있습니다.
여기서 반복되는 순서는 A B C B
충돌이 가장 적은 토큰이기 때문입니다.
조금 복잡하게합시다. 지금부터 각 토큰에는 결정된 유형이 없습니다. 현실에서, 우리는 항상 어떤 토큰 유형을 100 % 확신하지는 않습니다. 대신, 우리는 특정 유형을 가질 확률을줍니다.
A 0.2 A 0.0 A 0.1
B 0.5 B 0.5 B 0.9 etc.
C 0.0 C 0.0 C 0.0
D 0.3 D 0.5 D 0.0
다음은 달성하고자하는 추상 그래픽입니다.
A로 간주되는 솔루션 : 토큰 패치의 컨볼 루션
이 솔루션은 여러 패치 패치로 컨볼 루션을 적용하고 충돌이 가장 적은 토큰을 가져옵니다.
여기서 어려운 부분은 관찰 시퀀스를 따라 롤링 할 수있는 패치를 찾는 것입니다. 이것에 대한 몇 가지 아이디어가 있지만 매우 만족스러운 것은 없습니다.
토큰 간 전환에 대한 Markov 모델 구축단점 : Markov 모델에는 메모리가 없으므로 전환 순서를 잃게됩니다. 예를 들어 반복 된 시퀀스가 A B C B D
이면 A-> B가 C-> B보다 먼저 발생한다는 사실을 잃게됩니다.
이것은 DNA / RNA에서 핵 염기 (GTAC)를 분석하기 위해 생물학에서 광범위하게 사용되는 것으로 보인다. 단점 : 접미사 트리는 정확한 토큰 (예 : 문자)을 정확하게 일치시키는 데 좋습니다. 정확한 순서도없고 정확한 토큰도 없습니다.
무차별 대입모든 크기의 모든 조합을 시도하십시오. 실제로 작동 할 수 있지만 시간이 오래 걸릴 수 있습니다.
B로 간주되는 해결책 : Levenshtein의 접미사 거리 표를 작성하십시오.
직관은 모든 접미사에서 모든 접미사까지의 거리를 계산할 때 약간의 로컬 최소 거리가 존재할 수 있다는 것입니다.
거리 함수는 Levenshtein 거리이지만 각 토큰에 대해 고정 된 유형 대신 특정 유형의 확률을 고려하기 위해 미래에이를 사용자 정의 할 수 있습니다.
이 데모에서 간단하게 유지하기 위해 고정형 토큰을 사용하고 클래식 레 벤슈 테인을 사용하여 토큰 간의 거리를 계산합니다.
예를 들어 입력 시퀀스를 보자 ABCGDEFGH ABCDEFGH ABCDNEFGH
.
모든 접미사와 모든 접미사 거리를 계산합니다 (같은 크기로 자른 경우).
for i = 0 to sequence.lengh
for j = i to sequence.lengh
# Create the suffixes
suffixA = sequence.substr(i)
suffixB = sequence.substr(j)
# Make the suffixes the same size
chunkLen = Math.min(suffixA.length, suffixB.length)
suffixA = suffixA.substr(0, chunkLen)
suffixB = suffixB.substr(0, chunkLen)
# Compute the distance
distance[i][j] = LevenshteinDistance(suffixA, suffixB)
예를 들어 다음과 같은 결과를 얻습니다 (흰색은 작은 거리, 검은 색은 큰).
이제 그 자체에 비해 접미사가 널 거리를 갖는 것이 분명합니다. 그러나 접미사 자체 (정확하거나 부분적으로)에 관심이 없으므로 해당 부분을 자릅니다.
접미사를 같은 크기로 자르기 때문에 긴 줄을 비교하면 작은 줄을 비교하는 것보다 항상 더 큰 거리가 생성됩니다.
오른쪽 (+ P)에서 시작하여 왼쪽으로 선형으로 페이드 아웃하는 부드러운 페널티로이를 보상해야합니다.
모든 경우에 적합한 우수한 페널티 기능을 선택하는 방법을 아직 잘 모르겠습니다.
여기서 우리는 맨 오른쪽에 (+ P = 6) 페널티를 적용하고 왼쪽으로 0으로 페이드 아웃합니다.
이제 우리는 분명한 대각선 2 개가 나오는 것을 볼 수 있습니다. 이 순서에는 3 개의 항목 (Item1, Item2, Item3)이 있습니다. 가장 긴 줄은 Item1과 Item2 및 Item2와 Item3 간의 일치를 나타냅니다. 두 번째로 긴 것은 Item1과 Item3 간의 일치를 나타냅니다.
이제 해당 데이터를 활용하는 가장 좋은 방법은 확실하지 않습니다. 가장 높은 대각선을 취하는 것만 큼 간단합니까?
그것이 있다고 가정 해 봅시다.
각 토큰에서 시작하는 대각선의 평균값을 계산해 봅시다. 다음 그림에서 결과를 볼 수 있습니다 (행렬 아래의 벡터).
각 항목의 시작 부분과 일치하는 3 개의 로컬 최소값이 있습니다. 환상적으로 보입니다!
이제 시퀀스에 결함을 더 추가해 봅시다.
ABCGDEFGH ABCDEFGH TROLL ABCDEFGH
분명히, 우리의 대각선 평균 벡터가 엉망이되어 더 이상 그것을 이용할 수 없습니다 ...
내 가정은 전체 블록의 삽입이 그다지 불이익을받지 않을 수있는 맞춤형 거리 기능 (Levenshtein 대신)으로 해결할 수 있다고 가정합니다. 그것이 내가 확실하지 않은 것입니다.
결론
탐색 된 컨볼 루션 기반 솔루션 중 어느 것도 우리의 문제에 맞지 않는 것 같습니다.
Levenshtein-distance-based-distance-based 솔루션은 특히 확률 기반 유형 토큰과 호환되므로 유망한 것으로 보입니다. 그러나 결과를 악용하는 방법에 대해서는 아직 확실하지 않습니다.
관련 분야에서 경험을 쌓았거나 우리에게 알려주는 몇 가지 좋은 힌트 또는 다른 기술을 살펴보면 매우 감사하겠습니다. 대단히 감사합니다.