1

我有一个小型的研究项目,我尝试解码一些验证码图片。我用Tensorflow 0.9 convnet实施的基础上,MNIST例子(https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/3_NeuralNetworks/convolutional_network.py用convnet识别验证码,如何定义丢失函数

我的代码可以在GitHub上https://github.com/ksopyla/decapcha/blob/master/decaptcha_convnet.py

我尝试做重现描述的想法:

其中特定的字符序列被编码为一个二进制向量。在我的情况下的验证码中包含最多20个拉丁字符,每个字符被编码为63暗淡的二元载体,其中1个比特被设定在位置,根据:

  • 数字“0-9” - 在0- 1位9
  • 大字母 'AZ' - 1在位置10-35
  • 小字母 'AZ' - 1个atposition 36-61
  • 位置62被保留用于空白字符 ''(更短的话,然后20个字符是填充''多达20个)

所以最后当我连接所有20个字符时,我得到了20 * 63昏暗的矢量,我的网络应该学习。我的主要问题是如何为优化器定义适当的损失函数。

架构我的网络的:

  1. CONV 3x3x32 - > RELU - >池(K = 2) - >差
  2. CONV 3x3x64 - > RELU - >池(K = 2) - >差
  3. CONV 3x3x64 - > RELU - >池(K = 2) - >差
  4. FC 1024 - > RELU - >差
  5. 输出20 * 63 -

所以我的主要问题是如何为优化器定义损失以及如何评估模型。我有尝试这样的事情

# Construct model 
pred = conv_net(x, weights, biases, keep_prob) 

# Define loss and optimizer 

#split prediction for each char it takes 63 continous postions, we have 20 chars 
split_pred = tf.split(1,20,pred) 
split_y = tf.split(1,20,y) 


#compute partial softmax cost, for each char 
costs = list() 
for i in range(20): 
    costs.append(tf.nn.softmax_cross_entropy_with_logits(split_pred[i],split_y[i])) 

#reduce cost for each char 
rcosts = list() 
for i in range(20): 
    rcosts.append(tf.reduce_mean(costs[i])) 

# global reduce  
loss = tf.reduce_sum(rcosts) 
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) 


# Evaluate model 

# pred are in format batch_size,20*63, reshape it in order to have each  character prediction 
# in row, then take argmax of each row (across columns) then check if it is  equal 
# original label max indexes 
# then sum all good results and compute mean (accuracy) 

#batch, rows, cols 
p = tf.reshape(pred,[batch_size,20,63]) 
#max idx acros the rows 
#max_idx_p=tf.argmax(p,2).eval() 
max_idx_p=tf.argmax(p,2) 

l = tf.reshape(y,[batch_size,20,63]) 
#max idx acros the rows 
#max_idx_l=tf.argmax(l,2).eval() 
max_idx_l=tf.argmax(l,2) 

correct_pred = tf.equal(max_idx_p,max_idx_l) 
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))enter code   here 

我尽量拆分从输出的每个字符并做SOFTMAX及cross_entropy每个字符separatelly,然后将所有的成本。但我已经将tensorflow函数与普通的python列表混合在一起,我可以这样做吗?张量流引擎会理解这一点吗?我可以使用哪些tensorflow函数来代替python列表?

精度以类似的方式计算,输出重新整形为20x63,我从每一行取得argmax,而不是与真正编码的char进行比较。

当我运行这个损失函数正在减少,但准确度上升然后下降。 此图显示了它的样子https://plon.io/files/57a0a7fb4bb1210001ca0476loss_function

我将不胜感激任何进一步的评论,我已经做出的错误或想法实施。

+0

在较新的TF版本中,您可以使用Python列表作为'reduce_sum'的输入。这相当于首先在Python列表中调用'tf.pack'将其转换为TensorFlow张量。精确度图看起来很奇怪,但是请注意,当交叉熵损失非常大时,如果交错熵为百万,那么交叉熵的降低不一定会提高准确性。我会添加L2罚款正规化器,并尝试等到交叉熵接近于零。此外,它有助于开始简单的问题(即只有数字),以了解等待多久的意义 –

+0

我想知道这个问题 'loss = tf.nn.sigmoid_cross_entropy_with_logits(pred,y)' would not更合适。 以前的方法使用'softmax_cross_entrophy_with_logits',但类应该是异常的,所以我分割每个字符计算softmax_cross_entropy并且按顺序对所有20个字符求和。 – ksopyla

+0

真正的问题是数据规范化,我的Xdata是矩阵[N,D]当我规范化图像,然后网络开始学习模式 'x_mean = Xdata.mean(axis = 0) x_std = Xdata.std(axis = 0 ) X =(Xdata-x_mean)/(x_std + 0.00001)' – ksopyla

回答

1

真正的问题是我的网络卡住了,网络输出对于任何输入都是不变的。

当我将损失函数更改为loss = tf.nn.sigmoid_cross_entropy_with_logits(pred,y)并正常化输入时,网络开始学习模式。

标准化(。减去平均值和由STD除)有很大帮助,

扩展数据是矩阵[N,d]

x_mean = Xdata.mean(axis=0) 
x_std = Xdata.std(axis=0) 
X = (Xdata-x_mean)/(x_std+0.00001) 

数据预处理是关键,这是值得读http://cs231n.github.io/neural-networks-2/#data-preprocessing