現在就來練習如何將拿到的原始文本data,轉化為向量吧(還是透過Keras工具,呵呵...)。
在http://mng.bz/0tIo 可以下在IMDb原始文本,將下載好的data 解壓縮後,放在路徑'C:\\Users\\lido_lee\\Downloads\\aclImdb'
#將文本讀取存放並分類 import os imdb_dir = 'C:\\Users\\lido_lee\\Downloads\\aclImdb' train_dir = os.path.join(imdb_dir, 'train') labels = [] #建立一個存放label 的list texts = [] #建立一個存放文本 的list for label_type in ['neg','pos']: dir_name = os.path.join(train_dir, label_type) for fname in os.listdir(dir_name): if fname[-4:] == '.txt': # 'cp950' error 需在open中加入(encoding = 'utf-8-sig') f = open(os.path.join(dir_name, fname), encoding = 'utf-8-sig') texts.append(f.read()) f.close() if label_type == 'neg': labels.append(0) else: labels.append(1)
來看看存入的資料 & label
>>>texts[0]
"Story of a man who has unnatural feelings for a pig. Starts out with a opening scene that is a terrific example of absurd comedy. A formal orchestra audience is turned into an insane, violent mob by the crazy chantings of it's singers. Unfortunately it stays absurd the WHOLE time with no general narrative eventually making it just too off putting. Even those from the era should be turned off. The cryptic dialogue would make Shakespeare seem easy to a third grader. On a technical level it's better than you might think with some good cinematography by future great Vilmos Zsigmond. Future stars Sally Kirkland and Frederic Forrest can be seen briefly."
>>>labels[0]0 ==>表示'neg'
接著要來了解如何對文本資料做分詞(Tokenizer)&序列預處理pad_sequences ,我們會用到Keras的 Tokenizer ,見連結。
函數如下:
keras.preprocessing.text.Tokenizer(num_words=None,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~ ',
lower=True,
split=' ',
split=' ',
char_level=False,
oov_token=None,
document_count=0)
其中參數表示:
序列預處理pad_sequences 將多個序列截斷或補齊為相同長度。
函數如下:
其中參數表示:
- num_words: 需要保留的最大詞數,基於詞頻。只有最常出現的 num_words 詞會被保留。
- filters: 一個字符串,其中每個元素是一個將從文本中過濾掉的字符。默認值是所有標點符號,加上製表符和換行符,減去 ' 字符。
- lower: 布爾值。是否將文本轉換為小寫。
- split: 字符串。按該字符串切割文本。
- char_level: 如果為 True,則每個字符都將被視為標記。
- oov_token: 如果給出,它將被添加到 word_index 中,並用於在 text_to_sequence 調用期間替換詞彙表外的單詞。
默認情況下,刪除所有標點符號,將文本轉換為空格分隔的單詞序列(單詞可能包含 ' 字符)。這些序列然後被分割成標記列表。然後它們將被索引或向量化。
- fit_on_text(texts) 使用一系列文檔來生成token詞典,texts為list類,每個元素為一個文檔。
- texts_to_sequences(texts) 將多個文檔轉換為word下標的向量形式,shape為[len(texts),len(text)] -- (文檔數,每條文檔的長度)
- texts_to_matrix(texts) 將多個文檔轉換為矩陣表示,shape為[len(texts),num_words]
Tokenizer 的属性函數:
- word_counts:字典,將單詞(字符串)映射為它們在訓練期間出現的次數。僅在調用fit_on_texts之後設置。
- word_docs: 字典,將單詞(字符串)映射為它們在訓練期間所出現的文檔或文本的數量。僅在調用fit_on_texts之後設置。
- word_index: 字典,將單詞(字符串)映射為它們的排名或者索引。僅在調用fit_on_texts之後設置。
- document_count: 整數。分詞器被訓練的文檔(文本或者序列)數量。僅在調用fit_on_texts或fit_on_sequences之後設置。
函數如下:
keras.preprocessing.sequence.pad_sequences(sequences,
maxlen=None,
dtype='int32',
padding='pre',
truncating='pre',
value=0)
經過大概了解 Tokenizer & pad_sequences 怎麼使用之後,我們將texts list進行分詞處理存進sequences中,然後將處理後的分詞建立一個字典word_index,最後將sequences透過pad_sequences 處理轉化成長度為maxlen的data(np矩陣)。
Found 88582 unique tokens.
Shape of data tensor: (25000, 200)
Shape of label tensor: (25000,)
接著來到文本與序列預處理的最後階段,劃分訓練集&驗證集。
我們會需要將資料打亂,
將資料與標籤順序打亂後,後還是互相對應的。
利用在python中 a,b =b,a 的語法,直接做swap,像似 [a,b] = [b,a] = array[1,2] = array[2,1] 類似概念。
舉個例:
['e' 'f' 'c' 'i' 'g' 'h' 'a' 'b' 'j' 'd']
得到互相對應的array,就是我們要的。
最後將訓練集&驗證集打亂後分配好:
maxlen=None,
dtype='int32',
padding='pre',
truncating='pre',
value=0)
- sequences:浮點數或整數構成的兩層嵌套列表。
- maxlen:None或整數,為序列的最大長度。大於此長度的序列將被截短,小於此長度的序列將在後部填0。
- dtype:返回的numpy array的數據類型。
- padding:‘pre’或‘post’,確定當需要補0時,在序列的起始還是結尾補。
- truncating:‘pre’或‘post’,確定當需要截斷序列時,從起始還是結尾截斷。
- value:浮點數,此值將在填充時代替默認的填充值0。
該函數將一個 num_samples 的序列(整數列表)轉化為一個 2D Numpy 矩陣,其尺寸為 (num_samples, num_timesteps)。 num_timesteps 要么是給定的 maxlen 參數,要么是最長序列的長度。比 num_timesteps 短的序列將在末端以 value 值補齊。比 num_timesteps 長的序列將會被截斷以滿足所需要的長度。補齊或截斷發生的位置分別由參數 pading 和 truncating 決定。向前補齊為默認操作。
經過大概了解 Tokenizer & pad_sequences 怎麼使用之後,我們將texts list進行分詞處理存進sequences中,然後將處理後的分詞建立一個字典word_index,最後將sequences透過pad_sequences 處理轉化成長度為maxlen的data(np矩陣)。
#對數據進行分詞 from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences import numpy as np maxlen = 200 training_samples = 20000 validation_samples = 10000 max_words = 10000 #利用 Keras Tokenizer 過濾文本的單詞 tokenizer = Tokenizer(num_words=max_words) #接續 Tokenizer之後使用.fit_on_texts#將過濾的文本存入list tokenizer.fit_on_texts(texts) sequences = tokenizer.texts_to_sequences(texts) word_index = tokenizer.word_index print('Found %s unique tokens.' % len(word_index)) data = pad_sequences(sequences, maxlen=maxlen) labels = np.asarray(labels) print('Shape of data tensor:', data.shape) print('Shape of label tensor:', labels.shape)都轉化為numpy.ndarray之後,print出來的結果:
Found 88582 unique tokens.
Shape of data tensor: (25000, 200)
Shape of label tensor: (25000,)
接著來到文本與序列預處理的最後階段,劃分訓練集&驗證集。
我們會需要將資料打亂,
將資料與標籤順序打亂後,後還是互相對應的。
利用在python中 a,b =b,a 的語法,直接做swap,像似 [a,b] = [b,a] = array[1,2] = array[2,1] 類似概念。
舉個例:
import numpy as np a = [1,2,3,4,5,6,7,8,9,10] b = ['a','b','c','d','e','f','g','h','i','j'] a = np.asarray(a) b = np.asarray(b) indices = np.arange(len(a)) np.random.shuffle(indices) a = a[indices] b = b[indices] print(a ,"\n" ,b)[ 5 6 3 9 7 8 1 2 10 4]
['e' 'f' 'c' 'i' 'g' 'h' 'a' 'b' 'j' 'd']
得到互相對應的array,就是我們要的。
最後將訓練集&驗證集打亂後分配好:
#將數據劃分為訓練集和驗證集 """ 首先要打亂數據,因為一開始數據中的樣本是排好序的 (所有負面評論都在前面,然後是所有正面評論) """ indices = np.arange(data.shape[0]) np.random.shuffle(indices) data = data[indices] labels = labels[indices] x_train = data[:training_samples] y_train = labels[:training_samples] x_val = data[training_samples: training_samples + validation_samples] y_val = labels[training_samples: training_samples + validation_samples]
沒有留言:
張貼留言