PorterStemmer와 Snowball을 사용해 보았지만 둘 다 모든 단어에서 작동하지 않으며 매우 일반적인 단어가 누락되었습니다.
내 테스트 단어는 : " cats running ran cactus cactuses cacti community community "그리고 둘 다 절반 미만의 권리를 얻습니다.
또한보십시오:
PorterStemmer와 Snowball을 사용해 보았지만 둘 다 모든 단어에서 작동하지 않으며 매우 일반적인 단어가 누락되었습니다.
내 테스트 단어는 : " cats running ran cactus cactuses cacti community community "그리고 둘 다 절반 미만의 권리를 얻습니다.
또한보십시오:
답변:
Python을 아는 경우 NLTK (Natural Language Toolkit) 에는 WordNet 을 사용하는 매우 강력한 lemmatizer가 있습니다 .
이 lemmatizer를 처음 사용하는 경우 사용하기 전에 말뭉치를 다운로드해야합니다. 이것은 다음을 통해 수행 할 수 있습니다.
>>> import nltk
>>> nltk.download('wordnet')
이 작업은 한 번만 수행하면됩니다. 이제 코퍼스를 다운로드했다고 가정하면 다음과 같이 작동합니다.
>>> from nltk.stem.wordnet import WordNetLemmatizer
>>> lmtzr = WordNetLemmatizer()
>>> lmtzr.lemmatize('cars')
'car'
>>> lmtzr.lemmatize('feet')
'foot'
>>> lmtzr.lemmatize('people')
'people'
>>> lmtzr.lemmatize('fantasized','v')
'fantasize'
nltk.stem 모듈 에 다른 lemmatizer가 있지만 직접 시도하지는 않았습니다.
dies
하면 dy
대신 die
. 어떤 종류의 하드 코딩 된 형태소 분석기 사전이 없습니까?
WordNetLemmatizer
잘못 lemmatize 하는 단어가 무엇인지 아십니까?
나는 lemmatization 을 수행하기 위해 stanford nlp 를 사용합니다. 지난 며칠 동안 비슷한 문제가 발생했습니다. 이 문제를 해결하는 데 도움이되는 stackoverflow 덕분입니다.
import java.util.*;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.ling.*;
import edu.stanford.nlp.ling.CoreAnnotations.*;
public class example
{
public static void main(String[] args)
{
Properties props = new Properties();
props.put("annotators", "tokenize, ssplit, pos, lemma");
pipeline = new StanfordCoreNLP(props, false);
String text = /* the string you want */;
Annotation document = pipeline.process(text);
for(CoreMap sentence: document.get(SentencesAnnotation.class))
{
for(CoreLabel token: sentence.get(TokensAnnotation.class))
{
String word = token.get(TextAnnotation.class);
String lemma = token.get(LemmaAnnotation.class);
System.out.println("lemmatized version :" + lemma);
}
}
}
}
나중에 분류 자에서 사용되는 경우 불용어를 사용하여 출력 기본형을 최소화하는 것도 좋은 생각 일 수 있습니다. John Conwell이 작성한 coreNlp 확장을 살펴보십시오 .
이 눈덩이 데모 사이트 에서 용어 목록을 시도했는데 결과가 괜찮아 보입니다 ....
형태소 분석기는 변형 된 형태의 단어를 일반적인 어근으로 바꿔야합니다. 그 어근을 '적절한'사전 단어로 만드는 것은 실제로 형태소 분석기의 일이 아닙니다. 이를 위해서는 형태 / 직교 분석기 를 살펴볼 필요가 있습니다 .
나는 이 질문 이 거의 똑같은 것에 관한 것이라고 생각하며, 그 질문 에 대한 Kaarel의 대답은 내가 두 번째 링크를 가져온 곳입니다.
형태소 분석기 대 lemmatizer 논쟁은 계속됩니다. 효율성보다 정밀도를 선호하는 문제입니다. 언어 적으로 의미있는 단위를 얻기 위해 lemmatize하고 최소한의 컴퓨팅 주스를 사용하면서 동일한 키 아래에서 단어와 그 변형을 색인화해야합니다.
다음은 Python NLTK를 사용한 예입니다.
>>> sent = "cats running ran cactus cactuses cacti community communities"
>>> from nltk.stem import PorterStemmer, WordNetLemmatizer
>>>
>>> port = PorterStemmer()
>>> " ".join([port.stem(i) for i in sent.split()])
'cat run ran cactu cactus cacti commun commun'
>>>
>>> wnl = WordNetLemmatizer()
>>> " ".join([wnl.lemmatize(i) for i in sent.split()])
'cat running ran cactus cactus cactus community community'
WordNetLemmatizer
의 lemmatize()
는 POS 태그를 사용할 수 있습니다. 따라서 귀하의 예에서 : " ".join([wnl.lemmatize(i, pos=VERB) for i in sent.split()])
제공합니다 'cat run run cactus cactuses cacti community communities'
.
pos=NOUN
? BTW :
pos=VERB
하면 동사에 대해서만 lemmatization을 수행하기 때문입니다. 명사는 동일하게 유지됩니다. 실제 Penn Treebank POS 태그를 중심으로 피벗하여 각 토큰에 올바른 lemmatization을 적용하기 위해 자체 코드를 작성해야했습니다. 또한 WordNetLemmatizer
nltk의 기본 토크 나이저를 lemmatizing 할 때 악취가납니다. 예를 들면 같은 does n't
에 lemmatize하지 않습니다 do not
.
port.stem("this")
생성 합니다. thi
port.stem("was")
wa
Martin Porter의 공식 페이지에는 PHP 와 다른 언어 로 된 Porter Stemmer가 포함되어 있습니다 .
Porter Algorithm과 같은 것으로 시작해야하지만 좋은 형태소 분석에 대해 정말로 진지한 경우, 규칙을 추가하여 데이터 세트에 공통된 잘못된 사례를 수정 한 다음 마지막으로 규칙에 많은 예외를 추가합니다. . 키가 조회 할 단어이고 값이 원본을 대체 할 어간 단어 인 키 / 값 쌍 (dbm / hash / dictionaries)으로 쉽게 구현할 수 있습니다. 내가 작업 한 상업용 검색 엔진은 수정 된 Porter 알고리즘에 대한 몇 가지 예외로 끝났습니다.
http://wordnet.princeton.edu/man/morph.3WN
많은 프로젝트에서 더 공격적인 포터 형태소 분석보다 어휘 기반 WordNet lemmatizer를 선호합니다.
http://wordnet.princeton.edu/links#PHP 에는 WN API에 대한 PHP 인터페이스에 대한 링크가 있습니다.
Stack Overflow에 대한 다양한 답변과 제가 만난 블로그에 따르면 이것이 제가 사용하는 방법이며 실제 단어를 꽤 잘 반환하는 것 같습니다. 아이디어는 들어오는 텍스트를 단어 배열로 분할 한 다음 (원하는 방법을 사용하여) 해당 단어의 품사 (POS)를 찾아이를 사용하여 단어의 어간과 lemmatize를 돕는 것입니다.
위의 샘플은 POS를 결정할 수 없기 때문에 너무 잘 작동하지 않습니다. 그러나 실제 문장을 사용하면 상황이 훨씬 더 잘 작동합니다.
import nltk
from nltk.corpus import wordnet
lmtzr = nltk.WordNetLemmatizer().lemmatize
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUN
def normalize_text(text):
word_pos = nltk.pos_tag(nltk.word_tokenize(text))
lemm_words = [lmtzr(sw[0], get_wordnet_pos(sw[1])) for sw in word_pos]
return [x.lower() for x in lemm_words]
print(normalize_text('cats running ran cactus cactuses cacti community communities'))
# ['cat', 'run', 'ran', 'cactus', 'cactuses', 'cacti', 'community', 'community']
print(normalize_text('The cactus ran to the community to see the cats running around cacti between communities.'))
# ['the', 'cactus', 'run', 'to', 'the', 'community', 'to', 'see', 'the', 'cat', 'run', 'around', 'cactus', 'between', 'community', '.']
이것은 흥미로워 보입니다 : MIT Java WordnetStemmer : http://projects.csail.mit.edu/jwi/api/edu/mit/jwi/morph/WordnetStemmer.html
LemmaGen -C # 3.0으로 작성된 오픈 소스 라이브러리를 살펴보십시오 .
테스트 단어에 대한 결과 ( http://lemmatise.ijs.si/Services )
원형 화를위한 (특정 순서) 상위 파이썬 패키지는 다음과 같습니다 : spacy
, nltk
, gensim
, pattern
, CoreNLP
와 TextBlob
. 나는 단어의 POS 태그를 식별하고 적절한 기본형을 자동으로 할당하기 때문에 spaCy와 gensim의 구현 (패턴 기반)을 선호합니다. 의미를 그대로 유지하면서 더 관련성이 높은 기본형을 제공합니다.
nltk 또는 TextBlob을 사용하려는 경우 올바른 POS 태그를 수동으로 찾고 올바른 기본형을 찾아야합니다.
spaCy를 사용한 기본형 예제 :
# Run below statements in terminal once.
pip install spacy
spacy download en
import spacy
# Initialize spacy 'en' model
nlp = spacy.load('en', disable=['parser', 'ner'])
sentence = "The striped bats are hanging on their feet for best"
# Parse
doc = nlp(sentence)
# Extract the lemma
" ".join([token.lemma_ for token in doc])
#> 'the strip bat be hang on -PRON- foot for good'
Gensim을 사용한 기본형 예제 :
from gensim.utils import lemmatize
sentence = "The striped bats were hanging on their feet and ate best fishes"
lemmatized_out = [wd.decode('utf-8').split('/')[0] for wd in lemmatize(sentence)]
#> ['striped', 'bat', 'be', 'hang', 'foot', 'eat', 'best', 'fish']
위의 예는이 lemmatization 페이지 에서 차용 한 것입니다 .
StompChicken이 언급 한 질문에 대한 답변을 인용 할 수 있다면 :
여기서 핵심 문제는 형태소 분석 알고리즘이 작업중인 언어에 대한 실제 이해없이 음성 기반으로 작동한다는 것입니다.
그들은 언어를 이해하지 못하고 용어 사전에서 실행되지 않기 때문에 "run"/ "ran"과 같은 불규칙한 경우를 인식하고 적절하게 대응할 방법이 없습니다.
불규칙한 경우를 처리해야하는 경우 다른 접근 방식을 선택하거나 형태소 분석기가 작업을 수행 한 후 실행할 사용자 지정 수정 사전을 사용하여 형태소 분석을 확장해야합니다.
NLTK의 형태소 분석기 최신 버전은 Snowball입니다.
여기에서 사용 방법에 대한 예를 찾을 수 있습니다.
http://nltk.googlecode.com/svn/trunk/doc/api/nltk.stem.snowball2-pysrc.html#demo
Morpha 형태소 분석기를 사용할 수 있습니다. UW는 Java 애플리케이션에서 사용하려는 경우 morpha 형태소 분석기를 Maven central에 업로드 했습니다. 훨씬 쉽게 사용할 수있는 래퍼가 있습니다. 종속성으로 추가하고 edu.washington.cs.knowitall.morpha.MorphaStemmer
클래스를 사용하기 만하면 됩니다. 인스턴스는 스레드로부터 안전합니다 (원래 JFlex에는 불필요하게 로컬 변수에 대한 클래스 필드가 있음). 클래스를 인스턴스화하고 morpha
줄기를 원하는 단어를 실행 하십시오.
new MorphaStemmer().morpha("climbed") // goes to "climb"
Martin Porter는 Snowball (형태소 분석 알고리즘 용 언어)을 작성하고 Snowball에서 "English Stemmer"를 다시 작성했습니다. C 및 Java 용 English Stemmer가 있습니다.
그는 Porter Stemmer가 역사적인 이유로 만 다시 구현되었다고 명시 적으로 언급하므로 Porter Stemmer에 대한 형태소 분석 정확성을 테스트하면 이미 알고 있어야하는 결과를 얻을 수 있습니다.
에서 http://tartarus.org/~martin/PorterStemmer/index.html (강조 광산)
Porter 형태소 분석기는 ' 고정 ', 즉 엄격하게 정의 된 것으로 간주되어야하며 추가 수정이 불가능합니다. 형태소 분석기는 Snowball English 또는 Porter2 형태소 분석기보다 약간 열등합니다.이 형태소는 여기에서 파생되며 때때로 개선됩니다. 따라서 실제 작업을 위해서는 새로운 Snowball 형태소 분석기를 사용하는 것이 좋습니다. Porter 형태소 분석기는 실험이 정확하게 반복되어야하는 형태소 분석과 관련된 IR 연구 작업에 적합합니다.
Porter 박사는 Porter 형태소 분석기 대신 English 또는 Porter2 형태소 분석기를 사용할 것을 제안합니다. 영어 형태소 분석기는 @StompChicken이 이전에 답변했듯이 데모 사이트 에서 실제로 사용되는 것입니다.
Java에서는 tartargus-snowball 을 사용 하여 단어를 형태소 분석합니다.
메이븐 :
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-snowball</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
샘플 코드 :
SnowballProgram stemmer = new EnglishStemmer();
String[] words = new String[]{
"testing",
"skincare",
"eyecare",
"eye",
"worked",
"read"
};
for (String word : words) {
stemmer.setCurrent(word);
stemmer.stem();
//debug
logger.info("Origin: " + word + " > " + stemmer.getCurrent());// result: test, skincar, eyecar, eye, work, read
}
여기에서 시도해보세요 : http://www.twinword.com/lemmatizer.php
데모에 쿼리를 입력 하고 선택적 플래그를 "cats running ran cactus cactuses cacti community communities"
얻었 ["cat", "running", "run", "cactus", "cactus", "cactus", "community", "community"]
습니다 ALL_TOKENS
.
샘플 코드
이것은 API이므로 모든 환경에서 연결할 수 있습니다. 다음은 PHP REST 호출의 모습입니다.
// These code snippets use an open-source library. http://unirest.io/php
$response = Unirest\Request::post([ENDPOINT],
array(
"X-Mashape-Key" => [API KEY],
"Content-Type" => "application/x-www-form-urlencoded",
"Accept" => "application/json"
),
array(
"text" => "cats running ran cactus cactuses cacti community communities"
)
);
Spacy (기본 텍스트 구문 분석 및 태그 지정)와 Textacy (Spacy 위에 구축 된 고급 텍스트 처리 )를 사용하는 것이 좋습니다 .
기본 화 된 단어 는 기본적으로 Spacy 에서 토큰의 .lemma_
속성으로 사용할 수 있으며 텍스트는 텍스트를 사용하여 다른 많은 텍스트 전처리를 수행하는 동안 lemmatized 할 수 있습니다. 예를 들어 용어 또는 단어 모음을 만드는 동안 또는 일반적으로 필요한 일부 처리를 수행하기 직전에.
코드를 작성하기 전에 두 가지를 모두 확인하는 것이 좋습니다. 이렇게하면 많은 시간을 절약 할 수 있습니다!
df_plots = pd.read_excel("Plot Summary.xlsx", index_col = 0)
df_plots
# Printing first sentence of first row and last sentence of last row
nltk.sent_tokenize(df_plots.loc[1].Plot)[0] + nltk.sent_tokenize(df_plots.loc[len(df)].Plot)[-1]
# Calculating length of all plots by words
df_plots["Length"] = df_plots.Plot.apply(lambda x :
len(nltk.word_tokenize(x)))
print("Longest plot is for season"),
print(df_plots.Length.idxmax())
print("Shortest plot is for season"),
print(df_plots.Length.idxmin())
#What is this show about? (What are the top 3 words used , excluding the #stop words, in all the #seasons combined)
word_sample = list(["struggled", "died"])
word_list = nltk.pos_tag(word_sample)
[wnl.lemmatize(str(word_list[index][0]), pos = word_list[index][1][0].lower()) for index in range(len(word_list))]
# Figure out the stop words
stop = (stopwords.words('english'))
# Tokenize all the plots
df_plots["Tokenized"] = df_plots.Plot.apply(lambda x : nltk.word_tokenize(x.lower()))
# Remove the stop words
df_plots["Filtered"] = df_plots.Tokenized.apply(lambda x : (word for word in x if word not in stop))
# Lemmatize each word
wnl = WordNetLemmatizer()
df_plots["POS"] = df_plots.Filtered.apply(lambda x : nltk.pos_tag(list(x)))
# df_plots["POS"] = df_plots.POS.apply(lambda x : ((word[1] = word[1][0] for word in word_list) for word_list in x))
df_plots["Lemmatized"] = df_plots.POS.apply(lambda x : (wnl.lemmatize(x[index][0], pos = str(x[index][1][0]).lower()) for index in range(len(list(x)))))
#Which Season had the highest screenplay of "Jesse" compared to "Walt"
#Screenplay of Jesse =(Occurences of "Jesse")/(Occurences of "Jesse"+ #Occurences of "Walt")
df_plots.groupby("Season").Tokenized.sum()
df_plots["Share"] = df_plots.groupby("Season").Tokenized.sum().apply(lambda x : float(x.count("jesse") * 100)/float(x.count("jesse") + x.count("walter") + x.count("walt")))
print("The highest times Jesse was mentioned compared to Walter/Walt was in season"),
print(df_plots["Share"].idxmax())
#float(df_plots.Tokenized.sum().count('jesse')) * 100 / #float((df_plots.Tokenized.sum().count('jesse') + #df_plots.Tokenized.sum().count('walt') + #df_plots.Tokenized.sum().count('walter')))