版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
计分方式
-
组合观点
-
直接观点
句子 | 主体 | 观点 | 程度(含否定) | 得分 | 观点类型 |
---|---|---|---|---|---|
价格真tm高 | 价格(-1) | 高(1) | 真tm(2) | 组合观点 | |
价格没有不合理 | 价格 | 合理(1) | 没有(-1)不(-1) | 直接观点 | |
希望有美颜功能 | 美颜功能 | 希望有(-1) | -1 | 直接观点 | |
有美颜功能 | 美颜功能(1) | 有(1) | 组合观点 | ||
麻雀虽小五脏俱全 | 麻雀(1) | 小(-1)、五脏俱全(1) | 混合观点 |
- 特殊组合观点
正面观点 | 负面观点 |
---|---|
声音足够小 | 声音过小 |
声音足够大 | 声音过大 |
材质够软 | 材质不够软 |
材料够硬 | 材质不够硬 |
- 需要结合语境的情感
观点 | 语境 |
---|---|
好评 | 发动机力气大 |
差评 | 开盖要很大的力气 才行 |
- 机器学习
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
# 语料
train = [
'手机慢', '手机烂', '手机垃圾', '音箱差',
'手机快', '手机好看', '音箱好看', '音箱ok',
]
y = [0, 0, 0, 0, 1, 1, 1, 1]
# 待识别的实体
entities = {'手机', '音箱', '拍照'}
# TF-IDF向量训练
vectorizer = TfidfVectorizer(tokenizer=jieba.cut)
X = vectorizer.fit_transform(train)
# 分类模型
clf = MultinomialNB()
clf.fit(X, y)
# 实体识别+情感分析
text = '手机很慢,但拍照好看,无聊时听听FM,音箱ok'
for clause in text.split(','):
for word in jieba.cut(clause):
if word in entities:
vector = vectorizer.transform([clause])
pred = clf.predict(vector)[0]
print(word, pred)
手机 0
拍照 1
音箱 1
合并同flag词
from jieba.posseg import lcut
text = '拳王真的非常非常威猛高大'
ls = lcut(text)
words = [i.word for i in ls]
flags = [i.flag for i in ls]
print(words)
print(flags)
def combine(words, flags):
"""
合并相邻的同flag项
e.g.
[ 非常 非常 美丽 动人 ] → [ 非常非常 美丽动人 ]
"""
length = len(words)
for i in range(length - 1, 0, -1):
if flags[i-1] == flags[i]:
words[i-1] = words[i-1] + words[i]
del words[i]
del flags[i]
return words, flags
words, flags = combine(words, flags)
print(words)
print(flags)
-
[‘拳王’, ‘真的’, ‘非常’, ‘非常’, ‘威猛’, ‘高大’]
[‘n’, ‘d’, ‘d’, ‘d’, ‘a’, ‘a’]
[‘拳王’, ‘真的非常非常’, ‘威猛高大’]
[‘n’, ‘d’, ‘a’]
否定词模型
- 语料
texts = [
'价格 高', '价格 不 高', '价格 不是 高', '价格 不是 不 高',
'价格 低', '价格 不 低', '价格 不是 低', '价格 不是 不 低',
'价值 高', '价值 不 高', '价值 不是 高', '价值 不是 不 高',
'价值 低', '价值 不 低', '价值 不是 低', '价值 不是 不 低',
]
y = [
0, 1, 1, 0,
1, 0, 0, 1,
1, 0, 0, 1,
0, 1, 1, 0,
]
- 机器学习分类模型(失败)
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
for clf in [MultinomialNB, LogisticRegression, SVC]:
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(texts)
classifier = clf()
classifier.fit(X, y)
print(classifier.score(X, y), clf.__name__)
- 深度学习(失败)
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Embedding, Dense,\
LSTM, Bidirectional,\
Conv1D, GlobalMaxPool1D
"""数据读取与处理"""
words = {word for text in texts for word in text.split()}
word2id = {w: i for i, w in enumerate(words, 1)}
x = [[word2id[word] for word in text.split()] for text in texts]
"""配置"""
input_dim = len(words) + 1 # 词库大小
maxlen = 4 # 序列长度
output_dim = 6 # 词向量维度
x = pad_sequences(x, maxlen)
def modeling(model_name='rnn'):
"""建模"""
model = Sequential()
model.add(Embedding(input_dim, output_dim, input_length=maxlen))
if model_name == 'cnn':
model.add(Conv1D(filters=6, kernel_size=3, padding='same', activation='relu'))
model.add(GlobalMaxPool1D())
else:
model.add(Bidirectional(LSTM(units=8)))
model.add(Dense(units=1, activation='sigmoid'))
model.summary()
"""编译、训练"""
model.compile('adam', 'binary_crossentropy', ['acc'])
model.fit(x, y, batch_size=1, epochs=500, verbose=2, validation_split=.125)
modeling(model_name='cnn')
modeling(model_name='rnn')
- 手写规则(麻烦)
word2flag = {
'价格': 'subject', '价值': 'subject',
'高': 'adjective', '低': 'adjective',
'不': 'privative', '不是': 'privative',
}
word2value = {
'价格': -1, '价值': 1,
'高': 1, '低': -1,
'不': -1, '不是': -1,
}
def calculate(words):
dt = {'privative': 1}
flags = [word2flag[word] for word in words]
values = [word2value[word] for word in words]
for i in range(len(words)):
if flags[i] == 'privative':
dt['privative'] *= values[i]
else:
dt[flags[i]] = values[i]
subject = dt.get('subject', 0)
adjective = dt.get('adjective', 0)
privative = dt.get('privative')
return subject * adjective * privative
scores = [calculate(text.split()) for text in texts]
y_pred = [1 if score > 0 else 0 for score in scores]
accuracy = sum([1 if i == j else 0 for i, j in zip(y, y_pred)]) / len(y)
print(accuracy)
否定词
- 否定词
不
不是
不算
不怎么
不曾
不等于
不会
不能
不是
不算
不太
不再
从不
从来不
从没
从未
没
没有
无
并不
并不是
并没有
并未
没法
未
- 双重否定
不得不
不是不
并非不
不可不
不是没
不是没有
不会不
别不
不无道理
未尝不可
- 疑问
是否
是不是
附录
en | cn |
---|---|
Sentiment Analysis | 情感分析 |
flag | n.标志、旗帜;v 标记 |
degree word | 程度词 |
sentiment word | 情感词 |
privative | 否定词 |
sentiment | 感情;观点 |
emotion | 情感;情绪 |
separator | 分隔符 |
conjunction | 连接词 |
explicit | 明显的;直率的 |
obscure | 隐晦的;含蓄的 |
parse | n.语法分析;vt.解析;vi.理解 |
lexical | 词汇的 |
syntax | 语法;句法; |
semantic | 语义(的) |