ValueError: total size of new array must be unchanged - Tensorflow - Machine Learning

Chào mọi người,
Mình đang học về tensorflow, máy học deep learning và đang làm 1 bài về phân lớp ảnh. Mình chỉ dùng mạng neural 1 lớp.
Hiện tại mình đang gặp lỗi như bên dưới:
> Traceback (most recent call last):
> File “draw_shape.py”, line 123, in
> batch_x, batch_y,batch_mask = batch_creator(batch_size, train_x.shape[0], ‘train’)
> File “draw_shape.py”, line 71, in batch_creator
> batch_x = eval(dataset_name + ‘_x’)[[batch_mask]].reshape(-1, input_num_units)
> ValueError: total size of new array must be unchanged

Đây là code của mình:

> from collections import Counter
> import os
> import numpy as np
> import pandas as pd
> from scipy.misc import imread
> import tensorflow as tf
> import cv2Preformatted text


> seed = 128
> rng = np.random.RandomState(seed)

> root_dir = "/home/trantrunghieu/lv"
> train = pd.read_csv(os.path.join(root_dir,"train", 'train.csv'))
> test = pd.read_csv(os.path.join(root_dir,"test",'test.csv'))

> train.head()

> temp = []
> for img_name in train.filename:
>     image_path = os.path.join(root_dir, 'train', img_name)
>     img = imread(image_path)
>     img = img.astype('float32')
>     img = tf.reshape(img,[-1])   
>     temp.append(img)
> train_x = np.stack(temp)

> for img_name in test.filename:
>     image_path = os.path.join(root_dir, 'test', img_name)
>     img = imread(image_path)
>     img = img.astype('float32')
>     img = tf.reshape(img,[-1])
>     
>     temp.append(img)
>     
> test_x = np.stack(temp)

> train_y = train.label.values[0:]
> print(train_y)
> print (Counter(train_y))


> def dense_to_one_hot(labels_dense, num_classes=8):
>     """Convert class labels from scalars to one-hot vectors"""
>     num_labels = labels_dense.shape[0]
>     index_offset = np.arange(num_labels) * num_classes
>     labels_one_hot = np.zeros((num_labels, num_classes))
>     labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
>     
>     return labels_one_hot

> def preproc(unclean_batch_x):
>     """Convert values to range 0-1"""
>     temp_batch = unclean_batch_x / unclean_batch_x.max()
>     
>     return temp_batch

> def batch_creator(batch_size, dataset_length, dataset_name):
>     """Create batch with random samples and return appropriate format"""
>     batch_mask = rng.choice(dataset_length, batch_size)
>     
>     batch_x = eval(dataset_name + '_x')[[batch_mask]].reshape(-1, input_num_units)
>     batch_x = preproc(batch_x)
>     
>     if dataset_name == 'train':
>         batch_y = eval(dataset_name).ix[batch_mask, 'label'].values
>         batch_y = dense_to_one_hot(batch_y)
>         
>     return batch_x, batch_y,batch_mask


> input_num_units = 16384
> output_num_units = 8

> x = tf.placeholder(tf.float32, [None, input_num_units])

> y = tf.placeholder(tf.float32, [None, output_num_units])


> epochs = 5
> batch_size = 128	
> learning_rate = 0.01


> W = tf.Variable(tf.zeros([input_num_units, output_num_units]))

> b = tf.Variable(tf.zeros([output_num_units]))
> output_layer = tf.matmul(x, W) + b

> cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output_layer, y))

> optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
> init = tf.global_variables_initializer()

> batch_mask = rng.choice(train_x.shape[0], batch_size)
> print("Batch_Mask: ",batch_mask)
> with tf.Session() as sess:
>     sess.run(init)
>     
>     for epoch in range(epochs):
>     	avg_cost = 0
> 	total_batch = int(train.shape[0]/batch_size)
> 	print(total_batch)
> 	for i in range(total_batch):
> 		batch_x, batch_y,batch_mask = batch_creator(batch_size, train_x.shape[0], 'train')
> 		_, c = sess.run([optimizer, cost], feed_dict = {x: batch_x, y: batch_y})
> 		avg_cost += c / total_batch

> 	print "Epoch:", (epoch+1), "cost =", "{:.5f}".format(avg_cost)
>     
>     print "\nTraining complete!"

method reshape của bạn có vấn đề, theo doc của numpy python thì

numpy.reshape(a, newshape, order='C')
    a: Array to be reshaped //obmit nếu không dùng kiểu C-like
    newshape : int or tuple of ints

trong khi đó mình thấy bạn truyền cả 2 tham số đều là int
https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html

Mình mới tìm hiểu về mảng này. Bài mình đang làm tham khảo code ở đây và áp dụng lại vào bộ dữ liệu của mình. Có 1 vài chỗ mình chưa hiểu rõ lắm. Mình cũng thấy chỗ reshape đó sai cú pháp, nhưng mình chưa biết sửa thế nào. Bạn có thể hướng dẫn mình thêm không? Cảm ơn bạn rất nhiều.

Bạn code trông bài bản phết, mình đọc code của bạn xong thấy bình thường mình toàn code búa xua chứ không ngon lành gì cả.

Nếu kích thước ảnh của bạn là 128 * 128 thì mình không thấy code sai ở đâu cả. Mình nghi ngờ kích cỡ ảnh không phải 128 * 128. Bạn up data lên mình xem thử.

Btw thì mình không thấy cách xử lý này hay mấy. Mình xử lý theo kiểu như này:

  • preprocess data trước (clean, đổi shape,…)
  • sau đó tạo ra các random batch
  • rồi lấy kết quả ở các random batch đó.

Mình coi lại kích thước ảnh rồi, đúng là 128*128. Cái này đâu phải tự tay mình code lên đâu. Mình chỉ mới bắt đầu tìm hiểu học về mảng này thôi. Bài này mình tham khảo ở link mình để ở trên và sửa đổi để chạy trên bộ dữ liệu ảnh của mình thôi. Cũng có nhiều chỗ chưa hiểu rõ, nên khi bị lỗi, nhiều cái không biết sửa thế nào. Bạn có kinh nghiệm về mảng này, vậy có thể hướng dẫn chi tiết cho mình theo cách bạn thường làm được không? (Nếu được bạn có thể cho mình xin skype hay facebook gì đó để tiện liên hệ). Cảm ơn bạn rất nhiều :smiley:

Ok, bạn code thừa 2 dòng này.

temp = []
for img_name in train.filename:
    image_path = os.path.join(root_dir, 'train', img_name)
    img = imread(image_path)
    img = img.astype('float32')
    # delete these 2 lines
    # img = tf.reshape(img,[-1])
    temp.append(img)
train_x = np.stack(temp)

for img_name in test.filename:
    image_path = os.path.join(root_dir, 'test', img_name)
    img = imread(image_path)
    img = img.astype('float32')
    # delete these 2 lines
    # img = tf.reshape(img,[-1])
    
    temp.append(img)
    
test_x = np.stack(temp)

Lần này mình cũng đang tiện tay nên check kỹ, chứ không up data lên thì khá mất thời gian check. Lỗi này mà có data chắc chỉ cần 3 4’ là mình check được rồi, 1 vài cái ảnh cho dự án cá nhân đâu cần phải giữ vậy?

Lỗi thì khá đơn giản, vì câu lệnh convert data từ TF sang np không được.

Link data: https://drive.google.com/file/d/0B3YdhMtOtK84TlcxWWZ0c0NROHc/view?usp=sharing
Sau khi sửa theo hướng dẫn của bạn thì phát sinh thêm lỗi này:

Traceback (most recent call last):
File “draw_shape.py”, line 128, in
batch_x, batch_y,batch_mask = batch_creator(batch_size, train_x.shape[0], ‘train’)
File “draw_shape.py”, line 76, in batch_creator
batch_y = dense_to_one_hot(batch_y)
File “draw_shape.py”, line 57, in dense_to_one_hot
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
IndexError: index 1024 is out of bounds for size 1024

Với lại, mình không cần phải flatten ảnh từ 1 mảng nhiều chiều sang dạng tensor 1 chiều sao?

Không, có nhiều lý do để phải sửa như thế. Đầu tiên là do API nó quy đinh

If the key is a tf.Tensor, the value may be a Python scalar, string, list, or numpy ndarray that can be converted to the same dtype as that tensor. Additionally, if the key is a tf.placeholder, the shape of the value will be checked for compatibility with the placeholder.
If the key is a tf.SparseTensor, the value should be a tf.SparseTensorValue.
If the key is a nested tuple of Tensors or SparseTensors, the value should be a nested tuple with the same structure that maps to their corresponding values as above.

Thứ 2 là việc trộn data có nhiều type lại rất khỏ xử lý, nhìn chung nên tránh.

Mình sửa lại thêm dòng này nữa thì chạy ok rồi, không gặp lỗi như trên :-?

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = output_layer))

[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6
6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8
8 8 8 8 8 8 8 8 8 8 8 8]
Counter({1: 20, 2: 20, 3: 20, 4: 20, 5: 20, 6: 20, 7: 20, 8: 20})
('Batch_Mask: ', array([ 83, 82, 119, 10, 34, 84, 57, 149, 113, 16, 42, 9, 0,
27, 22, 1, 99, 144, 30, 135, 79, 20, 103, 72, 150, 71,
36, 147, 39, 56, 148, 23, 45, 20, 20, 138, 140, 111, 19,
23, 111, 4, 42, 117, 86, 143, 149, 126, 44, 17, 114, 151,
89, 70, 10, 157, 131, 108, 110, 29, 151, 4, 29, 120, 16,
23, 133, 9, 33, 157, 141, 125, 4, 38, 87, 19, 102, 155,
84, 13, 101, 100, 65, 32, 114, 44, 120, 83, 39, 74, 159,
0, 19, 102, 63, 33, 14, 68, 101, 48]))
1
Epoch: 1 cost = 2.07944
1
Epoch: 2 cost = 12.74761
1
Epoch: 3 cost = 19.15919
1
Epoch: 4 cost = 14.31016
1
Epoch: 5 cost = 13.74835

Training complete!

btw lần sau bạn bỏ code vào trong markdown chứ đừng kiểu quote vậy. CHi tiết hướng dẫn thì đọc đâu đó trong diễn đàn sẽ có

Cảm ơn bạn rất nhiều. Mình có đọc ở nhiều chỗ trên mạng, thấy có nhiều cách để tạo tập huấn luyện và tập kiểm tra từ tập dữ liệu của mình (như dùng Queue, Placeholder) . Bạn có thể hướng dẫn cho mình 1 cách tổng quát, (có thể áp dụng cho đa số các trường hợp) để tạo dữ liệu đưa vào train từ tập ảnh của mình được không?

Thông thường thì chúng ta hay dùng tf.placeholder vì nó giúp cho việc optimize bằng Stochastic Gradient Descent (SGD).

Hướng dẫn thì ok, chắc tầm tối mai mình viết xong thì post lên.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?