Sentiment features for machine learning¶
KosacVectorizer turns Korean text into KOSAC label-probability features, so the
lexicon can feed a scikit-learn pipeline.
Install¶
pip install "kosac-lexicon[kiwi,sklearn]"
([kiwi] for the tokenizer, [sklearn] for the estimator base classes.)
A classification pipeline¶
from kosac.sklearn import KosacVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
train_texts = [
"정말 훌륭하고 만족스러운 제품이다",
"최고의 경험이었고 매우 행복했다",
"친절한 서비스에 기분이 좋았다",
"형편없고 실망스러운 품질이다",
"최악이었고 다시는 안 쓴다",
"불친절해서 너무 화가 났다",
]
labels = ["pos", "pos", "pos", "neg", "neg", "neg"]
clf = make_pipeline(KosacVectorizer("all"), LogisticRegression(max_iter=1000))
clf.fit(train_texts, labels)
clf.predict(["기대 이상으로 만족스럽다", "두 번 다시 가고 싶지 않다"])
# array(['pos', 'neg'], dtype='<U3')
KosacVectorizer("all") emits one column per <feature>=<label> probability —
29 columns across the six features.
Inspecting the features¶
vec = KosacVectorizer("polarity").fit(train_texts)
vec.get_feature_names_out()
# array(['polarity=COMP', 'polarity=NEG', 'polarity=NEUT',
# 'polarity=None', 'polarity=POS'], dtype=object)
vec.transform(train_texts).shape # (6, 5)
Each row is the per-label probability distribution from analyze() (the
probability method, which handles function-morpheme noise — see the
counting tutorial).
Tips for real data¶
The constructor mirrors
SentimentAnalyzer:KosacVectorizer("all", negation=True, ngrams=[1, 2, 3], min_freq=5).Evaluate with cross-validation, not a tiny toy set:
from sklearn.model_selection import cross_val_score cross_val_score(clf, train_texts, labels, cv=2) # array([0.333, 0.333]) — six toy samples are far too few to be meaningful; # run this on a real labeled corpus.
Combine lexicon features with bag-of-words for a stronger baseline:
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.pipeline import FeatureUnion features = FeatureUnion([ ("kosac", KosacVectorizer("all")), ("tfidf", TfidfVectorizer()), ]) features.fit_transform(train_texts, labels).shape # (6, 51) — 29 KOSAC + 22 TF-IDF