本文作者:Ovien
自由團隊將從0到1 手把手教各位讀者學會(1)Python基礎語法、(2)Python Web 網頁開發框架 – Django 、(3)Python網頁爬蟲 – 周易解夢網、(4)Tensorflow AI語言模型基礎與訓練 – LSTM、(5)實際部屬AI解夢模型到Web框架上。
AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源
本篇文章將帶大家進行 NLP 前段資料處理的實作 (本篇實作使用 colab)
!git clone https://github.com/ken19980727/emoji.git
Cloning into 'emoji'...remote: Enumerating objects: 6, done. remote: Counting objects: 100% (6/6), done. remote: Compressing objects: 100% (5/5), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (6/6), done.
!unzip /content/emoji/data.zip
這是我們的資料集,雖然有很多個檔案,但我們今天的實作只會用到其中兩個資料。
這個套件是將代號轉變成表情符號的工具,接下來會有實際的操作和詳細說明
!pip install emoji
Collecting emoji Downloading https://files.pythonhosted.org/packages/ff/1c/1f1457fe52d0b30cbeebfd578483cedb3e3619108d2d5a21380dfecf8ffd/emoji-0.6.0.tar.gz (51kB) |████████████████████████████████| 51kB 1.8MB/s Building wheels for collected packages: emoji Building wheel for emoji (setup.py) ... done Created wheel for emoji: filename=emoji-0.6.0-cp36-none-any.whl size=49716 sha256=b0cb86566420299a4f4558c19a9ac6f00d33c57c3647d8e08188f7932f2f3af7 Stored in directory: /root/.cache/pip/wheels/46/2c/8b/9dcf5216ca68e14e0320e283692dce8ae321cdc01e73e17796 Successfully built emoji Installing collected packages: emoji Successfully installed emoji-0.6.0
import numpy as np import emoji import matplotlib.pyplot as plt import pandas as pdimport emoji from sklearn.metrics import confusion_matrix from emoji import emojize
除了emoji
之外其他的大家一定都不陌生
再來,我們利用pd.read_csv
將csv資料讀進來
data = pd.read_csv('/content/data/emojify_data.csv',names = ['sentences','labels',3,4]) data_dev = pd.read_csv('/content/data/tesss.csv',names = ['sentences','labels'])
我們讀進兩筆data,第一個為train用,第二個valid用,而括號的第一欄是路徑,第二個是欄位名稱
data_dev
X_train = [i for i in data['sentences']] y_train = [i for i in data['labels']] X_valid = [i[:-1] for i in data_dev['sentences']] # clean the data y_valid = [i for i in data_dev['labels']] print(f'X_train length : {len(X_train)}.') print(f'y_train length : {len(y_train)}.') print(f'X_valid length : {len(X_valid)}.') print(f'y_valid length : {len(y_valid)}.')
可以發現X_valid
我取每個句子並去掉最後一個字元,原因是因為這筆資料保留的\t
跳脫字元,但我們不需要,所以去除(可以自己print
出來)
X_train length : 183. y_train length : 183. X_valid length : 56. y_valid length : 56.
前面有提到emoji
,他是可以將str
轉成可視的表情符號
emoji_dictionary = {"0": "\u2764\uFE0F", # :heart: prints a black instead of red heart depending on the font "1": ":baseball:", "2": ":smile:", "3": ":disappointed:", "4": ":fork_and_knife:"} def label_to_emoji(label): return emoji.emojize(emoji_dictionary[str(label)])
idx = 3 print(f'before emoji convert : \n{X_train[idx]} {y_train[idx]}') print('') print(f'after emoji convert : \n{X_train[idx]} {label_to_emoji(y_train[idx])}')
before emoji convert : throw the ball 1 after emoji convert : throw the ball ⚾
print(emoji.emojize('\u2764\uFE0F')) print(emoji.emojize(':baseball:')) print(emoji.emojize(':smile:', use_aliases=True)) print(emoji.emojize(":disappointed:", use_aliases=True)) print(emoji.emojize(':fork_and_knife:'))
❤️ ⚾ ? ? ?
idx
)idx = 2print(f'before emoji convert : \n{X_train[idx]} {y_train[idx]}') print('') print(f'after emoji convert : \n{X_train[idx]} {label_to_emoji(y_train[idx])}')
before emoji convert : I am upset 3 after emoji convert : I am upset ?
np.eye()
這個funcitonnp.eye(5)
array([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]])
這個 function 可以產生一個對稱的 n*n 的矩陣
因此利用其特性來做one hot encoding,方法有很多種,大家可以 brainstorming 一下
def convert_to_one_hot(Y, C): Y_oh = [np.eye(C)[i] for i in Y] return Y_oh y_oh_train = convert_to_one_hot(y_train, C = 5) y_oh_valid = convert_to_one_hot(y_valid, C = 5)
idx = 7 print(f'train : {y_train[idx]} is converted into one hot : {y_oh_train[idx]}') print(f'valid : {y_valid[idx]} is converted into one hot : {y_oh_valid[idx]}')
train : 3 is converted into one hot : [0. 0. 0. 1. 0.] valid : 2 is converted into one hot : [0. 0. 1. 0. 0.]
文字也要轉成index(索引),先建立一個words來存入全部的字(不重複)
words = [] for i in X_train: for j in i.split(): if j not in words: words.append(j) words.append('unk') words.append('pad')len(words)
335
可以看到總共有333+2個字,至於unk
、pad
待會兒會用到。
建立一個字典,讓每個字都有對應的index word2idx
,每個index也有對應的字idx2word
方便查表。
word2idx = {w: i for i, w in enumerate(words)} idx2word = {i: w for i, w in enumerate(words)} word2idx['unk']
idx = 24print(f'before split : {X_train[idx]}') print('') print(f'after split : {[word2idx[j] for j in X_train[idx].split()]}')
before split : family is all I haveafter split : [68, 2, 69, 7, 47]
X_train_int = [[word2idx[j] for j in i.split()] for i in X_train] X_valid_int = [] for i in X_valid: x_val_ = [] for j in i.split(): if j in words: x_val_.append(word2idx[j]) else: x_val_.append(word2idx['unk']) X_valid_int.append(x_val_)
這裡可以看到X_train_int
沒有複雜的判斷式,但為何X_valid_int
要呢?因為當初在建字典和辭庫時,是以X_train
的為主,所以X_valid_int
可能會有字典和辭庫沒有的字,遇到這種字一律使用unk。
這時候就會有熱心的讀者好奇,變 unk 會不會影響 model 的成效?
其實不會有任何影響,因為模型不會 train 到 unk 的數據,所以 model 在做預測的時候,並不會預測到 unk 的結果喔!
之前有說過,如果要用 gpu 加速的話,就要將資料全部轉成長度一致的矩陣,我們來看一下最長的句子長度
tr_maxLen = len(max(X_train_int, key=len)) print(f'train max length : {tr_maxLen}') va_maxLen = len(max(X_valid_int, key=len)) print(f'valid max length : {va_maxLen}')
train max length : 10valid max length : 8
def padding(X,maxlen): for i in X: for pad in range(maxlen-len(i)): i.append(word2idx['pad']) return X X_train_int = padding(X_train_int,tr_maxLen) X_valid_int = padding(X_valid_int,tr_maxLen)
我們將最長的長度設為tr_maxLen
,讓tr_maxLen
減去每個句子的長度,之間的差就是要填充的長度,我們再將word2idx['pad']
填入
print(f'train max length : {len(max(X_train_int, key=len))}') print(f'valid max length : {len(max(X_valid_int, key=len))}')
train max length : 10 valid max length : 10
到這裡,讀者們可以發現:NLP 的資料處理是非常複雜且多元的,視不同狀態,資料都必須做不同的調整方能供 AI 模型做進一步使用。
自由團隊 官方網站:https://aifreeblog.herokuapp.com/
自由團隊 Github:https://github.com/AI-FREE-Team/
自由團隊 粉絲專頁:https://www.facebook.com/AI.Free.Team/
自由團隊 IG:https://www.instagram.com/aifreeteam/
自由團隊 Youtube:https://www.youtube.com/channel/UCjw6Kuw3kwM_il39NTBJVTg/
文章同步發布於:第十二屆 IT 挑戰賽部落格