2017-11-30 15 views
0

나는 각 토큰이 (document_id, score) 쌍의 목록에 매핑되는 역 색인을 가지고 있습니다. 각 토큰의 값 목록은 내림차순 점수로 정렬되므로 가장 높은 순위의 문서가 먼저옵니다.역 색인에서 순서가 다른 값 배열의 교차점을 찾기위한 좋은 데이터 구조가 있습니까?

불행히도, 문서에서 토큰의 컨텍스트를 기준으로 점수가 조정되므로 모든 토큰에 대해 sorted-by-id가 동시에 정렬되도록 보장하는 것은 불가능합니다. 예를 들어 내 "문서"가 (id, score) = (1, 105)이고 "적포도주"가 (id, score) = (2, 100) 인 문자열 인 "와인 레드 아이폰"인 경우 "레드 와인"은 "레드"와 "와인"이 동일하지만 "와인은 <"빨간색 반전 인덱스 내가 ID를이 목록의 교차점을 찾을 필요가

"red" -> [(2, 100), (1, 95)] 
"wine" -> [(1, 105), (2, 100)] 
"iPhone" -> [(1, 115)] 

처럼 보이도록 점수가 조절 될 수 있도록 와인 레드 아이폰 '의 중요성 ","< "아이폰"하는을 반환 모든 토큰 집합을 포함하는 문서 ID의 순위 목록 (표준 검색 문제). 위의 예에서 ID로 다른 문서 "화이트 와인은"이 가정 = 3, 점수 = 50, 그래서 역 색인은 이제 다음과 같습니다 : 검색 토큰이 {"red", "wine"} 경우,

"red" -> [(2, 100), (1, 95)] 
"wine" -> [(1, 105), (2, 100), (3, 50)] 
"white" -> [(3, 50)] 
"iPhone" -> [(1, 115)] 

그런 문제를 기본적으로 두 개의 토큰 (이 경우 [(2, 100), (1, 95)][(1, 105), (2, 100), (3, 50)])의 값을 가져 와서 문서 ID에 교차하므로 결과는 [(2, f(100, 100)), (1, f(95, 105))]입니다. f은 일부 평균 기능이며 중요하지 않습니다.

빠른 속도가 필요하고 가능한 한 적은 메모리를 사용해야합니다 (그러나 디스크 공간에는 문제가 없습니다). 경우에 따라 수천만 개의 고유 한 문서 ID에 매핑되는 수백만 개의 고유 한 토큰을 저장합니다.

지금까지 제약 조건을 충족시키기 위해 메모리의 압축을 위해 키 값 저장소 (각각 (id, score) 쌍이 하나의 값임)로 수정 된 trie에 데이터를 저장하는 작업을 망쳤습니다. inverted_index.get(token)은 배열을 반복하고 id -> score의 해시 맵을 반환하며 get은 해시 맵을 인수로 취하여 배열을 반복하고 다음 맵을 어셈블하는 동안 교차가 완료되도록 할 수 있습니다. 목록을 기본 목록과 대체 목록, 직렬화/직렬화 해제, 나머지는 ㅋ 그것들은 더 큰 문제를 해결하지 못하는 모든 일종의 반창고입니다. 문제에 대해 올바른 데이터 구조와 알고리즘을 사용하지 않고 있습니다. 현재 가장 큰 유스 케이스는 약 20m의 고유 한 문서 ID를 가지며 메모리에 완전히로드 될 때 약 400MB를 차지합니다.

내 애플리케이션에서 성능상의 가장 큰 병목 현상입니다. 특히 토큰 집합에 매우 많은 값이 포함 된 토큰이 포함되어있는 경우에 특히 그렇습니다. 필자는 기존 라이브러리를 사용하고 처음부터 무언가를 작성하고 현재 메소드를 최적화하는 등의 작업을 할 수 있습니다. 메인 스택은 파이썬이지만이 부분은 C++과 Cython으로 작성되었습니다. 파이썬 래퍼를 쓸 수있는 한 기존 소스를 알고 있다면 모든 언어에 대해 개방적입니다.

도움 주셔서 감사합니다.

+0

좀 더 명확하게 설명 할 수 있습니까? 입력과 출력의 명확한 예를 작성하십시오. 나는이 목록의 교차점이 무엇을 의미하는지 이해하지 못합니다. –

+0

@robertking 완료, 이제 더 명확 해 졌으면 좋겠습니까? 의견을 보내 주셔서 감사합니다. – gmoss

+0

점수 별 정렬을 보장 할 수 없다면 ID 순서대로 정렬 할 수 있으며 순서에 맞지 않는 순서의 해시 테이블을 사용할 수 있습니까? –

답변

3

일반적으로 역 색인을 저장할 때 토큰에 대한 문서 목록은 문서 ID별로 정렬 된 간단한 배열에 저장되며 문서 ID가 가능한 최소 공간을 차지하도록 배열이 압축됩니다. 그런 다음 대량의 작업이 CPU 캐시에서 발생하는 정렬 된 배열을 디코딩, 검색 및 병합하여 교차를 빠르게 처리 할 수 ​​있습니다. 예 : 이 라이브러리를 참조하십시오 https://github.com/lemire/JavaFastPFOR - 여기에서 탐구를 시작하고 거기에 참조 된 관련 논문을 읽는 것이 좋습니다.

+0

어쩌면 최선의 방법은 현재 문서 ID별로 정렬하지 못하게하는 제약 조건을 해결하는 방법을 찾는 것입니다. 그런 다음이 방법을 사용하면 이러한 방법을 사용할 수 있습니다. 나는 그것이 대답이 될 것이라고 걱정했다 :) 도움이되는 링크 주셔서 감사합니다. – gmoss

+0

나는 내림차순으로 정렬하는 것이 좋습니다. 모든 문서가 같은 순서로 정렬되는 한 정렬 된 병합을 적용 할 수 있습니다. 연결 (점수, 문서 ID)을 정렬 키로 사용하십시오. – jkff

+0

"모든 문서가 같은 순서로 정렬되어있는 한". 그렇지 않습니다. 점수는 문서 스코어와 문서의 토큰 컨텍스트의 함수입니다. 내 질문에 첫 번째 예제를 참조하십시오. 그것이 문제의 어려움입니다. – gmoss