deeplearning4j의 Word2Vec에 Kuromoji를 도입했습니다.
소개
웹 API 마켓플레이스Apitore에 Word2Vec을 추가하려고 합니다. Word2Vec이 있으면 자연 언어 처리 시스템의 응용 프로그램에서 다양한 확산이 나옵니다. 그 이야기는 API를 공개했을 때로 이번에는 Java에서 Word2Vec을 구현하는 노하우를 공개합니다. Java로 Word2Vec을 만드는 경우, 본가의 Google에서도 추천하고 있는 deeplearning4j 를 사용하면 간단합니다. 내장하고 있는 형태소 해석 기능은 스페이스 단락이므로, 일본어 형태소 해석기의 Kuromoji를 사용합니다.
소스 코드 등은 여기 으로 공개하고 있습니다.
deeplearning4j word2vec
Java를 아무래도 사용하고 싶기 때문에, deeplearning4j 를 이용합니다. 형태소 분석기는 Kuromoji입니다. 이번에는 Maven을 사용합니다.
<dependency>
<groupId>com.atilika.kuromoji</groupId>
<artifactId>kuromoji-ipadic</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-ui</artifactId>
<version>0.5.0</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-nlp</artifactId>
<version>0.5.0</version>
</dependency>
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-native</artifactId>
<version>0.5.0</version>
</dependency>
deeplearning4j의 word2vec에서 kuromoji를 활용하기 위해 확장 클래스를 구현합니다. Tokenizer와 TokenizerFactory의 확장 클래스입니다. 이미 Scala에서 비슷한 일을 한 사람이 있었으므로 그쪽을 참고로했습니다.
public class KuromojiIpadicTokenizer implements Tokenizer {
private List<Token> tokens;
private int index;
private TokenPreProcess preProcess;
public KuromojiIpadicTokenizer (String toTokenize) {
com.atilika.kuromoji.ipadic.Tokenizer tokenizer = new com.atilika.kuromoji.ipadic.Tokenizer();
tokens = tokenizer.tokenize(toTokenize);
index = (tokens.isEmpty()) ? -1:0;
}
@Override
public int countTokens() {
return tokens.size();
}
@Override
public List<String> getTokens() {
List<String> ret = new ArrayList<String>();
while (hasMoreTokens()) {
ret.add(nextToken());
}
return ret;
}
@Override
public boolean hasMoreTokens() {
if (index < 0)
return false;
else
return index < tokens.size();
}
@Override
public String nextToken() {
if (index < 0)
return null;
Token tok = tokens.get(index);
index++;
if (preProcess != null)
return preProcess.preProcess(tok.getSurface());
else
return tok.getSurface();
}
@Override
public void setTokenPreProcessor(TokenPreProcess preProcess) {
this.preProcess = preProcess;
}
}
public class KuromojiIpadicTokenizerFactory implements TokenizerFactory {
private TokenPreProcess preProcess;
@Override
public Tokenizer create(String toTokenize) {
if (toTokenize == null || toTokenize.isEmpty()) {
throw new IllegalArgumentException("Unable to proceed; no sentence to tokenize");
}
KuromojiIpadicTokenizer ret = new KuromojiIpadicTokenizer(toTokenize);
ret.setTokenPreProcessor(preProcess);
return ret;
}
@Override
public Tokenizer create(InputStream paramInputStream) {
throw new UnsupportedOperationException();
}
@Override
public void setTokenPreProcessor(TokenPreProcess preProcess) {
this.preProcess = preProcess;
}
@Override
public TokenPreProcess getTokenPreProcessor() {
return this.preProcess;
}
}
글쎄, 실제로 배워 보겠습니다. 학습 데이터의 로드는 다음과 같이 합니다.
SentenceIterator iter = new BasicLineIterator(new File("corpus.txt"));
형태소 해석의 실행은 다음과 같이 합니다. 형태소 해석 실행 후에 영 단어의 활용형 부분(e.g. -ed,-ing)의 제거, 영문자 소문자화, 숫자의 기호화를 해 둡니다.
final EndingPreProcessor preProcessor = new EndingPreProcessor();
KuromojiIpadicTokenizerFactory tokenizer = new KuromojiIpadicTokenizerFactory();
tokenizer.setTokenPreProcessor( new TokenPreProcess()
{
@Override
public String preProcess( String token )
{
token = token.toLowerCase();
String base = preProcessor.preProcess( token );
base = base.replaceAll( "\\d" , "__NUMBER__" );
return base;
}
});
학습을 수행합니다. 파라미터는 넷에서 조사해 자주(잘) 사용되고 있을 것 같은 것을 채용하고 있으므로, 적당합니다. 코어는 6개 사용하도록 했습니다만, 태스크 매니저를 보면 6개는 사용하지 않는 것 같습니다.
int batchSize = 1000;
int iterations = 5;
int layerSize = 150;
Word2Vec vec = new Word2Vec.Builder()
.batchSize(batchSize)
.minWordFrequency(5)
.useAdaGrad(false)
.layerSize(layerSize)
.iterations(iterations)
.seed(1)
.windowSize(5)
.learningRate(0.025)
.minLearningRate(1e-3)
.negativeSample(10)
.iterate(iter)
.tokenizerFactory(tokenizer)
.workers(6)
.build();
vec.fit();
학습 모델을 저장합니다. 이것을 잊으면 지옥입니다.
WordVectorSerializer.writeWordVectors(vec, "model-wordvectors.txt");
학습이 완료된 후에는 만든 모델을 사용하여 알레콜레할 수 있습니다.
WordVectors vec = WordVectorSerializer.loadTxtVectors(new File("model-wordvectors.txt"));
Collection<String> lst = vec.wordsNearest("day", 10);
System.out.println(lst);
double cosSim = vec.similarity("day", "night");
System.out.println(cosSim);
double[] wordVector = wordVectors.getWordVector("day");
System.out.println(wordVector);
결론
deeplearning4j를 사용하여 Word2Vec을 쉽게 구현할 수있었습니다. 중요한 데모에 대해서는 준비 중입니다. API를 게시할 때 데모 결과를 포함하여 기사를 작성합니다. 덧붙여서 작은 데이터로 동작 확인은 하고 있으므로, 상기의 기사는 정확합니다. 현재 Windows10 64bit corei7, 메모리 10GB를 사용하여 학습 중입니다. 원 이틀이 지나도 끝나지 않습니다. 메모리는 10GB 지정했습니다만, 대체로 3GB~5GB정도 밖에 사용하지 않는 것 같습니다.
Reference
이 문제에 관하여(deeplearning4j의 Word2Vec에 Kuromoji를 도입했습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/keigohtr/items/f2c5022823370d78dde5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)