作者 | 算法进阶
来源 | 算法进阶
NLP,自然语言处理就是用计算机来分析和生成自然语言(文本、语音),目的是让人类可以用自然语言形式跟计算机系统进行人机交互,从而更便捷、有效地进行信息管理。
高清图可如下路径下载(原作者graykode): https://github.com/aialgorithm/AiPy/tree/master/Ai%E7%9F%A5%E8%AF%86%E5%9B%BE%E5%86%8C/Ai_Roadmap
对于中文语句,由于中文词语是连续的,可以用结巴分词(基于trie tree+维特比等算法实现最大概率的词语切分)等工具实现。
importjieba
jieba.lcut("我的地址是上海市松江区中山街道华光药房")
>>>['我','的','地址','是','上海市','松江区','中山','街道','华光','药房']
fromwordcloudimportWordCloud
ham_msg_cloud=WordCloud(width=520,height=260,max_font_size=50,background_color="black",colormap='Blues').generate(原文本语料)
plt.figure(figsize=(16,10))
plt.imshow(ham_msg_cloud,interpolation='bilinear')
plt.axis('off')#turnoffaxis
plt.show()
##词袋表示
fromsklearn.feature_extraction.textimportCountVectorizer
bow=CountVectorizer(
analyzer='word',
strip_accents='ascii',
tokenizer=[],
lowercase=True,
max_features=100,
)
词嵌入分布式表示:自然语言的单词数是成千上万的,One-hot编码会有高维、词语间无联系的缺陷。这时有一种更有效的方法就是——词嵌入分布式表示,通过神经网络学习构造一个低维、稠密,隐含词语间关系的向量表示。常见有Word2Vec、Fasttext、Bert等模型学习每个单词的向量表示,在表示学习后相似的词汇在向量空间中是比较接近的。
#Fasttextembed模型
fromgensim.modelsimportFastText,word2vec
model=FastText(text,size=100,sg=1,window=3,min_count=1,iter=10,min_n=3,max_n=6,word_ngrams=1,workers=12)
print(model.wv['hello'])#词向量
model.save('./data/fasttext100dim')
#TF-IDF可以直接调用sklearn
fromsklearn.feature_extraction.textimportTfidfTransformer
句法、语义依存分析是传统自然语言的基础句子级的任务,语义依存分析是指在句子结构中分析实词和实词之间的语义关系,这种关系是一种事实上或逻辑上的关系,且只有当词语进入到句子时才会存在。语义依存分析的目的即回答句子的”Who did what to whom when and where”的问题。例如句子“张三昨天告诉李四一个秘密”,语义依存分析可以回答四个问题,即谁告诉了李四一个秘密,张三告诉谁一个秘密,张三什么时候告诉李四一个秘密,张三告诉李四什么。 ![]()
#源码可见https://github.com/aialgorithm/Blog
importpandasaspd
importnumpyasnp
importmatplotlib.pyplotasplt
spam_df=pd.read_csv('./data/spam.csv',header=0,encoding="ISO-8859-1")
#数据展示
_,ax=plt.subplots(1,2,figsize=(10,5))
spam_df['label'].value_counts().plot(ax=ax[0],kind="bar",rot=90,title='label');
spam_df['label'].value_counts().plot(ax=ax[1],kind="pie",rot=90,title='label',ylabel='');
print("Datasetsize:",spam_df.shape)
spam_df.head(5)
#导入相关的库
importnltk
fromnltkimportword_tokenize
fromnltk.corpusimportstopwords
fromnltk.dataimportload
fromnltk.stemimportSnowballStemmer
fromstringimportpunctuation
importre#正则匹配
stop_words=set(stopwords.words('english'))
non_words=list(punctuation)
#词形、词干还原
#fromnltk.stemimportWordNetLemmatizer
#wnl=WordNetLemmatizer()
stemmer=SnowballStemmer('english')
defstem_tokens(tokens,stemmer):
stems=[]
fortokenintokens:
stems.append(stemmer.stem(token))
returnstems
###清除非英文词汇并替换数值x
defclean_non_english_xdig(txt,isstem=True,gettok=True):
txt=re.sub('[0-9]','x',txt)#去数字替换为x
txt=txt.lower()#统一小写
txt=re.sub('[^a-zA-Z]','',txt)#去除非英文字符并替换为空格
word_tokens=word_tokenize(txt)#分词
ifnotisstem:#是否做词干还原
filtered_word=[wforwinword_tokensifnotwinstop_words]#删除停用词
else:
filtered_word=[stemmer.stem(w)forwinword_tokensifnotwinstop_words]#删除停用词及词干还原
ifgettok:#返回为字符串或分词列表
returnfiltered_word
else:
return"".join(filtered_word)
spam_df['token']=spam_df.message.apply(lambdax:clean_non_english_xdig(x))
spam_df.head(3)
#数据清洗
spam_df['token']=spam_df.message.apply(lambdax:clean_non_english_xdig(x))
#标签整数编码
spam_df['label']=(spam_df.label=='spam').astype(int)
spam_df.head(3)
#训练词向量Fasttextembed模型
fromgensim.modelsimportFastText,word2vec
fmodel=FastText(spam_df.token,size=100,sg=1,window=3,min_count=1,iter=10,min_n=3,max_n=6,word_ngrams=1,workers=12)
print(fmodel.wv['hello'])#输出hello的词向量
#fmodel.save('./dta/fasttext100dim')
fmodel=FastText.load('./data/fasttext100dim')
#对每个句子的所有词向量取均值,来生成一个句子的vector
defbuild_sentence_vector(sentence,w2v_model,size=100):
sen_vec=np.zeros((size,))
count=0
forwordinsentence:
try:
sen_vec+=w2v_model[word]#.reshape((1,size))
count+=1
exceptKeyError:
continue
ifcount!=0:
sen_vec/=count
returnsen_vec
#句向量
sents_vec=[]
forsentinspam_df['token']:
sents_vec.append(build_sentence_vector(sent,fmodel,size=100))
print(len(sents_vec))
###训练文本分类模型
fromsklearn.model_selectionimporttrain_test_split
fromlightgbmimportLGBMClassifier
fromsklearn.linear_modelimportLogisticRegression
train_x,test_x,train_y,test_y=train_test_split(sents_vec,spam_df.label,test_size=0.2,shuffle=True,random_state=42)
result=[]
clf=LGBMClassifier(class_weight='balanced',n_estimators=300,num_leaves=64,reg_alpha=1,reg_lambda=1,random_state=42)
#clf=LogisticRegression(class_weight='balanced',random_state=42)
clf.fit(train_x,train_y)
importpickle
#保存模型
pickle.dump(clf,open('./saved_models/spam_clf.pkl','wb'))
#加载模型
model=pickle.load(open('./saved_models/spam_clf.pkl','rb))
fromsklearn.metricsimportauc,roc_curve,f1_score,precision_score,recall_score
defmodel_metrics(model,x,y,tp='auc'):
"""评估"""
yhat=model.predict(x)
yprob=model.predict_proba(x)[:,1]
fpr,tpr,_=roc_curve(y,yprob,pos_label=1)
metrics={'AUC':auc(fpr,tpr),'KS':max(tpr-fpr),
'f1':f1_score(y,yhat),'P':precision_score(y,yhat),'R':recall_score(y,yhat)}
roc_auc=auc(fpr,tpr)
plt.plot(fpr,tpr,'k--',label='ROC(area={0:.2f})'.format(roc_auc),lw=2)
plt.xlim([-0.05,1.05])#设置x、y轴的上下限,以免和边缘重合,更好的观察图像的整体
plt.ylim([-0.05,1.05])
plt.xlabel('FalsePositiveRate')
plt.ylabel('TruePositiveRate')#可以使用中文,但需要导入一些库即字体
plt.title('ROCCurve')
plt.legend(loc="lowerright")
returnmetrics
print('train',model_metrics(clf,train_x,train_y,tp='ks'))
print('test',model_metrics(clf,test_x,test_y,tp='ks'))
分享
点收藏
点点赞
点在看
文章转发自AI科技大本营微信公众号,版权归其所有。文章内容不代表本站立场和任何投资暗示。
Copyright © 2021.Company 元宇宙YITB.COM All rights reserved.元宇宙YITB.COM