1. 程式人生 > >獨熱(one-hot)編碼的tensorflow實現

獨熱(one-hot)編碼的tensorflow實現

一、獨熱編碼

獨熱編碼,又稱一位有效碼,用序列化的數字(只有0和1)表達特徵。主要思路是使用N位數字對N種情況進行編碼。

舉個例子,對[0,1,2,3]分別進行編碼。由於有4種情況,序列的長度為4,對應數字的位置1,其餘置0。所以:

[1,0,0,0]

[0,1,0,0]

[0,0,1,0]

[0,0,0,1]

二、幾個必要函式

掌握了獨熱編碼的規律,我們先來看一段程式碼,瞭解幾個必要的函式。

import tensorflow as tf

#建立一維向量a和b,shape均為(3, )

a = tf.constant([1,2,3])

b = tf.constant([4,5,6])

 

#a和b在一維上連線,c的shape為(6, )

c = tf.concat([a,b],0)

#由於a和b是一維向量,無法連線,會報錯

#c1 = tf.concat([a,b],1)

 

#將a和b擴充為二維向量,二者的shape均為(3,1)

t1 = tf.expand_dims(a,1)

t2 = tf.expand_dims(b,1)

 

#分別在第二維和第一維上連線

concated = tf.concat([t1,t2],1)

concated1 = tf.concat([t1,t2],0)

 

#檢視結果

with tf.Session() as sess:

  print(a,a.shape)

  print(b,b.shape)

  print(sess.run(t1),t1.shape)

  print(sess.run(t2),t2.shape)

  print(sess.run(c),c.shape)

  print(sess.run(concated),concated.shape)#(3,2)

  print(sess.run(concated1),concated1.shape)#(6,1)

 

tf.concat(values,dim,name='concat')

在某維上連線兩個向量的函式。

Values - 需要連線的向量

Dim - 維數。0表示第一維,1表示第二維

由上面的例子可知,維度為(3,1)和(3,1)的兩個向量,在第一維上連線,就是(6,1);在第二維連線,就是(3,2).

注意:有的版本可能是tf.concat(dim,values),具體可以自行實驗。

 

tf.expand_dims(input, axis=None, name=None, dim=None)

擴充向量的維數。

由上面的例子可知,使用t1 = tf.expand_dims(a,1)將向量[1,2,3]擴充為[[1],[2],[3]],從原來的(3,)變為(3,1),便於在第二維上連線concat。

 

 三、獨熱編碼實現

接下來看一段實際程式碼,瞭解獨熱編碼究竟如何生成。

為了方便理解,假設現在我們要對5張手寫數字進行分類,這些數字的標籤labels的範圍是0~9,形成(5, )的行向量,為[5,4,3,8,7]。

labels = [5,4,3,8,7]

NUM_CLASSES = 10

batch_size = tf.size(labels)

#labels表示圖片的標籤,5張圖片有5個標籤。Batch_size=5

labels = tf.expand_dims(labels, 1)

#擴充維數,將(5,)擴充為(5,1),裡面的內容不變:[[5],[4],[3],[8],[7]]

indices = tf.expand_dims(tf.range(0, batch_size, 1), 1)

#擴充維數。由於batch_size=(5, ),迴圈之後生成5*1的矩陣:[[0],[1],[2],[3],[4]]

concated = tf.concat(1, [indices, labels])

#將indices和labels在第二維連線,形成5*2的矩陣:[[0,5],[1,4],[2,3],[3,8],[4,7]]

onehot_labels = tf.sparse_to_dense(
concated, tf.stack([batch_size, NUM_CLASSES]), 1.0, 0.0)

#轉化為獨熱編碼。

#tf.pack()將兩個向量打包成一個。由於batch_size=5和NUM_CLASSES=10都是數,合併為行向量:[5,10]

#tf.sparse_to_dense()將稀疏矩陣轉密集矩陣。stack()函式指定生成的矩陣的shape為5*10,concated指定更換值的座標,1.0表示將concated指定座標的值更換為1,0.0表示其餘座標值置0.

最終結果: 

def sparse_to_dense(sparse_indices,
                    output_shape,
                    sparse_values,
                    default_value=0,
                    validate_indices=True,
                    name=None):

幾個引數的含義: 

sparse_indices: 元素的座標[[0,0],[1,2]] 表示(0,0),和(1,2)處有值 

output_shape: 得到的密集矩陣的shape 

sparse_values: sparse_indices座標表示的點的值,可以是0D或者1D張量。若0D,則所有稀疏值都一樣。若是1D,則len(sparse_values)應該等於len(sparse_indices) 

default_values: 預設點的預設值
tf.pack() ===> tf.stack(values, name = "pack")

Values表示輸入的tensor,實現將兩個tensor打包成一個。

        例子:

          a = tf.constant([1,2,3])   b=tf.constant([4,5,6])

          sess.run([a,b])

          輸出:[array([1, 2, 3]), array([4, 5, 6])]

          sess.run(tf.stack([a,b],name='rank')) 

          輸出:[[1,2,3],[4,5,6]]