SentencePiece는 주로 신경 모델 훈련에 앞서 어휘 크기가 미리 결정되는 신경망 기반 텍스트 생성 시스템을 위한 비지도 텍스트 토크나이저 및 디토크나이저입니다. SentencePiece는 원시 문장에서 직접 학습을 확장하여 하위 단어 단위 (예: 바이트 쌍 인코딩(BPE) [Sennrich et al.]) 및 유니그램 언어 모델 [Kudo.])을 구현합니다. SentencePiece를 사용하면 언어별 전/후처리에 의존하지 않는 순수한 엔드투엔드 시스템을 만들 수 있습니다.
이것은 공식 Google 제품이 아닙니다.
소프트웨어/알고리즘으로서의 SentencePiece에 익숙하지 않은 사람들을 위해 여기에서 간단한 소개를 읽을 수 있습니다.
특징 | 문장조각 | 하위 단어-nmt | 워드피스 |
---|---|---|---|
지원되는 알고리즘 | BPE, 유니그램, 문자, 단어 | BPE | BPE* |
OSS? | 예 | 예 | 구글 내부 |
하위 단어 정규화 | 예 | 아니요 | 아니요 |
Python 라이브러리(pip) | 예 | 아니요 | 해당 없음 |
C++ 라이브러리 | 예 | 아니요 | 해당 없음 |
사전 세분화가 필요합니까? | 아니요 | 예 | 예 |
사용자 정의 가능한 정규화(예: NFKC) | 예 | 아니요 | 해당 없음 |
직접 ID 생성 | 예 | 아니요 | 해당 없음 |
WordPiece에서 사용되는 BPE 알고리즘은 원래 BPE와 약간 다릅니다.
SentencePiece는 하위 단어 단위 를 다시 구현한 것으로, 신경 기계 번역에서 공개된 어휘 문제를 완화하는 효과적인 방법입니다. SentencePiece는 바이트 쌍 인코딩(BPE) [Sennrich et al.]과 유니그램 언어 모델 [Kudo.]이라는 두 가지 분할 알고리즘을 지원합니다. 다른 구현과의 높은 수준의 차이점은 다음과 같습니다.
신경 기계 번역 모델은 일반적으로 고정된 어휘로 작동합니다. 무한한 어휘를 가정하는 대부분의 비지도 단어 분할 알고리즘과 달리 SentencePiece는 최종 어휘 크기가 8k, 16k 또는 32k로 고정되도록 분할 모델을 훈련합니다.
SentencePiece는 훈련을 위한 최종 어휘 크기를 지정하며 이는 병합 작업 수를 사용하는 subword-nmt와 다릅니다. 병합 작업 수는 BPE 관련 매개변수이며 유니그램, 단어 및 문자를 포함한 다른 분할 알고리즘에는 적용할 수 없습니다.
이전 하위 단어 구현에서는 입력 문장이 사전 토큰화되었다고 가정합니다. 이 제약 조건은 효율적인 교육을 위해 필요했지만 언어 종속 토크나이저를 미리 실행해야 하므로 전처리가 복잡해졌습니다. SentencePiece의 구현은 원시 문장에서 모델을 훈련할 수 있을 만큼 빠릅니다. 이는 단어 사이에 명시적인 공백이 없는 중국어와 일본어에 대한 토크나이저 및 디토크나이저를 훈련하는 데 유용합니다.
자연어 처리의 첫 번째 단계는 텍스트 토큰화입니다. 예를 들어, 표준 영어 토크나이저는 "Hello world"라는 텍스트를 분할합니다. 다음 세 가지 토큰으로 변환됩니다.
[안녕하세요] [세계] [.]
한 가지 관찰은 원래 입력과 토큰화된 시퀀스가 가역적으로 변환 가능하지 않다는 것입니다. 예를 들어 'World'와 '.' 사이에 공백이 없는 정보입니다. 예를 들어 Tokenize(“World.”) == Tokenize(“World .”)
이므로 토큰화된 시퀀스에서 삭제됩니다.
SentencePiece는 입력 텍스트를 일련의 유니코드 문자로 처리합니다. 공백도 일반 기호로 처리됩니다. 공백을 기본 토큰으로 명시적으로 처리하기 위해 SentencePiece는 먼저 다음과 같이 메타 기호 " "(U+2581)를 사용하여 공백을 이스케이프합니다.
안녕하세요 월드.
그런 다음 이 텍스트는 작은 조각으로 분할됩니다. 예를 들면 다음과 같습니다.
[안녕하세요] [ 워] [ld] [.]
분할된 텍스트에는 공백이 유지되므로 모호함 없이 텍스트를 해독할 수 있습니다.
detokenized = ''.join(pieces).replace('▁', ' ')
이 기능을 사용하면 언어별 리소스에 의존하지 않고 토큰화 해제를 수행할 수 있습니다.
표준 단어 분할기로 문장을 분할할 때는 공백을 특수 기호로 처리하므로 동일한 무손실 변환을 적용할 수 없습니다. 토큰화된 시퀀스는 원래 문장을 복원하는 데 필요한 정보를 보존하지 않습니다.
하위 단어 정규화[Kudo.] 및 BPE-드롭아웃 Provilkov 등은 실시간 하위 단어 샘플링을 통해 훈련 데이터를 가상으로 강화하는 간단한 정규화 방법으로 NMT 모델의 정확성과 견고성을 향상시키는 데 도움이 됩니다.
하위 단어 정규화를 활성화하려면 SentencePiece 라이브러리(C++/Python)를 NMT 시스템에 통합하여 표준 오프라인 데이터 준비와 다른 각 매개변수 업데이트에 대해 하나의 분할을 샘플링하려고 합니다. 다음은 Python 라이브러리의 예입니다. '뉴욕'은 각 SampleEncode (C++)
에서 다르게 분할되거나 encode with enable_sampling=True (Python)
것을 확인할 수 있습니다. 샘플링 매개변수의 세부사항은 문장조각_프로세서.h에서 찾을 수 있습니다.
>>> import sentencepiece as spm
>>> s = spm.SentencePieceProcessor(model_file='spm.model')
>>> for n in range(5):
... s.encode('New York', out_type=str, enable_sampling=True, alpha=0.1, nbest_size=-1)
...
['▁', 'N', 'e', 'w', '▁York']
['▁', 'New', '▁York']
['▁', 'New', '▁Y', 'o', 'r', 'k']
['▁', 'New', '▁York']
['▁', 'New', '▁York']
SentencePiece는 SentencePiece 훈련과 분할을 모두 지원하는 Python 래퍼를 제공합니다. SentencePiece의 Python 바이너리 패키지를 설치할 수 있습니다.
pip install sentencepiece
자세한 내용은 Python 모듈을 참조하세요.
SentencePiece를 빌드하려면 다음 도구와 라이브러리가 필요합니다.
Ubuntu에서는 apt-get을 사용하여 빌드 도구를 설치할 수 있습니다.
% sudo apt-get install cmake build-essential pkg-config libgoogle-perftools-dev
그런 다음 다음과 같이 명령줄 도구를 빌드하고 설치할 수 있습니다.
% git clone https://github.com/google/sentencepiece.git
% cd sentencepiece
% mkdir build
% cd build
% cmake ..
% make -j $(nproc)
% sudo make install
% sudo ldconfig -v
OSX/macOS에서는 마지막 명령을 sudo update_dyld_shared_cache
로 바꿉니다.
vcpkg 종속성 관리자를 사용하여 문장을 다운로드하고 설치할 수 있습니다.
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install sentencepiece
vcpkg의 문장 포트는 Microsoft 팀 구성원과 커뮤니티 기여자가 최신 상태로 유지됩니다. 버전이 오래된 경우 vcpkg 저장소에서 이슈 또는 풀 요청을 생성하세요.
GitHub 릴리스 페이지에서 휠을 다운로드할 수 있습니다. 릴리스 프로세스 중에 OpenSSF의 slsa-framework/slsa-github-generator를 사용하여 SLSA3 서명을 생성합니다. 릴리스 바이너리를 확인하려면 다음 안내를 따르세요.
attestation.intoto.jsonl
을 다운로드합니다.slsa-verifier -artifact-path < the-wheel > -provenance attestation.intoto.jsonl -source github.com/google/sentencepiece -tag < the-tag >
pip 설치wheel_file.whl
% spm_train --input=<input> --model_prefix=<model_name> --vocab_size=8000 --character_coverage=1.0 --model_type=<type>
--input
: 한 줄에 한 문장으로 구성된 원시 코퍼스 파일입니다. 토크나이저, 노멀라이저 또는 전처리기를 실행할 필요가 없습니다. 기본적으로 SentencePiece는 유니코드 NFKC로 입력을 정규화합니다. 쉼표로 구분된 파일 목록을 전달할 수 있습니다.--model_prefix
: 모델 이름 접두사를 출력합니다. <model_name>.model
및 <model_name>.vocab
생성됩니다.--vocab_size
: 어휘 크기(예: 8000, 16000 또는 32000)--character_coverage
: 모델에 포함되는 문자의 양. 적절한 기본값은 일본어나 중국어와 같이 풍부한 문자 집합이 있는 언어의 경우 0.9995
이고 작은 문자 집합이 있는 기타 언어의 경우 1.0
입니다.--model_type
: 모델 유형. unigram
(기본값), bpe
, char
또는 word
중에서 선택합니다. word
형을 사용할 경우 입력 문장을 미리 토큰화해야 합니다. 훈련을 위한 모든 매개변수를 표시하려면 --help
플래그를 사용하거나 여기에서 개요를 확인하세요.
% spm_encode --model=<model_file> --output_format=piece < input > output
% spm_encode --model=<model_file> --output_format=id < input > output
--extra_options
플래그를 사용하여 BOS/EOS 마커를 삽입하거나 입력 순서를 반대로 바꾸세요.
% spm_encode --extra_options=eos (add </s> only)
% spm_encode --extra_options=bos:eos (add <s> and </s>)
% spm_encode --extra_options=reverse:bos:eos (reverse input and add <s> and </s>)
SentencePiece는 --output_format=(nbest|sample)_(piece|id)
플래그를 사용하여 nbest 분할 및 분할 샘플링을 지원합니다.
% spm_encode --model=<model_file> --output_format=sample_piece --nbest_size=-1 --alpha=0.5 < input > output
% spm_encode --model=<model_file> --output_format=nbest_id --nbest_size=10 < input > output
% spm_decode --model=<model_file> --input_format=piece < input > output
% spm_decode --model=<model_file> --input_format=id < input > output
--extra_options
플래그를 사용하여 텍스트를 역순으로 디코딩합니다.
% spm_decode --extra_options=reverse < input > output
% spm_train --input=data/botchan.txt --model_prefix=m --vocab_size=1000
unigram_model_trainer.cc(494) LOG(INFO) Starts training with :
input: "../data/botchan.txt"
... <snip>
unigram_model_trainer.cc(529) LOG(INFO) EM sub_iter=1 size=1100 obj=10.4973 num_tokens=37630 num_tokens/piece=34.2091
trainer_interface.cc(272) LOG(INFO) Saving model: m.model
trainer_interface.cc(281) LOG(INFO) Saving vocabs: m.vocab
% echo "I saw a girl with a telescope." | spm_encode --model=m.model
▁I ▁saw ▁a ▁girl ▁with ▁a ▁ te le s c o pe .
% echo "I saw a girl with a telescope." | spm_encode --model=m.model --output_format=id
9 459 11 939 44 11 4 142 82 8 28 21 132 6
% echo "9 459 11 939 44 11 4 142 82 8 28 21 132 6" | spm_decode --model=m.model --input_format=id
I saw a girl with a telescope.
어휘 ID 시퀀스로부터 원래 입력 문장이 복원된 것을 확인할 수 있습니다.
% spm_export_vocab --model=<model_file> --output=<output file>
<output file>
어휘 목록과 방출 로그 확률을 저장합니다. 어휘 ID는 이 파일의 줄 번호에 해당합니다.
By default, SentencePiece uses Unknown (<unk>), BOS (<s>) and EOS (</s>) tokens which have the ids of 0, 1, and 2 respectively. 훈련 단계에서 이 매핑을 다음과 같이 재정의할 수 있습니다.
% spm_train --bos_id=0 --eos_id=1 --unk_id=5 --input=... --model_prefix=... --character_coverage=...
-1 id를 설정하면(예: bos_id=-1
) 이 특수 토큰이 비활성화됩니다. 알 수 없는 ID는 비활성화할 수 없습니다. 패딩(<pad>)에 대한 ID를 --pad_id=3
으로 정의할 수 있습니다.
다른 특수 토큰을 할당하려면 사용자 정의 기호 사용을 참조하세요.
spm_encode
--vocabulary
및 --vocabulary_threshold
옵션을 허용하므로 spm_encode
어휘에도 나타나는 기호만 생성합니다(적어도 어느 정도 빈도로). 이 기능의 배경은 subword-nmt 페이지에 설명되어 있습니다.
사용법은 기본적으로 subword-nmt
와 동일합니다. L1과 L2가 두 언어(원본/대상 언어)라고 가정하고 공유 spm 모델을 훈련하고 각각에 대한 결과 어휘를 얻습니다.
% cat {train_file}.L1 {train_file}.L2 | shuffle > train
% spm_train --input=train --model_prefix=spm --vocab_size=8000 --character_coverage=0.9995
% spm_encode --model=spm.model --generate_vocabulary < {train_file}.L1 > {vocab_file}.L1
% spm_encode --model=spm.model --generate_vocabulary < {train_file}.L2 > {vocab_file}.L2
shuffle
명령은 spm_train
기본적으로 말뭉치의 처음 10M 라인을 로드하기 때문에 사용됩니다.
그런 다음 --vocabulary
옵션을 사용하여 학습/테스트 코퍼스를 분할합니다.
% spm_encode --model=spm.model --vocabulary={vocab_file}.L1 --vocabulary_threshold=50 < {test_file}.L1 > {test_file}.seg.L1
% spm_encode --model=spm.model --vocabulary={vocab_file}.L2 --vocabulary_threshold=50 < {test_file}.L2 > {test_file}.seg.L2