Day27 - 人工智慧 VIII.

斜槓學習 – 零基礎成為 AI 解夢大師秘笈

本文作者:Ovien

系列文章簡介

自由團隊將從0到1 手把手教各位讀者學會(1)Python基礎語法、(2)Python Web 網頁開發框架 – Django 、(3)Python網頁爬蟲 – 周易解夢網、(4)Tensorflow AI語言模型基礎與訓練 – LSTM、(5)實際部屬AI解夢模型到Web框架上。

學習資源

AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源

實作 Part - 1

本篇文章將帶大家進行 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.

clone完成後,應該會在左邊的side bar

解壓縮檔案

!unzip /content/emoji/data.zip

檢查side bar

這是我們的資料集,雖然有很多個檔案,但我們今天的實作只會用到其中兩個資料。

下載&導入套件

這個套件是將代號轉變成表情符號的工具,接下來會有實際的操作和詳細說明

!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 ⚾

我們總共有5類的答案

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 ?

one hot encoding

在用 one hot 之前,先介紹np.eye()這個funciton

np.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個字,至於unkpad待會兒會用到。

建立一個字典,讓每個字都有對應的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

最長的句子長度為10

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 模型做進一步使用。

想更深入認識 AI . FREE Team ?

自由團隊 官方網站: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 挑戰賽部落格

(繼續閱讀下一篇教學...)