<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【數(shù)據(jù)分析】數(shù)據(jù)分析(EDA)學(xué)習(xí)總結(jié)!

          共 7506字,需瀏覽 16分鐘

           ·

          2020-08-02 13:07

          作者:張永泰,北京工業(yè)大學(xué),Datawhale優(yōu)秀學(xué)習(xí)者

          探索性數(shù)據(jù)分析(Exploratory Data Analysis,EDA)是一種探索數(shù)據(jù)的結(jié)構(gòu)和規(guī)律的一種數(shù)據(jù)分析方法。其主要的工作包含:對(duì)數(shù)據(jù)進(jìn)行清洗,對(duì)數(shù)據(jù)進(jìn)行描述(描述統(tǒng)計(jì)量,圖表),查看數(shù)據(jù)的分布,比較數(shù)據(jù)之間的關(guān)系,培養(yǎng)對(duì)數(shù)據(jù)的直覺(jué)和對(duì)數(shù)據(jù)進(jìn)行總結(jié)。

          EDA可以幫助我們找到適合的數(shù)據(jù)模型,本文針對(duì)文本數(shù)據(jù),將進(jìn)行具體的數(shù)據(jù)探索性分析講解。

          一、數(shù)據(jù)及背景

          https://tianchi.aliyun.com/competition/entrance/531810/information(阿里天池-零基礎(chǔ)入門NLP賽事)

          二、實(shí)驗(yàn)環(huán)境

          導(dǎo)入需要使用的包
          import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.model_selection import train_test_splitimport seaborn as snsimport scipyfrom collections import Counter

          三、數(shù)據(jù)探索

          首先,利用Pandas對(duì)數(shù)據(jù)進(jìn)行讀取。

          df_train = pd.read_csv(train_path, sep='\t')df_test = pd.read_csv(test_path, sep='\t')

          3.1 簡(jiǎn)單查看數(shù)據(jù)

          df_train.head(), len(df_train)

          發(fā)現(xiàn)text域的數(shù)據(jù)是字符串。我們想要得到整數(shù)序列??梢杂米址指顂plit()。
          print(len(df_train['text'][0]), type(df_train['text'][0]))df_train.head()

          3.2 長(zhǎng)度分布

          3.2.1 describe

          這里與教程中的方法有所不同。vectorize是numpy中很方便的函數(shù),作用和pandas中apply差不多。用法:

          np.vectorize(function)(array)

          輸入待處理的array,以及逐元素處理函數(shù)function,返回經(jīng)過(guò)處理后的ndarray。原來(lái)的array則不受影響。

          當(dāng)前我使用的函數(shù)split_df負(fù)責(zé)將一行數(shù)據(jù)按空格切分成整數(shù)列表,然后計(jì)算該列表的長(zhǎng)度。

          def split_df(df_row):    return len(str(df_row).split())len_dist = np.vectorize(split_df)(df_train['text'])len_test_dist = np.vectorize(split_df)(df_test['text'])

          使用describe函數(shù)查看訓(xùn)練集和測(cè)試集中的數(shù)據(jù)長(zhǎng)度分布

          print(pd.Series(len_dist).describe())

          print(pd.Series(len_test_dist).describe())

          通過(guò)數(shù)據(jù)描述可以看到:
          • 訓(xùn)練集共200,000條新聞,每條新聞平均907個(gè)字符,最短的句子長(zhǎng)度為2,最長(zhǎng)的句子長(zhǎng)度為57921,其中75%以下的數(shù)據(jù)長(zhǎng)度在1131以下。

          • 測(cè)試集共50,000條新聞,每條新聞平均909個(gè)字符,最短句子長(zhǎng)度為14,最長(zhǎng)句子41861,75%以下的數(shù)據(jù)長(zhǎng)度在1133以下。

          • 訓(xùn)練集和測(cè)試集就長(zhǎng)度來(lái)說(shuō)似乎是同一分布。

          3.2.2 直方圖

          繪制直方圖查看訓(xùn)練集和測(cè)試集中的數(shù)據(jù)長(zhǎng)度分布

          fig, ax = plt.subplots(1,1,figsize=(12,6))
          ax = plt.hist(x=len_dist, bins=100)ax = plt.hist(x=len_test_dist, bins=100)
          plt.xlim([0, max(max(len_dist), max(len_test_dist))])plt.xlabel("length of sample")plt.ylabel("number of sample")plt.legend(['train_len','test_len'])
          plt.show()

          使用seaborn繪制更好的圖。seaborn計(jì)算的縱坐標(biāo)是頻率,而不是出現(xiàn)次數(shù)。由于訓(xùn)練集和測(cè)試集的數(shù)據(jù)量不一樣,因此用頻率更加科學(xué)、更能看出是否符合同一分布。

          plt.figure(figsize=(15,5))ax = sns.distplot(len_dist, bins=100)ax = sns.distplot(len_test_dist, bins=100)plt.xlim([0, max(max(len_dist), max(len_test_dist))])plt.xlabel("length of sample")plt.ylabel("prob of sample")plt.legend(['train_len','test_len'])

          通過(guò)直方圖,我們能直觀感受到訓(xùn)練集和測(cè)試集的長(zhǎng)度分布都屬于右偏分布。按理說(shuō)分析到這份兒上就該停了。

          3.2.3 同分布驗(yàn)證

          import scipyscipy.stats.ks_2samp(len_dist, len_test_dist)Ks_2sampResult(statistic=0.004049999999999998, pvalue=0.5279614323123156)

          P值為0.52,比指定的顯著水平(假設(shè)為5%)大,我們認(rèn)為二者同分布。

          3.2.4 截?cái)辔恢?/span>

          在輸入模型進(jìn)行訓(xùn)練之前,我們要把所有的數(shù)據(jù)長(zhǎng)度統(tǒng)一化,數(shù)據(jù)肯定要截?cái)?。但是在什么位置截?cái)嗪线m呢?
          考慮到數(shù)據(jù)長(zhǎng)度分布是長(zhǎng)尾分布,log一下看看是不是正態(tài)分布,如果是正態(tài)分布,使用3sigma法則作為截?cái)嗟膮⒖?。如果不是,則就只能瞎猜了

          測(cè)量擬合分布的均值和方差sigma原則:

          • 原則:數(shù)值分布在中的概率為0.6526;

          • 原則:數(shù)值分布在中的概率為0.9544;

          • 原則:數(shù)值分布在中的概率為0.9974;

          由于“小概率事件”和假設(shè)檢驗(yàn)的基本思想 “小概率事件”通常指發(fā)生的概率小于5%的事件,認(rèn)為在一次試驗(yàn)中該事件是幾乎不可能發(fā)生的。由此可見X落在以外的概率小于千分之三,在實(shí)際問(wèn)題中常認(rèn)為相應(yīng)的事件是不會(huì)發(fā)生的,基本上可以把區(qū)間看作是隨機(jī)變量X實(shí)際可能的取值區(qū)間,這稱之為正態(tài)分布的“”原則。

          log_len_dist = np.log(1+len_dist)log_len_test_dist = np.log(1+len_test_dist)plt.figure(figsize=(15,5))ax = sns.distplot(log_len_dist)ax = sns.distplot(log_len_test_dist)plt.xlabel("log length of sample")plt.ylabel("prob of log")plt.legend(['train_len','test_len'])

          從log圖上也能看出二者(很像)同分布。
          下面我想驗(yàn)證一下我的猜想:該分布為正態(tài)分布,且訓(xùn)練集和測(cè)試集為同分布。

          先驗(yàn)證訓(xùn)練集分布為正態(tài)分布:

          _, lognormal_ks_pvalue = scipy.stats.kstest(rvs=log_len_dist, cdf='norm')print('P value is ', lognormal_ks_pvalue)
          P value is 0.0
          ?0???擬合優(yōu)度檢驗(yàn),p值為0,意思就是說(shuō)這不是一個(gè)正態(tài)分布。

          之前我們把數(shù)據(jù)log了一下,但是這里有更科學(xué)的變換方式。log只是box-cox變換的特殊形式。我們使用box-cox變換再次做一下驗(yàn)證,是否為正態(tài)分布:

          trans_data, lam = scipy.stats.boxcox(len_dist+1)scipy.stats.normaltest(trans_data)NormaltestResult(statistic=1347.793358118494, pvalue=2.1398873511704724e-293)
          e后面跟了那么多負(fù)數(shù),我佛了。這說(shuō)明我們的假設(shè)不成立。

          但總歸是要猜一個(gè)截?cái)嘀档?。看log圖上8.5的位置比較靠譜。np.exp(8.5)=4914約等于5000,因此我初步?jīng)Q定把截?cái)嚅L(zhǎng)度定為5000。

          3.3 類別信息

          3.3.1 簡(jiǎn)單查看類別信息表

          先改造一下df_train,多加幾個(gè)字段,分別是:
          • text-split,將text字段分詞

          • len,每條新聞長(zhǎng)度

          • first_char,新聞第一個(gè)字符

          • last_char,新聞最后一個(gè)字符

          • most_freq,新聞最常出現(xiàn)的字符

          df_train['text_split'] = df_train['text'].apply(lambda x:x.split())df_train['len'] = df_train['text'].apply(lambda x:len(x.split()))df_train['first_char'] = df_train['text_split'].apply(lambda x:x[0])df_train['last_char'] = df_train['text_split'].apply(lambda x:x[-1])df_train['most_freq'] = df_train['text_split'].apply(lambda x:np.argmax(np.bincount(x)))df_train.head()

          構(gòu)建一個(gè)類別信息表。
          • count,該類別新聞個(gè)數(shù)

          • len_mean,該類別新聞平均長(zhǎng)度

          • len_std,該類別新聞長(zhǎng)度標(biāo)準(zhǔn)差

          • len_min,該類別新聞長(zhǎng)度最小值

          • len_max,該類別新聞長(zhǎng)度最大值

          • freq_fc,該類別新聞最常出現(xiàn)的第一個(gè)字符

          • freq_lc,該類別新聞最常出現(xiàn)的最后一個(gè)字符

          • freq_freq,該類別新聞最常出現(xiàn)的字符

          df_train_info = pd.DataFrame(columns=['count','len_mean','len_std','len_min','len_max','freq_fc','freq_lc','freq_freq'])for name, group in df_train.groupby('label'):    count = len(group) # 該類別新聞數(shù)    len_mean = np.mean(group['len']) # 該類別長(zhǎng)度平均值    len_std = np.std(group['len']) # 長(zhǎng)度標(biāo)準(zhǔn)差    len_min = np.min(group['len']) # 最短的新聞長(zhǎng)度    len_max = np.max(group['len']) # 最長(zhǎng)的新聞長(zhǎng)度    freq_fc = np.argmax(np.bincount(group['first_char'])) # 最頻繁出現(xiàn)的首詞    freq_lc = np.argmax(np.bincount(group['last_char'])) # 最頻繁出現(xiàn)的末詞    freq_freq = np.argmax(np.bincount(group['most_freq'])) # 該類別最頻繁出現(xiàn)的詞    df_train_info.loc[name] = [count,len_mean,len_std,len_min,len_max,freq_fc,freq_lc,freq_freq]df_train_info

          3.3.2 類別分布

          之前的討論是從數(shù)據(jù)集總體驗(yàn)證同分布的,我們還需要驗(yàn)證訓(xùn)練集的類別足夠均勻。

          在數(shù)據(jù)集中標(biāo)簽的對(duì)應(yīng)的關(guān)系如下

          label_2_index_dict = {'科技': 0, '股票': 1, '體育': 2, '娛樂(lè)': 3, '時(shí)政': 4, '社會(huì)': 5, '教育': 6, '財(cái)經(jīng)': 7, '家居': 8, '游戲': 9, '房產(chǎn)': 10, '時(shí)尚': 11, '彩票': 12, '星座': 13}index_2_label_dict = {v:k for k,v in label_2_index_dict.items()}
          plt.figure()plt.bar(x=range(14), height=np.bincount(df_train['label']))plt.xlabel("label")plt.ylabel("number of sample")plt.xticks(range(14), list(index_2_label_dict.values()), fontproperties=zhfont, rotation=60)plt.show()

          從統(tǒng)計(jì)結(jié)果可以看出
          • 賽題的數(shù)據(jù)集類別分布存在較為不均勻的情況。在訓(xùn)練集中科技類新聞最多,其次是股票類新聞,最少的新聞是星座新聞。

          • 科技類新聞最多,星座類新聞最少。這個(gè)國(guó)家的人大部分是唯物主義者哈,神秘學(xué)受眾比較少(啊這,我在分析什么?)。

          • 由于類別不均衡,會(huì)嚴(yán)重影響模型的精度。但是我們也是有辦法應(yīng)對(duì)的。

          3.3.3 類別長(zhǎng)度

          df_train['len'] = df_train['text'].apply(lambda x: len(x.split()))plt.figure()ax = sns.catplot(x='label', y='len', data=df_train, kind='strip')plt.xticks(range(14), list(index_2_label_dict.values()), fontproperties=zhfont, rotation=60)

          在散點(diǎn)圖中,股票類新聞的長(zhǎng)度都飄到天上去了,可以看出股票分析類文章真的很容易寫得又臭又長(zhǎng)?。òl(fā)現(xiàn):不同類別的文章長(zhǎng)度不同,可以把長(zhǎng)度作為一個(gè)Feature,以供機(jī)器學(xué)習(xí)模型訓(xùn)練)!

          3.4 字符分布

          訓(xùn)練集中總共包括6869個(gè)字,最大數(shù)字為7549,最小數(shù)字為0,其中編號(hào)3750的字出現(xiàn)的次數(shù)最多,編號(hào)3133的字出現(xiàn)的次數(shù)最少,僅出現(xiàn)一次。

          # 內(nèi)存警告?。?!沒(méi)有8G內(nèi)存不要運(yùn)行該代碼all_lines = ' '.join(list(df_train['text']))word_count = Counter(all_lines.split(" "))word_count = sorted(word_count.items(), key=lambda d:d[1], reverse=True)
          print(len(word_count))# 6869
          print(word_count[0])# ('3750', 7482224)
          print(word_count[-1])# ('3133', 1)

          下面代碼統(tǒng)計(jì)了不同字符在多少個(gè)句子中出現(xiàn)過(guò),其中字符3750、字符900和字符648在20w新聞的覆蓋率接近99%,很有可能是標(biāo)點(diǎn)符號(hào)。

          %%timedf_train['text_unique'] = df_train['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))all_lines = ' '.join(list(df_train['text_unique']))word_count = Counter(all_lines.split(" "))word_count = sorted(word_count.items(), key=lambda d:int(d[1]), reverse=True)# 打印整個(gè)訓(xùn)練集中覆蓋率前5的詞for i in range(5):    print("{} occurs {} times, {}%".format(word_count[i][0], word_count[i][1], (word_count[i][1]/200000)*100))

          四、分析總結(jié)

          數(shù)據(jù)分析肯定要有結(jié)論,沒(méi)有結(jié)論的數(shù)據(jù)分析是不完整的。
          1. 訓(xùn)練集共200,000條新聞,每條新聞平均907個(gè)字符,最短的句子長(zhǎng)度為2,最長(zhǎng)的句子長(zhǎng)度為57921,其中75%以下的數(shù)據(jù)長(zhǎng)度在1131以下。測(cè)試集共50,000條新聞,每條新聞平均909個(gè)字符,最短句子長(zhǎng)度為14,最長(zhǎng)句子41861,75%以下的數(shù)據(jù)長(zhǎng)度在1133以下。
          2. 訓(xùn)練集和測(cè)試集就長(zhǎng)度來(lái)說(shuō)似乎是同一分布,但是不屬于正態(tài)分布。
          3. 賽題的數(shù)據(jù)集類別分布存在較為不均勻的情況。在訓(xùn)練集中科技類新聞最多,其次是股票類新聞,最少的新聞是星座新聞。需要用采樣方法解決。文章最長(zhǎng)的是股票類新聞。不同類別的文章長(zhǎng)度不同,可以把長(zhǎng)度和句子個(gè)數(shù)作為一個(gè)Feature,以供機(jī)器學(xué)習(xí)模型訓(xùn)練。
          4. 訓(xùn)練集中總共包括6869個(gè)字,最大數(shù)字為7549,最小數(shù)字為0,其中編號(hào)3750的字出現(xiàn)的次數(shù)最多,編號(hào)3133的字出現(xiàn)的次數(shù)最少,僅出現(xiàn)一次,其中字符3750、字符900和字符648在20w新聞的覆蓋率接近99%,很有可能是標(biāo)點(diǎn)符號(hào)。
          5. 900很有可能是句號(hào),2662和885則很有可能為感嘆號(hào)和問(wèn)號(hào),3750出現(xiàn)頻率很高但是基本不在新聞最后出現(xiàn),因此初步判斷為逗號(hào)。按照這種劃分,訓(xùn)練集中每條新聞平均句子個(gè)數(shù)約為19。
          6. 在訓(xùn)練集中,不同類別新聞出現(xiàn)詞匯有特色。但是需要把共有的常用詞停用。自然想到利用TF-IDF編碼方式。


          往期精彩回顧





          獲取一折本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開:

          https://t.zsxq.com/yFQV7am

          本站qq群1003271085。

          加入微信群請(qǐng)掃碼進(jìn)群:

          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  波多野吉衣一区二区三区 | 日韩美女一级a黄片 | 激情五月天激情 | 成人色站第一区 | 日屄影院 |