[Natural Language] 텍스트 간 유사점 찾기
[Natural Language] 텍스트 간 유사점 찾기
Swift 언어를 사용해 단어 또는 문장 사이의 의미적 거리를 계산
단어나 문장 간의 의미적 유사성을 찾으면 앱의 사용자 환경을 개선하는 데 도움이 될 수 있음.
예를 들어, 검색어 '구름'이 '하늘'이라는 단어와 관련이 있다는 것을 알고 검색어를 확장하여 더 관련성 높은 결과를 표시함으로써 특정 사진을 검색하는 경험을 개선가능.
자연어 텍스트 사이의 유사점을 찾으려면 텍스트 임베딩을 사용.
임베딩은 단어 또는 문장과 같은 문자열을 벡터 공간에 매핑하는 것으로, 의미적으로 유사한 문자열은 벡터가 유사하므로 벡터 공간에서 서로 더 가까움.
- 즉, 0에 가까울수록 유사함.
임베딩은 다음과 같은 작업에 사용
예를 들어, 검색 쿼리를 확장하기 위해 주어진 용어와 가장 가까운 이웃을 검색
- 의미적 유사성의 척도로서 용어 사이의 거리를 계산
- 벡터를 모델의 입력 레이어로 사용
자연어에서 NLEmbedding은 공간 및 시간 효율적인 형식으로 저장된 임베딩을 나타냄. NLEmbedding은 대량의 일반 텍스트에 대해 학습된 여러 언어에 대해 사전 학습된 단어 임베딩을 제공
(단, 한국어는 현재 지원하지 않음.)
WWDC 23 내용에서 3개의 자연어 그룹으로 묶이는데, 한국은 CJK(중국어 - 일본어 - 한국어) 그룹인데, 이 그룹이 아직 지원되지 않는 것으로 보임.
비슷한 단어 찾기
개별 단어 사이의 거리를 계산하려면 단어 임베딩을 사용합니다.
- 단어 임베딩을 생성할 언어를 지정하여 wordEmbedding(for:)을 사용하여 NLEmbedding의 인스턴스를 생성
- 특정 입력 단어로 임베딩의 vector(for:) 메서드를 호출하면 해당 단어에 대해 생성된 벡터를 확인할 수 있음
- 입력 단어와 다른 단어 사이의 거리를 찾으려면 distance(between:and:distanceType:)를 사용
- 입력 단어와 가장 가까운 이웃을 찾으려면, 살펴볼 최대 이웃 개수를 지정하는 enumerateNeighborsForString:maximumCount:distanceType:usingBlock: 메서드를 호출하여 단어의 이웃을 열거함.
아래는 예제 코드
if let embedding = NLEmbedding.wordEmbedding(for: .english) {
let word = "bicycle"
if let vector = embedding.vector(for: word) {
print(vector)
}
let specificDistance = embedding.distance(between: word, and: "motorcycle")
print("🩵 \(specificDistance.description)")
embedding.enumerateNeighbors(for: word, maximumCount: 5) { neighbor, distance in
print("\(neighbor): \(distance.description)")
return true
}
}
아래 결과를 확인해보자
해당 문자를 영어로 임베딩하여 벡터 기반으로 변경하고, 벡터값 산출
"motorcycle"이란 글자와의 거리를 통해 유사도 분석
아래는 유사도이며, 이웃한 단어와의 거리도 추천해서 알려줌.
아래에 NLDistanceType으로 cosine이 들어가서 1 - [0.0, 2.0] 사이의 값을 가지게 된다.
따라서 위의 배열에서 음수가 나옴
문장 사이의 유사도도 검색할 수 있음.
구문 사이의 거리를 계산하려면 문장 임베딩을 사용. 텍스트 검색과 같은 작업에서 문장 간의 유사성을 측정하거나 의역어를 감지하는 데 사용할 수 있음. 예를 들어 사용자가 "내 주문이 어디에 있나요?"라는 텍스트를 사용하여 음식 배달 앱을 검색하는 경우, 문장 임베딩을 사용하여 "주문 상태를 확인하려면 어떻게 해야 하나요?"라는 유사한 제목의 FAQ 결과를 제안할 수 있음.
- 문장 임베딩을 생성할 언어를 지정하여 sentenceEmbedding(for:)을 사용하여 NLEmbedding의 인스턴스를 생성
- 특정 입력 문장으로 임베딩의 vector(for:) 메서드를 호출하면 해당 문장에 대해 생성된 벡터를 확인할 수 있
- 입력한 문장과 다른 문장 사이의 거리를 찾으려면 distanceBetweenString:andString:distanceType: 을 사용
아래는 샘플 코드다.
if let sentenceEmbedding = NLEmbedding.sentenceEmbedding(for: .english) {
let sentence = "This is a sentence."
if let vector = sentenceEmbedding.vector(for: sentence) {
print(vector)
}
let distance = sentenceEmbedding.distance(between: sentence, and: "That is a sentence.")
print("🥳 \(distance.description)")
}
아래 결과를 보면 유사도가 0에 가깝다.
문장 임베딩은 동적임. 고정된 어휘가 없으며 임의의 문장에 대한 결과를 반환할 수 있음. 따라서 가장 가까운 이웃 검색은 문장 임베딩에 적용되지 않음.
임베딩 지원 여부 확인
NLEmbedding.currentRevision(for: .korean)
- 반환값이 0이면 지원하지 않음, 1이면 지원함.
- 현재 한국어는 지원하지 않음.
학과 검색 프로젝트에서 퍼지 검색 대용으로 사용하고자 했으나, 한국어를 지원하지 않아서 아쉽다.
다만, 영어를 지원하는 서비스의 경우에는 도움이 될 것으로 보임.
(참고)