更新時(shí)間:2022年02月09日17時(shí)41分 來源:傳智教育 瀏覽次數(shù):
文本數(shù)據(jù)分析能夠有效幫助我們理解數(shù)據(jù)語料, 快速檢查出語料可能存在的問題, 并指導(dǎo)之后模型訓(xùn)練過程中一些超參數(shù)的選擇.
我們將基于真實(shí)的中文酒店評(píng)論語料來講解常用的幾種文本數(shù)據(jù)分析方法.
屬于二分類的中文情感分析語料, 該語料存放在"./cn_data"目錄下.其中train.tsv代表訓(xùn)練集, dev.tsv代表驗(yàn)證集, 二者數(shù)據(jù)樣式相同.
該train.tsv數(shù)據(jù)樣式:
sentence label
早餐不好,服務(wù)不到位,晚餐無西餐,早餐晚餐相同,房間條件不好,餐廳不分吸煙區(qū).房間不分有無煙房. 0
去的時(shí)候 ,酒店大廳和餐廳在裝修,感覺大廳有點(diǎn)擠.由于餐廳裝修本來該享受的早飯,也沒有享受(他們是8點(diǎn)開始每個(gè)房間送,但是我時(shí)間來不及了)不過前臺(tái)服務(wù)員態(tài)度好! 1
有很長時(shí)間沒有在西藏大廈住了,以前去北京在這里住的較多。這次住進(jìn)來發(fā)現(xiàn)換了液晶電視,但網(wǎng)絡(luò)不是很好,他們自己說是收費(fèi)的原因造成的。其它還好。 1
非常好的地理位置,住的是豪華海景房,打開窗戶就可以看見棧橋和海景。記得很早以前也住過,現(xiàn)在重新裝修了??偟膩碚f比較滿意,以后還會(huì)住 1
交通很方便,房間小了一點(diǎn),但是干凈整潔,很有香港的特色,性價(jià)比較高,推薦一下哦 1
酒店的裝修比較陳舊,房間的隔音,主要是衛(wèi)生間的隔音非常差,只能算是一般的 0
酒店有點(diǎn)舊,房間比較小,但酒店的位子不錯(cuò),就在海邊,可以直接去游泳。8樓的海景打開窗戶就是海。如果想住在熱鬧的地帶,這里不是一個(gè)很好的選擇,不過威海城市真的比較小,打車還是相當(dāng)便宜的。晚上酒店門口出租車比較少。 1
位置很好,走路到文廟、清涼寺5分鐘都用不了,周邊公交車很多很方便,就是出租車不太愛去(老城區(qū)路窄愛堵車),因?yàn)槭抢腺e館所以設(shè)施要陳舊些, 1
酒店設(shè)備一般,套房里臥室的不能上網(wǎng),要到客廳去。 0
train.tsv中的數(shù)據(jù)內(nèi)容共分為2列, 第一列數(shù)據(jù)代表具有感情色彩的評(píng)論文本; 第二列數(shù)據(jù), 0或1, 代表每條文本數(shù)據(jù)是積極或者消極的評(píng)論, 0代表消極, 1代表積極.
# 導(dǎo)入必備工具包
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# 設(shè)置顯示風(fēng)格
plt.style.use('fivethirtyeight')
# 分別讀取訓(xùn)練tsv和驗(yàn)證tsv
train_data = pd.read_csv("./cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("./cn_data/dev.tsv", sep="\t")
# 獲得訓(xùn)練數(shù)據(jù)標(biāo)簽數(shù)量分布
sns.countplot("label", data=train_data)
plt.title("train_data")
plt.show()
# 獲取驗(yàn)證數(shù)據(jù)標(biāo)簽數(shù)量分布
sns.countplot("label", data=valid_data)
plt.title("valid_data")
plt.show()
注意:在深度學(xué)習(xí)模型評(píng)估中, 我們一般使用ACC作為評(píng)估指標(biāo), 若想將ACC的基線定義在50%左右, 則需要我們的正負(fù)樣本比例維持在1:1左右, 否則就要進(jìn)行必要的數(shù)據(jù)增強(qiáng)或數(shù)據(jù)刪減. 上圖中訓(xùn)練和驗(yàn)證集正負(fù)樣本都稍有不均衡, 可以進(jìn)行一些數(shù)據(jù)增強(qiáng)。
# 在訓(xùn)練數(shù)據(jù)中添加新的句子長度列, 每個(gè)元素的值都是對(duì)應(yīng)的句子列的長度
train_data["sentence_length"] = list(map(lambda x: len(x), train_data["sentence"]))
# 繪制句子長度列的數(shù)量分布圖
sns.countplot("sentence_length", data=train_data)
# 主要關(guān)注count長度分布的縱坐標(biāo), 不需要繪制橫坐標(biāo), 橫坐標(biāo)范圍通過dist圖進(jìn)行查看
plt.xticks([])
plt.show()
# 繪制dist長度分布圖
sns.distplot(train_data["sentence_length"])
# 主要關(guān)注dist長度分布橫坐標(biāo), 不需要繪制縱坐標(biāo)
plt.yticks([])
plt.show()
# 在驗(yàn)證數(shù)據(jù)中添加新的句子長度列, 每個(gè)元素的值都是對(duì)應(yīng)的句子列的長度
valid_data["sentence_length"] = list(map(lambda x: len(x), valid_data["sentence"]))
# 繪制句子長度列的數(shù)量分布圖
sns.countplot("sentence_length", data=valid_data)
# 主要關(guān)注count長度分布的縱坐標(biāo), 不需要繪制橫坐標(biāo), 橫坐標(biāo)范圍通過dist圖進(jìn)行查看
plt.xticks([])
plt.show()
# 繪制dist長度分布圖
sns.distplot(valid_data["sentence_length"])
# 主要關(guān)注dist長度分布橫坐標(biāo), 不需要繪制縱坐標(biāo)
plt.yticks([])
plt.show()
通過繪制句子長度分布圖, 可以得知我們的語料中大部分句子長度的分布范圍, 因?yàn)槟P偷妮斎胍鬄楣潭ǔ叽绲膹埩?,合理的長度范圍對(duì)之后進(jìn)行句子截?cái)嘌a(bǔ)齊(規(guī)范長度)起到關(guān)鍵的指導(dǎo)作用. 上圖中大部分句子長度的范圍大致為20-250之間。
# 繪制訓(xùn)練集長度分布的散點(diǎn)圖
sns.stripplot(y='sentence_length',x='label',data=train_data)
plt.show()
# 繪制驗(yàn)證集長度分布的散點(diǎn)圖
sns.stripplot(y='sentence_length',x='label',data=valid_data)
plt.show()
通過查看正負(fù)樣本長度散點(diǎn)圖, 可以有效定位異常點(diǎn)的出現(xiàn)位置, 幫助我們更準(zhǔn)確進(jìn)行人工語料審查. 上圖中在訓(xùn)練集正樣本中出現(xiàn)了異常點(diǎn), 它的句子長度近3500左右, 需要我們?nèi)斯彶椤?/p>
# 導(dǎo)入jieba用于分詞
# 導(dǎo)入chain方法用于扁平化列表
import jieba
from itertools import chain
# 進(jìn)行訓(xùn)練集的句子進(jìn)行分詞, 并統(tǒng)計(jì)出不同詞匯的總數(shù)
train_vocab = set(chain(*map(lambda x: jieba.lcut(x), train_data["sentence"])))
print("訓(xùn)練集共包含不同詞匯總數(shù)為:", len(train_vocab))
# 進(jìn)行驗(yàn)證集的句子進(jìn)行分詞, 并統(tǒng)計(jì)出不同詞匯的總數(shù)
valid_vocab = set(chain(*map(lambda x: jieba.lcut(x), valid_data["sentence"])))
print("訓(xùn)練集共包含不同詞匯總數(shù)為:", len(valid_vocab))
輸出效果:
訓(xùn)練集共包含不同詞匯總數(shù)為: 12147
訓(xùn)練集共包含不同詞匯總數(shù)為: 6857
# 使用jieba中的詞性標(biāo)注功能
import jieba.posseg as pseg
def get_a_list(text):
"""用于獲取形容詞列表"""
# 使用jieba的詞性標(biāo)注方法切分文本,獲得具有詞性屬性flag和詞匯屬性word的對(duì)象,
# 從而判斷flag是否為形容詞,來返回對(duì)應(yīng)的詞匯
r = []
for g in pseg.lcut(text):
if g.flag == "a":
r.append(g.word)
return r
# 導(dǎo)入繪制詞云的工具包
from wordcloud import WordCloud
def get_word_cloud(keywords_list):
# 實(shí)例化繪制詞云的類, 其中參數(shù)font_path是字體路徑, 為了能夠顯示中文,
# max_words指詞云圖像最多顯示多少個(gè)詞, background_color為背景顏色
wordcloud = WordCloud(font_path="./SimHei.ttf", max_words=100, background_color="white")
# 將傳入的列表轉(zhuǎn)化成詞云生成器需要的字符串形式
keywords_string = " ".join(keywords_list)
# 生成詞云
wordcloud.generate(keywords_string)
# 繪制圖像并顯示
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()
# 獲得訓(xùn)練集上正樣本
p_train_data = train_data[train_data["label"]==1]["sentence"]
# 對(duì)正樣本的每個(gè)句子的形容詞
train_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_train_data))
#print(train_p_n_vocab)
# 獲得訓(xùn)練集上負(fù)樣本
n_train_data = train_data[train_data["label"]==0]["sentence"]
# 獲取負(fù)樣本的每個(gè)句子的形容詞
train_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_train_data))
# 調(diào)用繪制詞云函數(shù)
get_word_cloud(train_p_a_vocab)
get_word_cloud(train_n_a_vocab)
驗(yàn)證集正樣本形容詞詞云:
獲得驗(yàn)證集上正負(fù)的樣本的形容詞詞云
# 獲得驗(yàn)證集上正樣本
p_valid_data = valid_data[valid_data["label"]==1]["sentence"]
# 對(duì)正樣本的每個(gè)句子的形容詞
valid_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_valid_data))
#print(train_p_n_vocab)
# 獲得驗(yàn)證集上負(fù)樣本
n_valid_data = valid_data[valid_data["label"]==0]["sentence"]
# 獲取負(fù)樣本的每個(gè)句子的形容詞
valid_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_valid_data))
# 調(diào)用繪制詞云函數(shù)
get_word_cloud(valid_p_a_vocab)
get_word_cloud(valid_n_a_vocab)
根據(jù)高頻形容詞詞云顯示, 我們可以對(duì)當(dāng)前語料質(zhì)量進(jìn)行簡(jiǎn)單評(píng)估, 同時(shí)對(duì)違反語料標(biāo)簽含義的詞匯進(jìn)行人工審查和修正, 來保證絕大多數(shù)語料符合訓(xùn)練標(biāo)準(zhǔn). 上圖中的正樣本大多數(shù)是褒義詞, 而負(fù)樣本大多數(shù)是貶義詞, 基本符合要求, 但是負(fù)樣本詞云中也存在"便利"這樣的褒義詞, 因此可以人工進(jìn)行審查。
什么是數(shù)據(jù)分析?數(shù)據(jù)分析有什么作用?
北京校區(qū)