权重变量 Tensorflow 的形状
Shape of weight variable Tensorflow
我正在尝试学习如何使用 tf.data.TFRecordDataset()
,但我对此感到困惑。我有一个 tfrecords
文件,其中包含我的图像 (24K) 和标签,我已将所有图像的大小调整为 100x100x3。
首先,我用 tf.data.TFRecordDataset
加载了我的 tfrecords
文件并解析数据和其他内容,如您在我的代码中所见。然后我写了一个简单的模型来学习 tfrecord
文件的使用,但是我在尝试 运行 时卡住了并出错。我在互联网上搜索过,但找不到任何答案。
这是我的代码:Train.py
import tensorflow as tf
import numpy as np
import os
import glob
NUM_EPOCHS = 10
batch_size = 128
def _parse_function(example_proto):
features = {"train/image": tf.FixedLenFeature((), tf.string, default_value=""),
"train/label": tf.FixedLenFeature((), tf.int64, default_value=0)}
parsed_features = tf.parse_single_example(example_proto, features)
image = tf.decode_raw(parsed_features['train/image'], tf.float32)
label = tf.cast(parsed_features['train/label'], tf.int32)
image = tf.reshape(image, [100, 100, 3])
image = tf.reshape(image, [100*100*3])
return image, label
filename = 'train_data1.tfrecords'
dataset = tf.data.TFRecordDataset(filename)
dataset = dataset.map(_parse_function)
#dataset = dataset.repeat(NUM_EPOCHS)
dataset = dataset.batch(batch_size=batch_size)
iterator = dataset.make_initializable_iterator()
image, label = iterator.get_next()
w = tf.get_variable(name='Weights',shape= [30000,3] , initializer=tf.random_normal_initializer(0, 0.01))
b = tf.get_variable(name='Biases', shape= [1, 3],initializer=tf.zeros_initializer())
logits = tf.matmul(image, w) + b
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=label, name='Entropy'), name='loss')
optimizer = tf.train.AdamOptimizer(0.001).minimize(loss)
preds = tf.nn.softmax(logits)
correct_preds = tf.equal(tf.argmax(preds, axis=1), tf.argmax(label, axis=1))
accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(2):
sess.run(iterator.initializer)
total_loss = 0
n_batches = 0
try:
while True:
_, l = sess.run([optimizer, loss])
total_loss += l
n_batches +=1
except tf.errors.OutOfRangeError:
pass
print('Average loss epoch {0}: {1}'.format(i, total_loss/n_batches))
这是图像的输出:
<tf.Tensor 'IteratorGetNext:0' shape=(?, 30000) dtype=float32>
标签是:
<tf.Tensor 'IteratorGetNext:1' shape=(?,) dtype=int32>
而这一次我得到了这个错误:
logits and labels must be same size: logits_size=[128,3]
labels_size=[1,128].
当我用 label = tf.reshape(label,[128,1])
将标签(我想,我在这里做错了)重塑为 [128,1] 时,我会得到这个错误:
imension size must be evenly divisible by 3 but is 128 for
'gradients/Entropy/Reshape_grad/Reshape' (op: 'Reshape') with input
shapes: [128,1], [2] and with input tensors computed as partial
shapes: input[1] = [?,3].
我正在尝试对我的 3 类 进行分类:自行车为 0,公共汽车为 1,汽车为 2。
这是我将图像和标签读入 tfrecords
的代码。
tfrecordWriter.py
的代码
shuffle_data = True
cat_dog_train_path = './Train/*.jpg'
addrs = glob.glob(cat_dog_train_path)
labels = [0 if 'bike' in addr else 1 if 'bus' in addr else 2 for addr in addrs]
if shuffle_data:
c = list(zip(addrs, labels))
shuffle(c)
addrs, labels = zip(*c)
train_addrs = addrs[:]
train_labels = labels[:]
train_shape = []
def load_image(addr):
img = cv2.imread(addr)
img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32)
return img
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def _bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
train_filename = 'train_data1.tfrecords'
# open the TFRecords file
writer = tf.python_io.TFRecordWriter(train_filename)
for i in range(len(train_addrs)):
print ('Train data: {}/{}'.format(i+1, len(train_addrs)))
sys.stdout.flush()
img = load_image(train_addrs[i])
label = train_labels[i]
feature = {'train/label': _int64_feature(label),
'train/image': _bytes_feature(tf.compat.as_bytes(img.tostring()))}
example = tf.train.Example(features=tf.train.Features(feature=feature))
writer.write(example.SerializeToString())
writer.close()
sys.stdout.flush()
谢谢
问题出在这一行:
w = tf.get_variable(name='Weights',shape= [None, 100, 100, 3] , initializer=tf.random_normal_initializer(0, 0.01))
您指定您的权重具有 tensorflow 无法处理的 shape=[None,100,100,3]
形状。正如错误所说 "Shape of a new variable (Weights) must be fully defined," 所以你不能将 None
作为权重的维度。在我看来,您将输入张量的形状与权重张量的形状混淆了。看起来您还没有在任何地方展平图像,因此您的模型没有任何意义。你在哪里:
logits = tf.matmul(image, w) + b
您似乎正试图将此问题视为简单的逻辑回归,将图像的像素作为单独的特征。这是一种不错的第一种方法(但通常人们会在图像上使用 Conv-net),但实际上你必须将图像展平为 shape=[batchsize,30000]
的形状,然后你的权重将具有 [=16] 的形状=] 这样在矩阵乘法结束时,您将得到形状为 shape=[batchsize,num_labels]
的最终输出。根据您的代码编写方式,我觉得您对数学或您要完成的操作背后的操作存在一些根本性的误解。也许回顾一下你到底想做什么。
编辑:这里的问题是对算法正在做什么的根本误解。该算法产生 3 个输出,因此标签必须具有 3 个对应的标签才能匹配 3 个输出。您的标签不能只有一个数字 - 0,1 或 2,具体取决于 class。您的标签必须是 3 个数字,每个数字告诉您图像是否在 class 中。换句话说,您必须使用 3 分量 (one-hot) 向量而不是 1 分量编号来标记图像。每张图片的标签应如下所示:
[1,0,0] - bike
[0,1,0] - bus
[0,0,1] - car
因此您的标签形状 (128,3)
应该与输出形状 相同 (128,3)
。
我正在尝试学习如何使用 tf.data.TFRecordDataset()
,但我对此感到困惑。我有一个 tfrecords
文件,其中包含我的图像 (24K) 和标签,我已将所有图像的大小调整为 100x100x3。
首先,我用 tf.data.TFRecordDataset
加载了我的 tfrecords
文件并解析数据和其他内容,如您在我的代码中所见。然后我写了一个简单的模型来学习 tfrecord
文件的使用,但是我在尝试 运行 时卡住了并出错。我在互联网上搜索过,但找不到任何答案。
这是我的代码:Train.py
import tensorflow as tf
import numpy as np
import os
import glob
NUM_EPOCHS = 10
batch_size = 128
def _parse_function(example_proto):
features = {"train/image": tf.FixedLenFeature((), tf.string, default_value=""),
"train/label": tf.FixedLenFeature((), tf.int64, default_value=0)}
parsed_features = tf.parse_single_example(example_proto, features)
image = tf.decode_raw(parsed_features['train/image'], tf.float32)
label = tf.cast(parsed_features['train/label'], tf.int32)
image = tf.reshape(image, [100, 100, 3])
image = tf.reshape(image, [100*100*3])
return image, label
filename = 'train_data1.tfrecords'
dataset = tf.data.TFRecordDataset(filename)
dataset = dataset.map(_parse_function)
#dataset = dataset.repeat(NUM_EPOCHS)
dataset = dataset.batch(batch_size=batch_size)
iterator = dataset.make_initializable_iterator()
image, label = iterator.get_next()
w = tf.get_variable(name='Weights',shape= [30000,3] , initializer=tf.random_normal_initializer(0, 0.01))
b = tf.get_variable(name='Biases', shape= [1, 3],initializer=tf.zeros_initializer())
logits = tf.matmul(image, w) + b
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=label, name='Entropy'), name='loss')
optimizer = tf.train.AdamOptimizer(0.001).minimize(loss)
preds = tf.nn.softmax(logits)
correct_preds = tf.equal(tf.argmax(preds, axis=1), tf.argmax(label, axis=1))
accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(2):
sess.run(iterator.initializer)
total_loss = 0
n_batches = 0
try:
while True:
_, l = sess.run([optimizer, loss])
total_loss += l
n_batches +=1
except tf.errors.OutOfRangeError:
pass
print('Average loss epoch {0}: {1}'.format(i, total_loss/n_batches))
这是图像的输出:
<tf.Tensor 'IteratorGetNext:0' shape=(?, 30000) dtype=float32>
标签是:
<tf.Tensor 'IteratorGetNext:1' shape=(?,) dtype=int32>
而这一次我得到了这个错误:
logits and labels must be same size: logits_size=[128,3] labels_size=[1,128].
当我用 label = tf.reshape(label,[128,1])
将标签(我想,我在这里做错了)重塑为 [128,1] 时,我会得到这个错误:
imension size must be evenly divisible by 3 but is 128 for 'gradients/Entropy/Reshape_grad/Reshape' (op: 'Reshape') with input shapes: [128,1], [2] and with input tensors computed as partial shapes: input[1] = [?,3].
我正在尝试对我的 3 类 进行分类:自行车为 0,公共汽车为 1,汽车为 2。
这是我将图像和标签读入 tfrecords
的代码。
tfrecordWriter.py
shuffle_data = True
cat_dog_train_path = './Train/*.jpg'
addrs = glob.glob(cat_dog_train_path)
labels = [0 if 'bike' in addr else 1 if 'bus' in addr else 2 for addr in addrs]
if shuffle_data:
c = list(zip(addrs, labels))
shuffle(c)
addrs, labels = zip(*c)
train_addrs = addrs[:]
train_labels = labels[:]
train_shape = []
def load_image(addr):
img = cv2.imread(addr)
img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32)
return img
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def _bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
train_filename = 'train_data1.tfrecords'
# open the TFRecords file
writer = tf.python_io.TFRecordWriter(train_filename)
for i in range(len(train_addrs)):
print ('Train data: {}/{}'.format(i+1, len(train_addrs)))
sys.stdout.flush()
img = load_image(train_addrs[i])
label = train_labels[i]
feature = {'train/label': _int64_feature(label),
'train/image': _bytes_feature(tf.compat.as_bytes(img.tostring()))}
example = tf.train.Example(features=tf.train.Features(feature=feature))
writer.write(example.SerializeToString())
writer.close()
sys.stdout.flush()
谢谢
问题出在这一行:
w = tf.get_variable(name='Weights',shape= [None, 100, 100, 3] , initializer=tf.random_normal_initializer(0, 0.01))
您指定您的权重具有 tensorflow 无法处理的 shape=[None,100,100,3]
形状。正如错误所说 "Shape of a new variable (Weights) must be fully defined," 所以你不能将 None
作为权重的维度。在我看来,您将输入张量的形状与权重张量的形状混淆了。看起来您还没有在任何地方展平图像,因此您的模型没有任何意义。你在哪里:
logits = tf.matmul(image, w) + b
您似乎正试图将此问题视为简单的逻辑回归,将图像的像素作为单独的特征。这是一种不错的第一种方法(但通常人们会在图像上使用 Conv-net),但实际上你必须将图像展平为 shape=[batchsize,30000]
的形状,然后你的权重将具有 [=16] 的形状=] 这样在矩阵乘法结束时,您将得到形状为 shape=[batchsize,num_labels]
的最终输出。根据您的代码编写方式,我觉得您对数学或您要完成的操作背后的操作存在一些根本性的误解。也许回顾一下你到底想做什么。
编辑:这里的问题是对算法正在做什么的根本误解。该算法产生 3 个输出,因此标签必须具有 3 个对应的标签才能匹配 3 个输出。您的标签不能只有一个数字 - 0,1 或 2,具体取决于 class。您的标签必须是 3 个数字,每个数字告诉您图像是否在 class 中。换句话说,您必须使用 3 分量 (one-hot) 向量而不是 1 分量编号来标记图像。每张图片的标签应如下所示:
[1,0,0] - bike
[0,1,0] - bus
[0,0,1] - car
因此您的标签形状 (128,3)
应该与输出形状 相同 (128,3)
。