KLAY - Korean Language AnalYzer (한국어 형태소 분석기)
Korean Language AnalYzer using KOMORAN’s dictionaries.
Performance와 동시에 확장성을 고려하였으며 Readability에 많은 신경을 썼습니다. 그래서 조금 더 자바(Java)스럽게 Design하였습니다.
Chain of Responsibiility 패턴을 사용하여 구현하였습니다. ChainedTokenizationRule 인터페이스를 구현하여 Rule을 쉽게 추가할 수 있습니다. 현재는 아래와 같은 Rule을 순차적으로 적용하고 있습니다.
마찬가지로 Chain of Responsibility 패턴을 사용하여 구현하였습니다. ChainedAnalysisRule 인터페이스를 구현하여 Rule을 쉽게 추가할 수 있습니다. 현재는 아래와 같은 Rule을 순차적으로 적용하고 있습니다.
HMM(Viterbi)는 MorphSequence 클래스를 사용하여 계산되어집니다.
Lucene의 Trie를 변형하여 적용하였습니다.
//***********************************************************************
// 1. configuration and creating Klay object ...
//***********************************************************************
Klay klay = new Klay(Paths.get("data/configuration/klay.conf"));
//***********************************************************************
// 2. start morphological analysis.
//***********************************************************************
String text = "너무기대안하고갔나....................재밌게봤다";
Morphs morphs = klay.doKlay(text);
//***********************************************************************
// 3. print result.
//***********************************************************************
Iterator<Morph> iter = morphs.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
String src = "data/performance/test.txt";
Klay klay = new Klay(Paths.get("data/configuration/klay.conf"));
StopWatch watch = new StopWatch();
watch.start();
int count = 0;
try (BufferedReader in = new BufferedReader(new FileReader(src))) {
String line = null;
while((line = in.readLine()) != null) {
line = line.trim();
if(line.isEmpty()) continue;
klay.doKlay(line);
System.out.print("\r" + ++count);
}
}
watch.stop();
System.out.println("Analysis Time : " + watch.getTime(TimeUnit.MILLISECONDS) / 1000.0 + " (s)");
<dependency>
<groupId>io.github.ks-shim.klay</groupId>
<artifactId>klay-common</artifactId>
<version>0.3.8</version>
</dependency>
<dependency>
<groupId>io.github.ks-shim.klay</groupId>
<artifactId>klay-dictionary</artifactId>
<version>0.3.8</version>
</dependency>
<dependency>
<groupId>io.github.ks-shim.klay</groupId>
<artifactId>klay-core</artifactId>
<version>0.3.8</version>
</dependency>
<repositories>
<repository>
<id>oos</id>
<url>https://s01.oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
public static void main(String[] args) throws Exception {
// 1. 사전에 환경설정 파일의 Raw 사전 정보를 변경합니다.
Properties config = new Properties();
config.load(Files.newInputStream(Paths.get("data/configuration/klay.conf")));
// 2. 관측확률/전이확률에 사용한 pos-frequency 정보를 읽어들입니다.
DictionaryTextSource posFreqSource = new DictionaryTextSource(Paths.get(config.getProperty("dictionary.grammar.path")));
// 3. 관측확률 사전의 소스/타겟 정보를 생성합니다.
DictionaryTextSource[] emissionSources = {
// *** must build DIC_WORD first !!
new DictionaryTextSource(
Paths.get(config.getProperty("dictionary.word.path")), DictionaryTextSource.DictionaryType.DIC_WORD),
new DictionaryTextSource(
Paths.get(config.getProperty("dictionary.irregular.path")), DictionaryTextSource.DictionaryType.DIC_IRREGULAR)
};
DictionaryBinaryTarget emissionTarget =
new DictionaryBinaryTarget(Paths.get(config.getProperty("dictionary.emission.path")));
// 4. 전이확률 사전의 소스/타켓 정보를 생성합니다.
DictionaryTextSource transitionSource =
new DictionaryTextSource(
Paths.get(config.getProperty("dictionary.grammar.path")), DictionaryTextSource.DictionaryType.GRAMMAR);
DictionaryBinaryTarget transitionTarget =
new DictionaryBinaryTarget(Paths.get(config.getProperty("dictionary.transition.path")));
// 5. 빌더를 생성하고 빌딩을 시작합니다.
DictionaryBuilder builder = new DictionaryBuilder.Builder()
.posFreqSource(posFreqSource)
.emissionSourcesAndTarget(emissionSources, emissionTarget)
.transitionSourceAndTarget(transitionSource, transitionTarget)
.build();
builder.buildAll();
}