深度学习原理与框架-CNN在文本分类的应用 1.tf.nn.embedding_lookup(根据索引数据从数据中取出数据) 2.saver.restore(加载sess参数)...
1. tf.nn.embedding_lookup(W, X) W的維度為[len(vocabulary_list), 128], X的維度為[?, 8],組合后的維度為[?, 8, 128]
代碼說明一下:即根據(jù)每一行X中的一個數(shù),從W中取出對應(yīng)行的128個數(shù)據(jù),比如X[1, 3]個數(shù)據(jù)是3062,即從W中的第3062行取出128個數(shù)據(jù)
import numpy as np
import tensorflow as tf
data = np.array([[2, 1], [3, 4], [5, 6]])
data = tf.convert_to_tensor(data)
lk = [[0,1],[1,0],[0,0], [1, 1]]
lookup_data = tf.nn.embedding_lookup(data,lk)
init = tf.global_variables_initializer()
sess = tf.Session()
print(sess.run(tf.shape(data)))
print(sess.run(tf.shape(lk)))
print(sess.run(tf.shape(lookup_data)))
print(sess.run(lookup_data)) 2 . saver.restore(sess, './model/-10') 根據(jù)路徑加載sess
這里只需要輸入最后參數(shù)的路徑名,.后面的不需要輸入
代碼說明:主要是使用CNN對名字進行性別的預(yù)測,里面使用了tf.embedding_lookup() 進行維度的轉(zhuǎn)換,原來的維度是?, 8, 經(jīng)過轉(zhuǎn)換后的維度是?, 8, 128?
數(shù)據(jù)說明:使用csv.reader()讀取csv文件,將名字添加到train_x, 將性別為男的,標簽train_y.append([0, 1]), 性別為女的,標簽train_y.append([1,0])
? ? ? ? ? ? ? ? ?構(gòu)建vocabulary_dict 字典,統(tǒng)計每一個詞的詞頻,循環(huán),在字典里面就+1, 對統(tǒng)計好的字典,使用sorted進行排序,獲得排序好后的key的值
? ? ? ? ? ? ? ? ?將每一個詞,使用一個數(shù)字來進行表示,使用enumerate
? ? ? ? ? ? ? ? ?循環(huán)train_x, 獲得每一個詞對應(yīng)的數(shù)字,并添加到列表中,如果列表的長度小于最大長度,使用0進行填充
?
代碼說明:這里的代碼說明:主要從兩部分來進行說明:
第一部分:數(shù)據(jù)的讀取,即train_vec_x, 和train_y的制作
第二部分:模型的構(gòu)建
第三部分:模型的訓(xùn)練操作
?
第一部分:數(shù)據(jù)的讀取,即train_vec_x 和train_y的制作
? ? ? ? ? ? ? 第一步:構(gòu)建train_x 和 train_y, 將讀取數(shù)據(jù)分別添加到train_x 和train_y中
? ? ? ? ? ? ? ? ? ? ? ? 第一步:使用with open('name.csv') 打開文件
? ? ? ? ? ? ? ? ? ? ? ? 第二步:使用csv.reader(csvfile) 讀取文件數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? ? ? 第三步:循環(huán)數(shù)據(jù),判斷數(shù)據(jù)的大小是否等于2,如果等于2,使用tran_x.append(row[0])
? ? ? ? ? ? ? ? ? ? ? ? 第四步:判斷row[1] == ‘男’:如果是train_y.append([0, 1]), 否者train_y.append([1, 0]) 作為每一個名字的標簽
? ? ? ? ? ? ?第二步:構(gòu)造vocabulary_dict 字典,用于統(tǒng)計每個詞對應(yīng)的詞頻
? ? ? ? ? ? ? ? ? ? ? ? 第一步:循環(huán)train_x, 每一個循環(huán)詞表示name
? ? ? ? ? ? ? ? ? ? ? ? 第二步:使用token = [word for word in name] 將名字中的字符串組合成一個列表
? ? ? ? ? ? ? ? ? ? ? ? 第三步:循環(huán)token,如果word in vocabulary_dict, vocabulary_dict[word] += 1, 即詞頻次數(shù)加1, 如果不在,vocabulary_dict[word] = 1,相當于做了一個初始化
? ? ? ? ? ? ? 第三步:vocabulary_list = [' '] + sorted(vocabulary_dict, key=vocabulary_dict.get, reverse=True) , 根據(jù)字典的值進行排序,返回字典的鍵,即每個詞
? ? ? ? ? ? ? 第四步:使用dict((x, y) for (y, x) in emurate(vocabulary_list))? 將每一個詞使用0, 1....相對應(yīng)
? ? ? ? ? ? ? 第五步:循環(huán)train_x, 生成映射的列表
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第一步:構(gòu)造train_vec_x的空列表, 循環(huán)trian_x中的name
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第二步:構(gòu)造name_vec的空列表,使用token = [word for word in name] 將名字分成一個個字的列表
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第三步:循環(huán)token中的word,獲得映射字典中vocab[word], 對應(yīng)的數(shù)字索引,將其添加到name_vec
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第四步:如果name_vec的長度小于最大長度,將name_vec繼續(xù)補零, 即append(0)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第五步:使用train_vec_x.append(name_vec) 將每個name對應(yīng)的數(shù)字映射進行添加
第二部分:構(gòu)建網(wǎng)絡(luò)模型,輸出為模型的預(yù)測結(jié)果,即[None, 2]
? ? ? ? ? ? 第一步:設(shè)置網(wǎng)絡(luò)的基本參數(shù),batch_size, input_size, num_classes, num_batch?
? ? ? ? ? ? 第二步:構(gòu)造網(wǎng)絡(luò)模型的函數(shù),輸入為vocabulary_size, embedding_size, 以及filter_num?
? ? ? ? ? ? 第三步:使用tf.placeholder(tf.int32, [None, input_size])構(gòu)造X初始化,使用tf.placeholder(tf.float32, [None, 2])構(gòu)造y初始化
? ? ? ? ? ? 第四步: with tf.name_scope('embedding') 進行embedding變化
? ? ? ? ? ? ? ? ? ? ? ? ? 第一步:構(gòu)建W = tf.Vairbale(tf.random_normal([vocabulary_size, embedding_size]))?
? ? ? ? ? ? ? ? ? ? ? ? ? 第二步:使用tf.embedding_lookup(W, X) 進行前向的embedding映射,此時的輸出為?, 8, 128
? ? ? ? ? ? ? ? ? ? ? ? ? 第三步:使用tf.expand_dim(embedding_chars, axis=-1) 將維度轉(zhuǎn)換為?, 8, 128, 1?
? ? ? ? ? ? ?第五步: 進行3種卷積核大小的卷積操作
? ? ? ? ? ? ? ? ? ? ? ? ? 第一步:定義三種卷積核尺寸的大小,分為是3, 4, 5, 構(gòu)造output_pool = [] 列表
? ? ? ? ? ? ? ? ? ? ? ? ? 第二步:循環(huán)三種卷積核的大小
? ? ? ? ? ? ? ? ? ? ? ? ? 第三步:構(gòu)造with tf.name_scope('conv_pool %d'%(conv_size, ))
? ? ? ? ? ? ? ? ? ? ? ? ? 第四步:構(gòu)造W的參數(shù),尺寸為[conv_size, embedding_size, 1, num_filter], 構(gòu)造b的參數(shù),尺寸為[num_filter]
? ? ? ? ? ? ? ? ? ? ? ? ? 第五步:使用tf.nn.conv2d進行卷積操作,使用tf.nn.relu進行激活操作
? ? ? ? ? ? ? ? ? ? ? ? ? 第六步:使用tf.nn.max_pool進行池化操作,ksize = [1, input_size - conv_filter + 1, 1, 1] 即為卷積后的大小
? ? ? ? ? ? ? ? ? ? ? ? ? 第七步:將卷積后的結(jié)果添加到output_pool列表中
? ? ? ? ? ? ? ? ? ? ? ? ? 第八步:將output_pool使用tf.concat進行維度的合并操作
? ? ? ? ? ? ? 第六步:對合并后的結(jié)果進行維度的變化,即維度變?yōu)閇-1, 3*128]為了進行后續(xù)的全連接操作
? ? ? ? ? ? ? 第七步:使用with tf.name_scope('dropout') 進行dropout操作,使用的是tf.nn.dropout?
? ? ? ? ? ? ? 第八步:使用with tf.name_scope('output') 構(gòu)造全連接操作
? ? ? ? ? ? ? ? ? ? ? ? ? ?第一步:構(gòu)造W的維度為[3*128, num_class], 構(gòu)造b的維度為[num_class]
? ? ? ? ? ? ? ? ? ? ? ? ? ?第二步:使用tf.nn.xw_plus_b進行tf.matmul(x, w) + b的操作
? ? ? ? ? ? ? ? ? ? ? ? ? ?第三步:返回output結(jié)果
?
第三部分:定義train_network() 進行模型的訓(xùn)練
? ? ? ? ? ? 第一步:使用neture_network(vocabulary_size= len(vocabulary_size)) 獲得輸出output
? ? ? ? ? ? 第二步:使用tf.reduce_mean(tf.nn.softmax...logits()) 定義損失值loss
? ? ? ? ? ? 第三步:使用tf.train.Adaoptimer(1e-3).minimize(loss) 減少損失值操作train_op?
? ? ? ? ? ? 第四步:使用tf.train.Saver(tf.global_variable()) 定義保存函數(shù)Saver?
? ? ? ? ? ? 第五步: 使用with tf.Session() 構(gòu)造sess執(zhí)行函數(shù),使用sess.run()進行變量的初始化
? ? ? ? ? ? 第六步:進行epoch的循環(huán),進行num_batch的循環(huán)
? ? ? ? ? ? 第七步:使用tran_vec_x[i*batch_size:(i+1)*batch]? ?獲得x_batch, 使用train_y[i*batch_size: (i+1)*batch]獲得y_batch?
? ? ? ? ? ? 第八步:使用sess.run([train_op, loss], feed_dict={X:x_batch, y:y_batch})?
? ? ? ? ? ? 第九步:如果迭代1000次,打印epoch, iteration和loss
? ? ? ? ? ? 第十步:迭代兩個epoch,就是用Saver.save()進行sess的保存,
代碼:main.py
import tensorflow as tf
import numpy as np
import csv# 第一部分:數(shù)據(jù)的讀取
# 第一步:創(chuàng)建列表train_x, train_y,將從文件中讀取的名字存儲在train_x, 讀取的性別使用[0, 1] 或者[1, 0]儲存在train_y中
train_x = [] # 創(chuàng)建列表
train_y = []
# 打開文件name.csv
with open('name.csv', 'r', encoding='utf-8') as csvfile:# 使用csv.reader進行讀取,讀取的數(shù)據(jù)為兩列,第一列為名字,第二列為性別data_csv = csv.reader(csvfile)# 循環(huán)讀取的數(shù)據(jù)for row in data_csv:# 如果當前行的大小為2if len(row) == 2:# 將當前行的第一個數(shù)據(jù)及name添加到train_x中train_x.append(row[0])# 如果當前行的第二個數(shù)據(jù)是'男',標簽train_y添加[0, 1]if row[1] == '男':train_y.append([0, 1])else:# 否者標簽train_y添加[1, 0]train_y.append([1, 0])
# 打印最長的名字大小
max_len_name = max([len(name) for name in train_x])
print(max_len_name)
# 把最長的名字長度設(shè)置為8
max_len_name = 8
# 第二步:構(gòu)造詞頻字典,建立詞匯表的字典
vocabulary_dict = {}
# 循環(huán)名字
for name in train_x:# 將名字中的每一個字拆開,變成一個列表token = [word for word in name]# 循環(huán)字列表for word in token:# 如果這個字在詞匯表的字典里,value+=1if word in vocabulary_dict:vocabulary_dict[word] += 1# 不在的話,就把value=1,即vocabulary_dict[word] = 1else:vocabulary_dict[word] = 1# 第三步:對詞頻字典進行根據(jù)value進行排序操作,獲得排序后的列表
vocabulary_list =[' '] + sorted(vocabulary_dict, key=vocabulary_dict.get, reverse=True)# 第四步:使用dict(x, y) 構(gòu)造數(shù)字映射的詞袋
vocab = dict((x, y) for (y, x) in enumerate(vocabulary_list))# 第五步:循環(huán)train_x, 組合名字中詞對應(yīng)的數(shù)字,將train_x中的name轉(zhuǎn)換為數(shù)字列表,如果數(shù)字列表的長度小于8,即.append(0)
train_vec_x = []
for name in train_x:# 構(gòu)造名字的vecname_vec = []# 將name拆分成一個字的列表token = [word for word in name]# 循環(huán)字列表for word in token:# 根據(jù)詞典中的key,獲得value進行添加到name_vecname_vec.append(vocab[word])# 如果name_vec的長度小于8,使用.append(0),補齊長度為8while len(name_vec) < max_len_name:name_vec.append(0)# 將組合好的名字向量添加到train_vec_x中train_vec_x.append(name_vec)##################
# 第二部分:構(gòu)建網(wǎng)絡(luò)模型,輸出結(jié)果為[None, num_class]即每一個類的得分值
# 第一步:構(gòu)建參數(shù)input_size, batch_size, num_classes,num_batch
input_size = max_len_name # 輸入的維度,即為名字的最長距離,即為8
batch_size = 64 # 每個batch大小
num_classes = 2 # 類別結(jié)果
num_batch = len(train_vec_x) // batch_size # 一次樣本經(jīng)過幾個batch
# 第二步:使用tf.placeholder構(gòu)造X和y
X = tf.placeholder(tf.int32, [None, input_size])
y = tf.placeholder(tf.float32, [None, num_classes])
# 構(gòu)造輸入keep_prob的大小,用于進行dropout
dropout_keep_prob = tf.placeholder(tf.float32)
# 第三步:構(gòu)造網(wǎng)絡(luò)的輸入函數(shù)
def neture_network(vocabulary_size, embedding_size=128, filter_num=128):# 第四步:進行embedding前向映射with tf.name_scope('embedding'):# 構(gòu)造W, 大小為[vocabulary_size, embedding_size]W = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))# 使用tf.nn.embedding_lookup進行投影映射,映射后的大小為[?, 8, 128]embedding_chares = tf.nn.embedding_lookup(W, X)# 使用tf.expand_dims增加維度,使其維度變?yōu)閇?, 8, 128, 1]embedding_chares = tf.expand_dims(embedding_chares, axis=-1)# 第五步:進行3個不同卷積尺寸的卷積進行卷積操作,對結(jié)果進行合并# 三種卷積核的大小分別是3, 4, 5conv_sizes = [3, 4, 5]# 構(gòu)造池化結(jié)果的列表pool1_output = []# 循環(huán)不同卷積核大小for conv_size in conv_sizes:# 構(gòu)造with.name_scope參數(shù)的作用范圍with tf.name_scope('conv-padding%d'%(conv_size, )):# 構(gòu)造卷積參數(shù)的W,維度為[conv_size, embedding_size, 1, filter_num]W = tf.Variable(tf.random_uniform([conv_size, embedding_size, 1, filter_num]))# 構(gòu)造卷積參數(shù)的b,維度為[filter_num]b = tf.Variable(tf.constant(0.1, shape=[filter_num]))# 進行卷積操作和激活操作conv = tf.nn.relu(tf.nn.conv2d(embedding_chares, W, strides=[1, 1, 1, 1], padding='VALID') + b)# 進行最大值池化操作,ksize = [1, input_size=conv_size + 1, 1, 1]中間的維度為卷積后的特征層的中間兩個維度pool = tf.nn.max_pool(conv, ksize=[1, input_size - conv_size + 1, 1, 1], strides=[1, 1, 1, 1], padding='VALID')# 池化后的維度大小為[?, 1, 1, 128]pool1_output.append(pool)# 將組合的維度,進行重疊操作,即維度[?, 1, 1 3*128]fcIn = tf.concat(pool1_output, axis=3)# 第六步:進行維度的變化,以進行后續(xù)的全連接操作fcIn = tf.reshape(fcIn, shape=[-1, 3*128])# 第七步:進行dropout操作with tf.name_scope('dropout'):fc_dropout = tf.nn.dropout(fcIn, keep_prob=dropout_keep_prob)# 第八步:進行最后的全連接操作,用于進行類別得分的計算with tf.name_scope('output'):# 構(gòu)造全連接的W,維度為[3*128, 2]W = tf.Variable(tf.random_uniform([3*128, num_classes], -1.0, 1.0))# 構(gòu)造全連接的b,維度為[2]b = tf.Variable(tf.constant(0.1, shape=[num_classes]))# 獲得最后的輸出得分output = tf.nn.xw_plus_b(fc_dropout, W, b)# 返回得分值return output
# 第三部分:進行模型的訓(xùn)練操作
def train_network():# 第一步:調(diào)用neture_network獲得輸出的結(jié)果outputoutput = neture_network(vocabulary_size=len(vocabulary_list))# 第二步:使用tf.reduce_mean(tf.nn.softmax_...logits)獲得損失值lossloss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=output, labels=y))# 第三步:使用自適應(yīng)損失值降低loss的操作train_optrain_op = tf.train.AdamOptimizer(1e-3).minimize(loss)# 第四步:使用tf.train.Saver構(gòu)造存儲sesssaver = tf.train.Saver(tf.global_variables())# 第五步:使用tf.Session()獲得sess執(zhí)行函數(shù),并進行參數(shù)初始化操作with tf.Session() as sess:# 參數(shù)初始化操作sess.run(tf.global_variables_initializer())# 第六步:循環(huán)epoch,循環(huán)num_batchfor e in range(11):for i in range(num_batch):# 第七步:根據(jù)索引值構(gòu)造batch_x和batch_ybatch_x = train_vec_x[i*batch_size:(i+1)*batch_size]batch_y = train_y[i*batch_size:(i+1)*batch_size]# 第八步:使用sess.run執(zhí)行train_op和loss_, _loss = sess.run([train_op, loss], feed_dict={X:batch_x, y:batch_y, dropout_keep_prob:0.7})# 第九步:如果迭代1000次打印結(jié)果if i % 1000 == 0:print('epoch', e, 'iter', i, 'loss:', _loss)# 如果迭代了兩次保存結(jié)果if e % 2 == 0:saver.save(sess, './model/epoch', global_step=e)train_network() 下面對訓(xùn)練好的參數(shù)進行測試,構(gòu)造函數(shù)為test_sex,由于網(wǎng)絡(luò)結(jié)果是相同的,就不需要對上述二部分進行修改,只需要改變第三部分,test_sex(name_list)
第一步:構(gòu)造test_sex進行模型的預(yù)測,輸入為名字的列表
第二步:根據(jù)數(shù)字映射,構(gòu)造train_x?
? ? ? ? ? ? ?第一步:構(gòu)造train_x的空列表
? ? ? ? ? ? ?第二步:循環(huán)name_list,獲得name
? ? ? ? ? ? ?第三步:使用token = [word for word in name] 將名字拆分成一個字的列表,構(gòu)造name_vec
? ? ? ? ? ? ?第四步:循環(huán)token,將name_vec.append(vocan[word]), 將字word轉(zhuǎn)換為數(shù)字
? ? ? ? ? ? ?第五步:如果name_vec的長度小于最大長度8,即使用.append(0)進行補零操作
? ? ? ? ? ? ?第六步:將name_vec添加到train_x列表中,構(gòu)造了train_x?
第三步:調(diào)用neture_network()獲得output
第四步:使用tf.argmax(output, axis=1) 獲得得分值較大索引值,即為類別值
第五步:使用tf.train.Saver() 獲得保存函數(shù)Saver?
第六步:使用with tf.Session() as sess構(gòu)造sess函數(shù)
第七步:使用Saver.restore(sess, './model/-10') 加載sess
第八步:使用sess.run(y_pred, feed_dict={X:train_x, keep_prob=1.0}) 獲得預(yù)測結(jié)果
第九步:循環(huán)預(yù)測結(jié)果,如果是結(jié)果是1,打印該類別為男,如果索引值的結(jié)果為0,打印該類別為女
# 第一步:構(gòu)造test_sex用于進行模型預(yù)測,輸入為name_list
def test_sex(name_list):# 第二步:構(gòu)造進行train_x# 構(gòu)造用于存儲的xx = []# 循環(huán)name列表,獲得當個名字for name in name_list:# 構(gòu)造name_vec列表,用于存儲一個名字的向量name_vec = []# 將名字拆分成字列表token = [word for word in name]# 循環(huán)每個字for word in token:# 將字對應(yīng)的詞袋中的數(shù)字添加到名字的數(shù)字向量中name_vec.append(vocab[word])# 如果名字的數(shù)字向量小于8,則添加0while len(name_vec) < max_len_name:name_vec.append(0)# 將名字的數(shù)字向量添加到詞向量中x.append(name_vec)# 第三步:調(diào)用模型,獲得輸出結(jié)果output = neture_network(vocabulary_size=len(vocabulary_list))# 第四步:使用tf.argmax獲得最大的索引值,0或者1y_pred = tf.argmax(output, axis=1)# 第五步:使用tf.train.Saver() 構(gòu)造Saver函數(shù)saver = tf.train.Saver(tf.global_variables())# 第六步:使用tf.Session() 構(gòu)造執(zhí)行函數(shù)with tf.Session() as sess:# 第七步:加載sess函數(shù)saver.restore(sess, './model/epoch')# 第八步:使用sess.run執(zhí)行y_pred,獲得實際的預(yù)測結(jié)果y_pred_ = sess.run(y_pred, feed_dict={X:x, dropout_keep_prob:1.0})# 第九步:循環(huán)預(yù)測結(jié)果,如果索引值為1,則打印為男的, 否者打印為女的for i in range(len(y_pred_)):if y_pred_[i] == 1:print(name_list[i], '男')else:print(name_list[i], '女')
總結(jié)
以上是生活随笔為你收集整理的深度学习原理与框架-CNN在文本分类的应用 1.tf.nn.embedding_lookup(根据索引数据从数据中取出数据) 2.saver.restore(加载sess参数)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通俗理解tf.name_scope()、
- 下一篇: tf.nn.embedding_look