回答多選項問題,使用softmax函數,對數幾率回歸在多個可能不同值上的推廣。函數返回值是C個分量的概率向量,每個分量對應一個輸出類別概率。分量為概率,C個分量和始終為1。每個樣本必須屬於某個輸出類別,所有可能樣本均被覆蓋。分量和小於1,存在隱藏類別;分量和大於1,每個樣本可能同時屬於多個類別。類別數量為2,輸出概率與對數幾率回歸模型輸出相同。
變量初始化,需要C個不同權值組,每個組對應一個可能輸出,使用權值矩陣。每行與輸入特征對應,每列與輸出類別對應。
鳶尾花數據集Iris,包含4個數據特征、3類可能輸出,權值矩陣4X3。
訓練樣本每個輸出類別損失相加。訓練樣本期望類別為1,其他為0。只有一個損失值被計入,度量模型為真實類別預測的概率可信度。每個訓練樣本損失相加,得到訓練集總損失值。TensorFlow的softmax交叉熵函數,sparse_softmax_cross_entropy_with_logits版本針對訓練集每個樣本只對應單個類別優化,softmax_cross_entropy_with_logits版本可使用包含每個樣本屬於每個類別的概率信息的訓練集。模型最終輸出是單個類別值。
不需要每個類別都轉換獨立變量,需要把值轉換為0~2整數(總類別數3)。tf.stack創建張量,tf.equal把文件輸入與每個可能值比較。tf.argmax找到張量值為真的位置。
推斷過程計算測試樣本屬於每個類別概率。tf. argmax函數選擇預測輸出值最大概率類別。tf.equal與期望類別比較。tf.reduce_meen計算准確率。
import tensorflow as tf#導入TensorFlow庫 import os#導入OS庫 W = tf.Variable(tf.zeros([4, 3]), name="weights")#變量權值,矩陣,每個特征權值列對應一個輸出類別 b = tf.Variable(tf.zeros([3], name="bias"))#模型偏置,每個偏置對應一個輸出類別 def combine_inputs(X):#輸入值合並 print "function: combine_inputs" return tf.matmul(X, W) + b def inference(X):#計算返回推斷模型輸出(數據X) print "function: inference" return tf.nn.softmax(combine_inputs(X))#調用softmax分類函數 def loss(X, Y):#計算損失(訓練數據X及期望輸出Y) print "function: loss" return tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=combine_inputs(X), labels=Y))#求平均值,針對每個樣本只對應單個類別優化 def read_csv(batch_size, file_name, record_defaults):#從csv文件讀取數據,加載解析,創建批次讀取張量多行數據 filename_queue = tf.train.string_input_producer([os.path.join(os.getcwd(), file_name)]) reader = tf.TextLineReader(skip_header_lines=1) key, value = reader.read(filename_queue) decoded = tf.decode_csv(value, record_defaults=record_defaults)#字符串(文本行)轉換到指定默認值張量列元組,為每列設置數據類型 return tf.train.shuffle_batch(decoded, batch_size=batch_size, capacity=batch_size * 50, min_after_dequeue=batch_size)#讀取文件,加載張量batch_size行 def inputs():#讀取或生成訓練數據X及期望輸出Y print "function: inputs" #數據來源:https://archive.ics.uci.edu/ml/datasets/Iris #iris.data改為iris.csv,增加sepal_length, sepal_width, petal_length, petal_width, label字段行首行 sepal_length, sepal_width, petal_length, petal_width, label =\ read_csv(100, "iris.csv", [[0.0], [0.0], [0.0], [0.0], [""]]) #轉換屬性數據 label_number = tf.to_int32(tf.argmax(tf.to_int32(tf.stack([ tf.equal(label, ["Iris-setosa"]), tf.equal(label, ["Iris-versicolor"]), tf.equal(label, ["Iris-virginica"]) ])), 0))#將類名稱轉抽象為從0開始的類別索引 features = tf.transpose(tf.stack([sepal_length, sepal_width, petal_length, petal_width]))#特征裝入矩陣,轉置,每行一樣本,每列一特征 return features, label_number def train(total_loss):#訓練或調整模型參數(計算總損失) print "function: train" learning_rate = 0.01 return tf.train.GradientDescentOptimizer(learning_rate).minimize(total_loss) def evaluate(sess, X, Y):#評估訓練模型 print "function: evaluate" predicted = tf.cast(tf.arg_max(inference(X), 1), tf.int32)#選擇預測輸出值最大概率類別 print sess.run(tf.reduce_mean(tf.cast(tf.equal(predicted, Y), tf.float32)))#統計所有正確預測樣本數,除以批次樣本總數,得到正確預測百分比 with tf.Session() as sess:#會話對象啟動數據流圖,搭建流程 print "Session: start" tf.global_variables_initializer().run() X, Y = inputs() total_loss = loss(X, Y) train_op = train(total_loss) coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) training_steps = 1000#實際訓練迭代次數 for step in range(training_steps):#實際訓練閉環 sess.run([train_op]) if step % 10 == 0:#查看訓練過程損失遞減 print str(step)+ " loss: ", sess.run([total_loss]) print str(training_steps) + " final loss: ", sess.run([total_loss]) evaluate(sess, X, Y)#模型評估 coord.request_stop() coord.join(threads) sess.close()
參考資料:
《面向機器智能的TensorFlow實踐》
歡迎加我微信交流:qingxingfengzi
我的微信公眾號:qingxingfengzigz
我老婆張幸清的微信公眾號:qingqingfeifangz