Tensorflow input function returns invalid values (Tensor instead of Tensor dict) - python

I have been working on standard image classification problem with Tensorflow. Most of the code is derived from tutorials on www.tensorflow.org, the only major change is that I use my own data.
The images are already processed, of same size, encoding etc., and sorted into appropriate folders called groupA and groupB. While most of the code worked without a problem (images get loaded from disk and decoded, labels are assigned etc.) I encountered an unexpected roadblock.
labels = tf.constant([1.0 if 'groupA' in filename else 0.1 for filename in training_data])
file_names = tf.constant(training_data)
dataset = tf.data.Dataset.from_tensor_slices((file_names, labels))
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image = tf.image.decode_png(filename)
return image, label
dataset = dataset.map(_parse_function)
def create_input_fn_train(dataset):
def input_fn():
ds = dataset.shuffle(buffer_size=10000)
ds = ds.batch(16)
ds = ds.repeat()
iterator = ds.make_one_shot_iterator()
images, labels = iterator.get_next()
return images, labels
return input_fn
input_fn_train = create_input_fn_train(dataset)
model = tf.estimator.DNNClassifier(feature_columns=[construct_feature_columns(150,150)],
hidden_units=[1024,100],
optimizer=tf.train.AdamOptimizer(1e-4),
n_classes=2,
dropout=0.1,
model_dir="./tmp/fon_model")
The input function is returning wrong type of data, causing following error.
ValueError("features should be a dictionary of `Tensor`s. Given type: <class 'tensorflow.python.framework.ops.Tensor'>",)
I tried to look up possible solutions, leading me to tensorflow ValueError: features should be a dictionary of `Tensor`s. Given type: <class 'tensorflow.python.framework.ops.Tensor'> and tried the provided solution.
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image = tf.image.decode_png(filename)
features = {}
features['pixels'] = image
return features, label
But it gave me another error message, this time:
ValueError("Items of feature_columns must be a _FeatureColumn. Given (type <class 'set'>): {_NumericColumn(key='pixels', shape=(22500,), default_value=None, dtype=tf.float32, normalizer_fn=None)}.",)
Which leads me to believe that I made some sort of fundamental error. Either when parsing the data, assigning labels etc.
But I can't figure out where I went wrong.
EDIT:
I altered the code so that estimator constructor is
model = tf.estimator.DNNClassifier(feature_columns=construct_feature_columns(150,150),
hidden_units=[1024,100],
optimizer=tf.train.AdamOptimizer(1e-4),
n_classes=2,
dropout=0.1,
model_dir="./tmp/fon_model")
and the construct_feature_columns into:
def construct_feature_columns(image_height, image_width):
return set([tf.feature_column.numeric_column('pixels', shape=[image_height*image_width])])
Eliminating the ValueError:
ValueError("Items of feature_columns must be a _FeatureColumn. Given (type <class 'set'>): {_NumericColumn(key='pixels', shape=(22500,), default_value=None, dtype=tf.float32, normalizer_fn=None)}.",)
I also rewrote the input function into:
def input_fn():
ds = dataset.shuffle(buffer_size=len(training_data))
ds = ds.batch(16)
ds = ds.repeat()
iterator = ds.make_one_shot_iterator()
images, labels = iterator.get_next()
images = {'pixels':images}
return images, labels
However new error turned up, confirming my belief that I messed up something fundamental:
UnimplementedError (see above for traceback): Cast string to float is not supported
[[Node: dnn/input_from_feature_columns/input_layer/pixels/ToFloat = Cast[DstT=DT_FLOAT, SrcT=DT_STRING, _device="/job:localhost/replica:0/task:0/device:CPU:0"](dnn/input_from_feature_columns/input_layer/pixels/ExpandDims)]]

Related

Getting Error: TypeError: cross_entropy_loss(): argument 'target' (position 2) must be Tensor, not tuple

I am working on a CNN multi-class classification of different concentrations (10uM, 30uM, etc.) I create my dataset to include the images as the features and the concentrations as labels. Note that the concentrations are left as a string. When running the code, I am getting the following error:
TypeError: cross_entropy_loss(): argument 'target' (position 2) must be Tensor, not tuple
The following is my dataset class:
class CustomDataset(Dataset):
def __init__(self, path, method):
"""
Args:
csv_path (string): path to csv file
data_path (string): path to the folder where images are
transform: pytorch transforms for transforms and tensor conversion
"""
# Transforms
self.to_tensor = transforms.ToTensor()
# Read the excel file
self.data_path = pd.read_excel(path, sheet_name=method)
# First column contains the image paths
self.img_arr = np.asarray(self.data_path.iloc[:, 0])
# Second column is the labels
self.label_arr = np.asarray(self.data_path.iloc[:, 1])
def __getitem__(self, index):
# Get image name from the pandas df
img_path = self.img_arr[index]
# Open image
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Converts the image from BGR to RGB
# Transform image to tensor
img_tensor = self.to_tensor(img)
# Get label(class) of the image based on the cropped pandas column
img_label = self.to_tensor(self.label_arr[index])
img_label = self.label_arr[index]
return (img_tensor, img_label)
def __len__(self):
return len(self.data_path)
I am aware that the reason is most probably due to the fact that the labels are left as tuples, so the loss function is unable to compare the CNN output with the label. However, I am unable to find any resources that explain how labels are dealt with in multi-class classifications of tuple type labels. The solution seems simple, but I am a bit confused on how to solve it. Can anyone direct me?
EDIT: This is the implemented training loop:
def train_epoch(model,dataloader,loss_fn,optimizer):
train_loss,train_correct = 0.0, 0
model.train() #Sets the mode to train (Helpful when using layers such as DropOut and BatchNorm)
for features,labels in dataloader:
#Zero grad
optimizer.zero_grad()
#Forward Pass
output=model(features)
print(output)
print(labels)
loss=loss_fn(output,labels)
#Backward Pass
loss.backward()
optimizer.step()
train_loss += loss.item()*features.size(0) #features.size is useful when using batches.
scores, predictions = torch.max(output.data,1) # 1 is to create a 1 dimensional tensor with max values from each row
train_correct += (predictions==labels).sum().item()
return train_loss, train_correct
This is the output of "output" and "labels", respectively:
tensor([[-0.0528, -0.0150, -0.0153, -0.0939, -0.0887, -0.0863]],
grad_fn=<AddmmBackward0>)
('70uM',)

Attempt to convert a value (<PIL.BmpImagePlugin.BmpImageFile image mode=L size=190x100 at 0x7F35C52AD210>) with an unsupported type to a Tensor

I tried to execute the ViT model from Image Classification with Hugging Face Transformers and Keras, I got an error, particularly in this instruction:
processed_dataset = ds.map(augmentation, batched=True)
the error :
ValueError: Exception encountered when calling layer "resizing_8"
(type Resizing).
Attempt to convert a value (<PIL.BmpImagePlugin.BmpImageFile image
mode=L size=190x100 at 0x7F35C52AD210>) with an unsupported type
(<class 'PIL.BmpImagePlugin.BmpImageFile'>) to a Tensor.
Call arguments received: • inputs=<PIL.BmpImagePlugin.BmpImageFile
image mode=L size=190x100 at 0x7F35C52AD210>
I tried the answer in this link ArrowTypeError: Could not convert <PIL.PngImagePlugin.PngImageFile image mode=RGB size=32x32 at 0x7F2223B6ED10>, where I added 'img': Image(decode=True, id=None) to my features in create_image_folder_dataset() and I still have the same problem except for a small change in this part
ValueError: Exception encountered when calling layer "resizing_13"
(type Resizing).
What I should do to solve this problem?
create_image_folder_dataset function:
def create_image_folder_dataset(root_path):
"""creates `Dataset` from image folder structure"""
# get class names by folders names
_CLASS_NAMES= os.listdir(root_path)
# defines `datasets` features`
features=datasets.Features({
"img": datasets.Image(decode=True, id=None),
#"img": datasets.Image(),
"label": datasets.features.ClassLabel(names=_CLASS_NAMES),
})
#print(_CLASS_NAMES)
# temp list holding datapoints for creation
img_data_files=[]
label_data_files=[]
# load images into list for creation
for img_class in os.listdir(root_path):
for img in os.listdir(os.path.join(root_path,img_class)):
path_=os.path.join(root_path,img_class,img)
img_data_files.append(path_)
label_data_files.append(img_class)
# create dataset
ds = datasets.Dataset.from_dict({"img":img_data_files,"label":label_data_files},features=features)
return ds
ds = create_image_folder_dataset("/content/drive/MyDrive/FINAL_DATASET")
ds[0] """ return:
{'img': <PIL.BmpImagePlugin.BmpImageFile image mode=L size=190x100 at 0x7F35C54ECC10>,
'label': 0}"""
my Augmentation function :
from transformers import ViTFeatureExtractor
from tensorflow import keras
from tensorflow.keras import layers
model_id = "google/vit-base-patch16-224-in21k"
#google/vit-base-patch32-384
feature_extractor = ViTFeatureExtractor.from_pretrained(model_id)
# learn more about data augmentation here: https://www.tensorflow.org/tutorials/images/data_augmentation
data_augmentation = keras.Sequential(
[
layers.Resizing(feature_extractor.size, feature_extractor.size),
layers.Rescaling(1./255),
layers.RandomFlip("horizontal"),
layers.RandomRotation(factor=0.02),
layers.RandomZoom(
height_factor=0.2, width_factor=0.2
),
],
name="data_augmentation",
)
# use keras image data augementation processing
def augmentation(examples):
print(examples["img"])
examples["pixel_values"] = [data_augmentation(image) for image in examples["img"]]
return examples
# basic processing (only resizing)
def process(examples):
examples.update(feature_extractor(examples['img'], ))
return examples
# we are also renaming our label col to labels to use `.to_tf_dataset` later
#ds = ds.rename_column("label", "labels")
Now it's working, I convert my dataset from "L" to "RGB".

Proper dataloader setup to train fasterrcnn-resnet50 for object detection with pytorch

I am trying to train pytorches torchvision.models.detection.fasterrcnn_resnet50_fpn to detect objects in my own images.
According to the documentation, this model expects a list of images and a list of dictionaries with
'boxes' and 'labels' as keys. So my dataloaders __getitem__() looks like this:
def __getitem__(self, idx):
# load images
_, img = self.images[idx].getImage()
img = Image.fromarray(img, mode='RGB')
objects = self.images[idx].objects
boxes = []
labels = []
for o in objects:
# append bbox to boxes
boxes.append([o.x, o.y, o.x+o.width, o.y+o.height])
# append the 4th char of class_id, the number of lights (1-4)
labels.append(int(str(o.class_id)[3]))
# convert everything into a torch.Tensor
boxes = torch.as_tensor(boxes, dtype=torch.float32)
labels = torch.as_tensor(labels, dtype=torch.int64)
target = {}
target["boxes"] = boxes
target["labels"] = labels
# transforms consists only of transforms.Compose([transforms.ToTensor()]) for the time being
if self.transforms is not None:
img = self.transforms(img)
return img, target
To my best knowledge, it returns exactly what's asked. My dataloader looks like this
data_loader = torch.utils.data.DataLoader(
dataset, batch_size=4, shuffle=False, num_workers=2)
however, when it get's to this stage:
for images, targets in dataloaders[phase]:
it raises
RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension 0. Got 12 and 7 in dimension 1 at C:\w\1\s\windows\pytorch\aten\src\TH/generic/THTensor.cpp:689
Can someone point me in the right direction?
#jodag was right, I had to write a seperate collate function in order for the net to receive the data like it was supposed to. In my case I only needed to bypass the default function.

Tensorflow parsing and reshaping float list in Dataset.map()

I am trying to write a 3D float list into a TFrecord, so I successfully, write it by flattening it first, I parse it but it raises an error while reshaping it.
Error: ValueError: Shapes () and (8,) are not compatible
This is how I write the TFrecord file
def _floats_feature(value):
return tf.train.Feature(float_list=tf.train.FloatList(value=value.flatten()))
def write(output_path, data_rgb, data_depth, data_decalib):
with tf.python_io.TFRecordWriter(output_path) as writer:
feature = {'data_rgb': _floats_feature(data_rgb),
'data_depth': _floats_feature(data_depth),
'data_decalib': _floats_feature(data_decalib)}
sample = tf.train.Example(features=tf.train.Features(feature=feature))
writer.write(sample.SerializeToString())
And This is how I read the TFrecord file
def get_batches(date, drives, batch_size=1):
"""
Create a generator that returns batches of tuples
rgb, depth and calibration
:param date: date of the drive
:param drives: array of the drive_numbers within the drive date
:return: batch generator
"""
filenames = get_paths_drives(date, drives)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(input_parser) # Parse the record into tensors.
dataset = dataset.repeat() # Repeat the input indefinitely.
dataset = dataset.batch(batch_size)
return dataset
config = configparser.ConfigParser()
config.read(path_helpers.get_config_file_path())
IMAGE_WIDTH = int(config['DATA_INFORMATION']['IMAGE_WIDTH'])
IMAGE_HEIGHT = int(config['DATA_INFORMATION']['IMAGE_HEIGHT'])
INPUT_RGB_SHAPE = [IMAGE_HEIGHT, IMAGE_WIDTH, 3]
INPUT_DEPTH_SHAPE = [IMAGE_HEIGHT, IMAGE_WIDTH, 1]
LABEL_CALIB_SHAPE = [8]
def input_parser(example_proto):
features = {'data_rgb': tf.FixedLenFeature([], tf.float32),
'data_depth': tf.FixedLenFeature([], tf.float32),
'data_decalib': tf.FixedLenFeature([], tf.float32)}
parsed_features = tf.parse_single_example(example_proto, features)
data_rgb = parsed_features['data_rgb']
data_rgb.set_shape(np.prod(INPUT_RGB_SHAPE))
img_rgb = tf.reshape(data_rgb, INPUT_RGB_SHAPE)
data_depth = parsed_features['data_depth']
data_depth.set_shape(np.prod(INPUT_DEPTH_SHAPE))
img_depth = tf.reshape(data_depth, INPUT_DEPTH_SHAPE)
data_decalib = parsed_features['data_decalib']
data_decalib.set_shape(LABEL_CALIB_SHAPE)
return img_rgb, img_depth, data_decalib
Turns out I needed to change my input parser as follows:
def input_parser(example_proto):
features = {'data_rgb': tf.FixedLenFeature(shape=[np.prod(INPUT_RGB_SHAPE)], dtype=tf.float32),
'data_depth': tf.FixedLenFeature(shape=[np.prod(INPUT_DEPTH_SHAPE)], dtype=tf.float32),
'data_decalib': tf.FixedLenFeature(shape=LABEL_CALIB_SHAPE, dtype=tf.float32)}
parsed_features = tf.parse_single_example(example_proto, features)
as the documentation for tf.FixedLenFeature (now tf.io.FixedLenFeature) dictates. The first argument is the shape, which I set to [] hence the error ValueError: Shapes () and (8,) are not compatible. Setting it to their real values worked out.

TypeError when training Tensorflow Random Forest using TensorForestEstimator

I get a TypeError when attempting to train an Tensorflow Random Forest using TensorForestEstimator.
TypeError: Input 'input_data' of 'CountExtremelyRandomStats' Op has type float64 that does not match expected type of float32.
I've tried using Python 2.7 and Python 3, and I've tried using tf.cast() to put everything in float32 but it doesn't help. I have checked the data type on execution and it's float32. The problem doesn't seem to be the data I provide (csv of all floats), so I'm not sure where to go from here.
Any suggestions of things I can try would be much appreciated.
Code:
# Build an estimator.
def build_estimator(model_dir):
params = tensor_forest.ForestHParams(
num_classes=2, num_features=760,
num_trees=FLAGS.num_trees, max_nodes=FLAGS.max_nodes)
graph_builder_class = tensor_forest.RandomForestGraphs
if FLAGS.use_training_loss:
graph_builder_class = tensor_forest.TrainingLossForest
# Use the SKCompat wrapper, which gives us a convenient way to split in-memory data into batches.
return estimator.SKCompat(random_forest.TensorForestEstimator(params, graph_builder_class=graph_builder_class, model_dir=model_dir))
# Train and evaluate the model.
def train_and_eval():
# load datasets
training_set = pd.read_csv('/Users/carl/Dropbox/Docs/Python/randomforest_balanced_train.csv', dtype=np.float32, header=None)
test_set = pd.read_csv('/Users/carl/Dropbox/Docs/Python/randomforest_balanced_test.csv', dtype=np.float32, header=None)
print('###########')
print(training_set.loc[:,1].dtype) # this prints float32
# load labels
training_labels = pd.read_csv('/Users/carl/Dropbox/Docs/Python/randomforest_balanced_train_class.csv', dtype=np.int32, names=LABEL, header=None)
test_labels = pd.read_csv('/Users/carl/Dropbox/Docs/Python/randomforest_balanced_test_class.csv', dtype=np.int32, names=LABEL, header=None)
# define the path where the model will be stored - default is current directory
model_dir = tempfile.mkdtemp() if not FLAGS.model_dir else FLAGS.model_dir
print('model directory = %s' % model_dir)
# build the random forest estimator
est = build_estimator(model_dir)
tf.cast(training_set, tf.float32) #error occurs with/without casts
tf.cast(test_set, tf.float32)
# train the forest to fit the training data
est.fit(x=training_set, y=training_labels) #this line throws the error
You are using tf.cast in incorrect manner
tf.cast(training_set, tf.float32) #error occurs with/without casts
should be
training_set = tf.cast(training_set, tf.float32)
tf.cast is not in-place method, it is a tensor flow op, as any other operation, and needs to be assigned and run.

Categories

Resources