我正在尝试为英国车牌(https://github.com/matthewearl/deep-anpr)到包含阿拉伯字母的摩洛哥车牌实施Tensorflow神经网络,添加utf-8编码后,我能够生成包含阿拉伯车牌的数据集字母,但是当我尝试进行训练时,最终会出现张量形状错误。这是train_1.py代码
#!/usr/bin/python
# -*- coding: utf-8 -*-
_all__ = (
'train',
)
import functools
import glob
import itertools
import multiprocessing
import random
import sys
import time
import cv2
import numpy
import tensorflow as tf
import common
import gen
import model
DIGITS = "0123456789"
DIGITS_E = "0 1 2 3 4 5 6 7 8 9"
DIGITS_E1 = "0123456789 "
DIGITS_0 = "123456789"
BARRE = "|"
LETTERS = "وهدجبأ"
CHARS = LETTERS + DIGITS + BARRE + DIGITS_E + DIGITS_0 + DIGITS_E1
def generate_code_train():
matricule = "{}{} {}{} {}{} {}{}{}{}".format(
random.choice(DIGITS_0),
random.choice(DIGITS),
random.choice(DIGITS),
random.choice(DIGITS),
random.choice(DIGITS_E1),
random.choice(BARRE),
random.choice(LETTERS),
random.choice(BARRE),
random.choice(DIGITS_0),
random.choice(DIGITS_E1))
#matricule = matricule.decode("utf-8")
return matricule
def code_to_vec(p, code):
def char_to_vec(c):
y = numpy.zeros((len(CHARS),))
y[CHARS.index(c)] = 1.0
return y
code = generate_code_train()
c = numpy.vstack([char_to_vec(c) for c in code])
return numpy.concatenate([[1. if p else 0], c.flatten()])
def read_data(img_glob):
for fname in sorted(glob.glob(img_glob)):
im = cv2.imread(fname)[:, :, 0].astype(numpy.float32) / 255.
code = fname.split("/")[1][9:19]
p = fname.split("/")[1][20] == '1'
yield im, code_to_vec(p, code)
def unzip(b):
xs, ys = zip(*b)
xs = numpy.array(xs)
ys = numpy.array(ys)
return xs, ys
def batch(it, batch_size):
out = []
for x in it:
out.append(x)
if len(out) == batch_size:
yield out
out = []
if out:
yield out
def mpgen(f):
def main(q, args, kwargs):
try:
for item in f(*args, **kwargs):
q.put(item)
finally:
q.close()
@functools.wraps(f)
def wrapped(*args, **kwargs):
q = multiprocessing.Queue(3)
proc = multiprocessing.Process(target=main,
args=(q, args, kwargs))
proc.start()
try:
while True:
item = q.get()
yield item
finally:
proc.terminate()
proc.join()
return wrapped
#@mpgen
def read_batches(batch_size):
g = gen.generate_ims()
def gen_vecs():
for im, c, p in itertools.islice(g, batch_size):
yield im, code_to_vec(p, c)
while True:
yield unzip(gen_vecs())
def get_loss(y, y_):
# Calculate the loss from digits being incorrect. Don't count loss from
# digits that are in non-present plates.
digits_loss = tf.nn.softmax_cross_entropy_with_logits(
logits=tf.reshape(y[:, 1:],
[-1, len(CHARS)]),
labels=tf.reshape(y_[:, 1:],
[-1, len(CHARS)]))
digits_loss = tf.reshape(digits_loss, [-1, 10]) #7 changed to 10
digits_loss = tf.reduce_sum(digits_loss, 1)
digits_loss *= (y_[:, 0] != 0)
digits_loss = tf.reduce_sum(digits_loss)
# Calculate the loss from presence indicator being wrong.
presence_loss = tf.nn.sigmoid_cross_entropy_with_logits(
logits=y[:, :1], labels=y_[:, :1])
presence_loss = 10 * tf.reduce_sum(presence_loss) # 7 changed to 10
return digits_loss, presence_loss, digits_loss + presence_loss
def train(learn_rate, report_steps, batch_size, initial_weights):
"""
Train the network.
The function operates interactively: Progress is reported on stdout, and
training ceases upon `KeyboardInterrupt` at which point the learned weights
are saved to `weights.npz`, and also returned.
:param learn_rate:
Learning rate to use.
:param report_steps:
Every `report_steps` batches a progress report is printed.
:param batch_size:
The size of the batches used for training.
:param initial_weights:
(Optional.) Weights to initialize the network with.
:return:
The learned network weights.
"""
x, y, params = model.get_training_model()
y_ = tf.placeholder(tf.float32, [None, 10 * len(CHARS) + 1]) #7 changed to 10
digits_loss, presence_loss, loss = get_loss(y, y_)
train_step = tf.train.AdamOptimizer(learn_rate).minimize(loss)
best = tf.argmax(tf.reshape(y[:, 1:], [-1, 10, len(CHARS)]), 2) # 7 changed to 10
correct = tf.argmax(tf.reshape(y_[:, 1:], [-1, 10, len(CHARS)]), 2) #7 changed to 10
if initial_weights is not None:
assert len(params) == len(initial_weights)
assign_ops = [w.assign(v) for w, v in zip(params, initial_weights)]
init = tf.initialize_all_variables()
def vec_to_plate(v):
return "".join(CHARS[i] for i in v)
def do_report():
r = sess.run([best,
correct,
tf.greater(y[:, 0], 0),
y_[:, 0],
digits_loss,
presence_loss,
loss],
feed_dict={x: test_xs, y_: test_ys})
num_correct = numpy.sum(
numpy.logical_or(
numpy.all(r[0] == r[1], axis=1),
numpy.logical_and(r[2] < 0.5,
r[3] < 0.5)))
r_short = (r[0][:190], r[1][:190], r[2][:190], r[3][:190])
for b, c, pb, pc in zip(*r_short):
#print "{} {} <-> {} {}".format(vec_to_plate(c), pc,
#vec_to_plate(b), float(pb)) # print command needs to be changed according to python3
print ("{} {} <-> {} {}".format(vec_to_plate(c), pc,
vec_to_plate(b), float(pb)))
num_p_correct = numpy.sum(r[2] == r[3])
print ("B{:3d} {:2.02f}% {:02.02f}% loss: {} "
"(digits: {}, presence: {}) |{}|".format(
batch_idx,
100. * num_correct / (len(r[0])),
100. * num_p_correct / len(r[2]),
r[6],
r[4],
r[5],
"".join("X "[numpy.array_equal(b, c) or (not pb and not pc)]
for b, c, pb, pc in zip(*r_short))))
def do_batch():
sess.run(train_step,
feed_dict={x: batch_xs, y_: batch_ys})
if batch_idx % report_steps == 0:
do_report()
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.95)
with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess:
sess.run(init)
if initial_weights is not None:
sess.run(assign_ops)
test_xs, test_ys = unzip(list(read_data("test/*.png"))[:50])
try:
last_batch_idx = 0
last_batch_time = time.time()
batch_iter = enumerate(read_batches(batch_size))
for batch_idx, (batch_xs, batch_ys) in batch_iter:
do_batch()
if batch_idx % report_steps == 0:
batch_time = time.time()
if last_batch_idx != batch_idx:
print ("time for 60 batches {}".format(
60 * (last_batch_time - batch_time) /
(last_batch_idx - batch_idx)))
last_batch_idx = batch_idx
last_batch_time = batch_time
except KeyboardInterrupt:
last_weights = [p.eval() for p in params]
numpy.savez("weights.npz", *last_weights)
return last_weights
if __name__ == "__main__":
if len(sys.argv) > 1:
f = numpy.load(sys.argv[1])
initial_weights = [f[n] for n in sorted(f.files,
key=lambda s: int(s[4:]))]
else:
initial_weights = None
train(learn_rate=0.001,
report_steps=20,
batch_size=50,
initial_weights=initial_weights)
这是我得到的错误:
Traceback (most recent call last):
File "train_1.py", line 286, in <module>
initial_weights=initial_weights)
File "train_1.py", line 259, in train
do_batch()
File "train_1.py", line 242, in do_batch
feed_dict={x: batch_xs, y_: batch_ys})
File "/usr/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 929, in run
run_metadata_ptr)
File "/usr/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 1128, in _run
str(subfeed_t.get_shape())))
ValueError: Cannot feed value of shape (50, 807) for Tensor u'Placeholder_1:0', which has shape '(?, 621)'
答案 0 :(得分:0)
根据错误消息,问题在于您正在为占位符y_
提供不同形状的值。您输入的占位符y_
的形状为(batch_size, 621)
,但是要填充的batch_ys
的形状为(batch_size, 807)
。
在您的实现中,batch_ys
是由matricule
函数的generate_code_train
变量生成的。因此,您必须生成matricule
且没有空格,因为您假设车牌的长度为10。
因此,只需在matricule
函数中删除generate_code_train
的空格。
def generate_code_train():
#matricule = "{}{} {}{} {}{} {}{}{}{}".format(
matricule = "{}{}{}{}{}{}{}{}{}{}".format(
random.choice(common.DIGITS_0),
random.choice(common.DIGITS),
random.choice(common.DIGITS),
random.choice(common.DIGITS),
random.choice(common.DIGITS_E1),
random.choice(common.BARRE),
random.choice(common.LETTERS),
random.choice(common.BARRE),
random.choice(common.DIGITS_0),
random.choice(common.DIGITS_E1))
#matricule = matricule.decode("utf-8")
return matricule
通过修改以上内容,您可以执行train_1.py
,但
如果您使用原始的common.py
,gen.py
和model.py
,请同时确认以下内容。
LETTERS
中的CHARS
和common.py
。 w_fc2
的{{1}},b_fc2
和w_conv2
的形状(即用10代替7)