2013-05-01 2 views
1

나는 스탠포드 nlp 패키지를 사용하여 아래 코드를 작성했습니다.자연 언어 처리의 성별 식별

GenderAnnotator myGenderAnnotation = new GenderAnnotator(); 
myGenderAnnotation.annotate(annotation); 

그러나 "Annie goes to school"문장의 경우 Annie의 성별을 확인할 수 없습니다.

응용 프로그램의 출력은 다음과 같습니다

 [Text=Annie CharacterOffsetBegin=0 CharacterOffsetEnd=5 PartOfSpeech=NNP Lemma=Annie NamedEntityTag=PERSON] 
    [Text=goes CharacterOffsetBegin=6 CharacterOffsetEnd=10 PartOfSpeech=VBZ Lemma=go NamedEntityTag=O] 
    [Text=to CharacterOffsetBegin=11 CharacterOffsetEnd=13 PartOfSpeech=TO Lemma=to NamedEntityTag=O] 
    [Text=school CharacterOffsetBegin=14 CharacterOffsetEnd=20 PartOfSpeech=NN Lemma=school NamedEntityTag=O] 
    [Text=. CharacterOffsetBegin=20 CharacterOffsetEnd=21 PartOfSpeech=. Lemma=. NamedEntityTag=O] 

성별을 얻을 수있는 올바른 방법은 무엇입니까?

답변

4

이름이 지정된 엔티티 인식기가 토큰에 대해 PERSON을 출력하면 이름을 기반으로하는 성별 분류자를 사용하거나 빌드 할 수 없습니다. 예를 들어 NLTK 라이브러리 자습서 페이지의 Gender Identification 섹션을 참조하십시오. 그들은 다음과 같은 기능을 사용합니다 :

  • 마지막 이름.
  • 첫 번째 이름.
  • 이름의 길이 (문자 수).
  • 문자 unigram 존재 (부울 값에 문자가 있는지 여부).

문자 n-gram 빈도를 사용하여 문자 trigrams까지 사용하면 꽤 좋은 결과를 얻을 수 있습니다.

1

성별 주석 자 텍스트 출력에 정보를 추가하지 않고 다음 코드에서와 같이 당신은 여전히 ​​코드를 통해 액세스 할 수 있습니다 :

Properties props = new Properties(); 
props.setProperty("annotators", "tokenize,ssplit,pos,parse,gender"); 

StanfordCoreNLP pipeline = new StanfordCoreNLP(props); 

Annotation document = new Annotation("Annie goes to school"); 

pipeline.annotate(document); 

for (CoreMap sentence : document.get(CoreAnnotations.SentencesAnnotation.class)) { 
    for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)) { 
    System.out.print(token.value()); 
    System.out.print(", Gender: "); 
    System.out.println(token.get(MachineReadingAnnotations.GenderAnnotation.class)); 
    } 
} 

출력 :

Annie, Gender: FEMALE 
goes, Gender: null 
to, Gender: null 
school, Gender: null 
1

많은 접근법이 있으며 그 중 하나가 nltk cookbook에 설명되어 있습니다.

기본적으로 이름에서 일부 기능 (첫 번째 문자, 첫 번째 문자, 첫 번째 문자, 두 번째 문자 등)을 추출하고 이러한 기능을 기반으로 예측을하는 분류 기준을 작성합니다.

import nltk 
import random 

def extract_features(name): 
    name = name.lower() 
    return { 
     'last_char': name[-1], 
     'last_two': name[-2:], 
     'last_three': name[-3:], 
     'first': name[0], 
     'first2': name[:1] 
    } 

f_names = nltk.corpus.names.words('female.txt') 
m_names = nltk.corpus.names.words('male.txt') 

all_names = [(i, 'm') for i in m_names] + [(i, 'f') for i in f_names] 
random.shuffle(all_names) 

test_set = all_names[500:] 
train_set= all_names[:500] 

test_set_feat = [(extract_features(n), g) for n, g in test_set] 
train_set_feat= [(extract_features(n), g) for n, g in train_set] 

classifier = nltk.NaiveBayesClassifier.train(train_set_feat) 

print nltk.classify.accuracy(classifier, test_set_feat) 

이 기본 테스트는 대략 77 %의 정확도를 제공합니다.

+0

"# 'last_char': name [-1]"과 같이 5 개의 각 기능에 '#'을 붙 였으므로 추출 된 기능이 없어야하고 코드를 실행하면 62- 정확도의 63 %, 왜 동전 던지기 (50 %)보다 더 나은 기능이 없을까요? – KubiK888

+0

@ KubiK888 데이터 세트가 불균형 (63 % 남성) 일 수 있고 NaiveBayes를 학습 한 후 가장 좋은 방법은 남성을 항상 선택하는 것이기 때문일 수 있습니다. –