我剛剛在我的機器學習生涯的開始,並想創建簡單的CNN來分類2種不同的樹葉(屬於2種不同樹種)。在收集大量的樹葉圖片之前,我決定在Tensorflow中創建非常小巧,簡單的CNN,並僅在一幅圖像上進行訓練,以檢查代碼是否正常。我將大小爲256x256(x 3通道)的照片標準化爲< 0,1>,並創建了4層(2 conv和2 dense)網絡。不幸的是,從一開始,損失幾乎總是趨向於一些常數值(通常是一些整數)。我認爲圖片有些問題,所以我用相同尺寸的隨機數組替換它。不幸的是,損失仍然不變。有時網絡似乎在學習,因爲損失在減少,但大多數時候從一開始就是不變的。任何人都可以幫助解釋,爲什麼這樣呢?我讀過一個例子的培訓是檢查你的代碼是否缺乏錯誤的最好方法,但是我與它鬥爭的時間越長,我越是看不到。CNN在Tensorflow - 損失保持不變
這是我的代碼(基於此TensorFlow教程1)。我使用了指數線性單位,因爲我認爲我的問題是由初始化不良的ReLU中0梯度引起的。
import matplotlib.pyplot as plt
import numpy as np
from numpy import random
from sklearn import utils
import tensorflow as tf
#original dataset of 6 leaves
# input = [ndimage.imread("E:\leaves\dab1.jpg"),
# ndimage.imread("E:\leaves\dab2.jpg"),
# ndimage.imread("E:\leaves\dab3.jpg"),
# ndimage.imread("E:\leaves\klon1.jpg"),
# ndimage.imread("E:\leaves\klon2.jpg"),
# ndimage.imread("E:\leaves\klon3.jpg")]
#normalize each image (originally uint8)
#input=[input/255 for i in range(len(input))
#temporary testing dataset, mimicking 6 images, each 3-channel, of dimension 256x256
input=[random.randn(256,256,3)]
# random.randn(256, 256, 3),
# random.randn(256, 256, 3),
# random.randn(256, 256, 3),
# random.randn(256, 256, 3),
# random.randn(256, 256, 3)]
#each image belong to one of two classes
labels=[[1]]#,[1,0],[1,0],[0,1],[0,1],[0,1]]
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.truncated_normal(shape, stddev=.1)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
x = tf.placeholder(tf.float32, shape=[None, 256,256,3])
y_ = tf.placeholder(tf.float32, shape=[None, 1])
x_image = tf.reshape(x, [-1,256,256,3])
#first conv layer
W_conv1 = weight_variable([5,5, 3,8])
b_conv1 = bias_variable([8])
h_conv1 = tf.nn.elu(conv2d(x_image, W_conv1) + b_conv1)
#second conv layer
W_conv2 = weight_variable([5,5, 8,16])
b_conv2 = bias_variable([16])
h_conv2 = tf.nn.elu(conv2d(h_conv1, W_conv2) + b_conv2)
#first dense layer
W_fc1 = weight_variable([256*256*16, 10])
b_fc1 = bias_variable([10])
out_flat = tf.reshape(h_conv2, [-1, 256*256*16])
h_fc1 = tf.nn.elu(tf.matmul(out_flat, W_fc1) + b_fc1)
#second dense layer
W_fc2 = weight_variable([10, 1])
b_fc2 = bias_variable([1])
h_fc2 = tf.nn.elu(tf.matmul(h_fc1, W_fc2) + b_fc2)
#tried also with softmax with logits
cross_entropy=tf.losses.mean_squared_error(predictions=h_fc2, labels=y_)
train_step = tf.train.AdamOptimizer(1e-3).minimize(cross_entropy)
print("h2", h_fc2.shape)
print("y", y_.shape)
sess=tf.Session()
sess.run(tf.global_variables_initializer())
loss = []
for i in range(10):
sess.run(train_step, feed_dict={x:input, y_:labels})
input, labels = utils.shuffle(input, labels)
loss.append(sess.run(cross_entropy, feed_dict={x:input, y_:labels}))
print(i, " LOSS: ", loss[-1])
np.set_printoptions(precision=3, suppress=True)
for i in range(len(input)):
print(labels[i], sess.run(h_fc2, feed_dict={x:[input[i]], y_:[labels[i]]}))
plt.plot(loss)
plt.show()
在這裏的是我的嘗試列表:
- 底座上面的代碼中損失的結果幾乎總是等於4.0完全相同
- 擴大培訓時間爲100個時代。原來,實現不斷損失的可能性增加了。這很奇怪,因爲在我看來,在訓練的早期階段,時代的數量應該會改變任何事情。
- 我把特徵圖的數量更改爲I層中的32,II層中的64和緻密層中的100個神經元
- 因爲我的輸出是二進制的,所以最初我只使用單個輸出。我將它改爲排除2個輸出。它將損失改爲2.5。事實證明,我的輸出傾向於[-1,-1],而標籤是[1,0]
- 我嘗試了各種學習率,從0.001到0.00005
- 我初始化了標準偏差的權重和偏差等於2而不是0.1。損失似乎減少了,但是達到了很高的價值,如1e10。所以我把時代的數量從10個改爲100個,而且從一開始,損失就是2.5個。在回到10個時期後,損失仍然是2.5
- 我擴展了數據集到6個元素。損失與之前相同。
有沒有人有任何想法,爲什麼會發生這種情況?據我所知,如果網絡不能一概而論,損失不會減少,反而會增加/波動,但不會保持不變?
我以前用tf.nn.sigmoid_cross_entropy_with_logits嘗試過,然後用tf.losses.mean_squared_error替換它而不更改變量名稱(cross_entrophy) - 我的不好:)我在正常化後檢查照片並非空白,它們被轉換爲浮動他們的價值被擠壓到<0,1>。正如我所說,我用浮點值和標準偏差= <0.1; 2>隨機numpy陣列替換我的照片。刪除多餘的呼叫後,開始減少,但現在趨向於恰好爲2.0的值。事實證明,輸出幾乎都是-1的所有向量。我不知道爲什麼,我不使用-1的地方 – tech2nick