[NLP] 개체명 인식(Named Entity Recognition) 구현하기

    개체명은 단어의 의미를 어느정도 파악하기 위해서 사용하는 방법으로 단어의 꼬리표를 다는 방법이다. 예를 들어, 홍길동이라는 것은 사람이름이고, 삼성전자는 기업이름이라고 한다면, 컴퓨터는 문서의 내용을 어느정도 이해할 수 있게 된다.

     

    게다가 많은 개체명의 경우 복합 명사인 경우가 많은데 의미와 함께 단어를 복합명사로 추출하여, 강력한 분석용 단어를 추출할수도 있게 된다.

     

    형태소 분석은 순수하게 의미가 있는 단어로 최대한 잘게잘게 나누기 때문에 문장의 뜻을 정확하게 알기 위해서는 분명 필요한 기능일 수 있으나, 데이터 분석에서 사용을 하게 되는 경우 너무 작은 단위의 단어는 feature만 늘어나게 되고, 문서간의 유사도 등을 비교하거나 검색에서 문서를 찾을 때에도 비효율적이 된다.

     

    [NLP] 개체명 인식(Named Entity Recognition) 구현하기

     


     

    개체명 구현 코드 (Komoran 예시)

    package dev.zeronelab.lecture.nlp;
    
    import kr.co.shineware.nlp.komoran.constant.DEFAULT_MODEL;
    import kr.co.shineware.nlp.komoran.core.Komoran;
    import kr.co.shineware.nlp.komoran.model.KomoranResult;
    import kr.co.shineware.nlp.komoran.model.Token;
    
    import java.util.*;
    
    public class NLP {
        
        private Map<String, String> NER_MAP;
    
        /**
         * NER 개체명 세팅
         */
        public void setNerKwd() {
            NER_MAP = new HashMap<>();
            NER_MAP.put("서울", "LOC");
            NER_MAP.put("데이터분석", "SKL");
        }
    
        public void action() {
            setNerKwd();
    
            Komoran komoran = new Komoran(DEFAULT_MODEL.FULL);
            String document = "안녕하세요 저는 서울에 사는 철수입니다. 데이터분석은 참 재미있는 것 인공지능은 분석 같아요";
    
            KomoranResult analyzeResultList = komoran.analyze(document);
            System.out.println(analyzeResultList.getNouns());
            List<Token> tokenList = analyzeResultList.getTokenList();
    
            Map<String, String> nerMap = getNerMap(tokenList);
            System.out.println("NER Map -> " + nerMap);
        }
    
        public Map<String, String> getNerMap(List<Token> tokenList) {
            Map<String, String> nerMap = new HashMap<>();
            String beforeSTr = "";
            boolean flag = false;
            for(Token token : tokenList) {
                // 명사가 아닐 경우, 초기화
                if(token.getPos().indexOf("NN") == -1) {
                    beforeSTr = "";
                    continue;
                }
    
                // 명사일 경우
                String mergeStr = beforeSTr + token.getMorph();
                if(NER_MAP.containsKey(mergeStr)) {
                    nerMap.put(mergeStr, NER_MAP.get(mergeStr));
                }
    
                beforeSTr = token.getMorph();
            }
    
            return nerMap;
        }
    }

     

    위 소스를 보면, 품사가 명사일 경우에만 진행한다. 아무래도 개체명은 대다수가 명사이기 때문에 명사 품사가 아닐 경우 스킵을 하게 되며, 명사일 경우 beforeStr과 현재의 형태소를 합쳐서 새로운 문자열을 만들고 이 값이 개체명 맵에 있는지 체크하여 있을 경우, nerMap에 담게 된다.

     

    개체명 분석 결과

    [안녕하세요, 서울, 철수, 데이터, 분석, 인공지능, 분석]
    NER Map -> {서울=LOC, 데이터분석=SKL}

     

    첫번째 명사 추출의 경우 데이터와 분석이 나뉘어져 있고, 아직 품사로만 분류했을 뿐 별다른 의미를 파악하기 힘이 든다. 하지만 개체명 인식을 추가하게 되면, 서울의 경우 지역이라는 의미와 데이터 분석은 합쳐지면서 "데이터분석"이 되고 스킬이라는 개체명을 인식하게 된다.

     

     

    댓글

    Designed by JB FACTORY