I have been trying to build a deep learning model, using Keras as API with tensorflow 2.2 and cuda 102.89. My dataset is "relatively big" (27500 400x400 images) and so I've tried using both keras.utils.sequence (here) and tf.keras.preprocessing.image.ImageDataGenerator (here) to fit these images into the memory using batches. Yet, neither of these worked so far, I must be not using it correctly but I can't see what's wrong with my code.
Using the keras.utils.sequence:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from tensorflow import keras
class BatchGenerator(keras.utils.Sequence):
def __init__(self, inputs, targets, batch_size=32):
self.inputs = inputs
self.targets = targets
self.batch_size = batch_size
def __len__(self):
return len(self.targets) // self.batch_size
def __getitem__(self, idx):
i = idx * self.batch_size
x = self.inputs[i : i + self.batch_size]
y = self.targets[i : i + self.batch_size]
return x, y
# Load images and labels with normalization and one hot encoding
# images: np.array, (27512, 480, 480, 3); labels: np.array, (27512, 480, 480, 9); nb_class = 9
images, labels, nb_class = data_loader('../Data/Images', '../Data/labels')
# Creation of the 0.2 validation split
train = list(range(images.shape[0]//5, images.shape[0]))
test = list(range(0, images.shape[0]//5))
# Batch generation
train_gen = BatchGenerator(images[train], labels[train], batch_size, data_aug)
valid_gen = BatchGenerator(images[test], labels[test], batch_size, data_aug)
# Model fitting
history = model.fit(train_gen, epochs=nb_epoch, verbose=1,
validation_data=valid_gen, shuffle=False, callbacks=callbacks)
Using ImageDataGeneratorlink and flow link:
from keras.preprocessing.image import ImageDataGenerator
# Load images and labels with normalization and one hot encoding
# images: np.array, (27512, 480, 480, 3); labels: np.array, (27512, 480, 480, 9); nb_class = 9
images, labels, nb_class = data_loader('../Data/Images', '../Data/labels')
# Batch generation with data augmentation instance
datagen = ImageDataGenerator(
vertical_flip=True,
horizontal_flip=True,
preprocessing_function=augmentations_color,
samplewise_center=True,
samplewise_std_normalization=True,
validation_split=0.2
)
# Batch generation application
train_gen = datagen.flow(images, labels, batch_size=16,
shuffle=True, subset='training')
valid_gen = datagen.flow(images, labels, batch_size=16,
shuffle=True, subset='validation')
# Model fitting
history = model.fit(train_gen, epochs=nb_epoch, verbose=1,
validation_data=valid_gen, shuffle=False, callbacks=callbacks)
In both cases, the code crashes during BatchGenerator and never reach the model fitting part complaining:
Traceback (most recent call last):
File "main.py", line 190, in <module>
conf_file=train_set.cfg_path)
File "main.py", line 92, in main
shuffle=True, subset='training')
File "/hpc_htom/kjam268/Virtual_ENV/HistoTAG/lib/python3.6/site-packages/keras_preprocessing/image/image_data_generator.py", line 434, in flow
dtype=self.dtype
File "/hpc_htom/kjam268/Virtual_ENV/HistoTAG/lib/python3.6/site-packages/keras_preprocessing/image/numpy_array_iterator.py", line 103, in __init__
np.unique(y[split_idx:]))):
File "<__array_function__ internals>", line 6, in unique
File "/hpc_htom/kjam268/Virtual_ENV/HistoTAG/lib/python3.6/site-packages/numpy/lib/arraysetops.py", line 261, in unique
ret = _unique1d(ar, return_index, return_inverse, return_counts)
File "/hpc_htom/kjam268/Virtual_ENV/HistoTAG/lib/python3.6/site-packages/numpy/lib/arraysetops.py", line 314, in _unique1d
ar = np.asanyarray(ar).flatten()
numpy.core._exceptions.MemoryError: Unable to allocate 189. GiB for an array with shape (50711040000,) and data type float32
I have trimmed the code to the essential but I can post all of it if needed. I tried both scenarios with different batch as small as 1 without improvements.
Any ideas of what I could try to be able to train my model ?
Thank you
You can follow this official instruction Image segmentation with a U-Net-like architecture. Here is the most relevant coding part for your case.
Generator
class BatchGenerator(keras.utils.Sequence):
"""Helper to iterate over the data (as Numpy arrays)."""
def __init__(self, batch_size, img_size, input_img_paths, target_img_paths):
self.batch_size = batch_size
self.img_size = img_size
self.input_img_paths = input_img_paths
self.target_img_paths = target_img_paths
def __len__(self):
return len(self.target_img_paths) // self.batch_size
def __getitem__(self, idx):
"""Returns tuple (input, target) correspond to batch #idx."""
i = idx * self.batch_size
batch_input_img_paths = self.input_img_paths[i : i + self.batch_size]
batch_target_img_paths = self.target_img_paths[i : i + self.batch_size]
x = np.zeros((self.batch_size,) + self.img_size + (3,), dtype="float32")
for j, path in enumerate(batch_input_img_paths):
img = load_img(path, target_size=self.img_size)
x[j] = img
y = np.zeros((self.batch_size,) + self.img_size + (1,), dtype="uint8")
for j, path in enumerate(batch_target_img_paths):
img = load_img(path, target_size=self.img_size, color_mode="grayscale")
y[j] = np.expand_dims(img, 2)
# Ground truth labels are 1, 2, 3. Subtract one to make them 0, 1, 2:
y[j] -= 1
return x, y
DataSet
input_dir = "images/"
target_dir = "annotations/trimaps/"
batch_size = 32
input_img_paths = sorted(
[
os.path.join(input_dir, fname)
for fname in os.listdir(input_dir)
if fname.endswith(".jpg")
]
)
target_img_paths = sorted(
[
os.path.join(target_dir, fname)
for fname in os.listdir(target_dir)
if fname.endswith(".png") and not fname.startswith(".")
]
)
print("Number of samples:", len(input_img_paths))
for input_path, target_path in zip(input_img_paths[:10], target_img_paths[:10]):
print(input_path, "|", target_path)
Data Generator
# Split our img paths into a training and a validation set
val_samples = 1000
random.Random(1337).shuffle(input_img_paths)
random.Random(1337).shuffle(target_img_paths)
train_input_img_paths = input_img_paths[:-val_samples]
train_target_img_paths = target_img_paths[:-val_samples]
val_input_img_paths = input_img_paths[-val_samples:]
val_target_img_paths = target_img_paths[-val_samples:]
# Instantiate data Sequences for each split
train_gen = BatchGenerator(
batch_size, img_size, train_input_img_paths, train_target_img_paths
)
val_gen = BatchGenerator(batch_size, img_size, val_input_img_paths,
val_target_img_paths)
Related
Hello I am trying to Use Tkinter as a GUI for the Prediction of a Binary Model. but keep getting a problem IndexError: tuple index out of range I Believe that there is a problem with the Size Inputs but I am lost as to where to start on where to modify so that the out of the Creation of the Model fits the predictors Desired Input
this is the Code I used for the creation of the Model
# dimensions of our images.
img_width, img_height = 480, 289
train_data_dir = r'C:\Users\felix\OneDrive\Desktop\Datasets\TRAIN'
validation_data_dir = r'C:\Users\felix\OneDrive\Desktop\Datasets\TEST'
nb_train_samples = 23
nb_validation_samples = 6
epochs = 1
batch_size = 1
if K.image_data_format() == 'channels_first':
input_shape = (1, img_width, img_height)
else:
input_shape = (img_width, img_height, 1)
from keras.applications.vgg16 import VGG16
from keras.models import Model
from keras.layers import Dense
vgg = VGG16(include_top=False, weights='imagenet', input_shape=[], pooling='avg')
x = vgg.output
x = Dense(1, activation='sigmoid')(x)
model = Model(vgg.input, x)
model.summary()
model.compile(keras.optimizers.Adam(lr=1e-5), 'binary_crossentropy', metrics=['accuracy'])
model.save('working.h5')
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
import seaborn as sns
test_steps_per_epoch = numpy.math.ceil(validation_generator.samples / validation_generator.batch_size)
predictions = model.predict_generator(validation_generator, steps=test_steps_per_epoch)
# Get most likely class
predicted_classes = numpy.argmax(predictions, axis=1)
true_classes = validation_generator.classes
class_labels = list(validation_generator.class_indices.keys())
report = classification_report(true_classes, predicted_classes, target_names=class_labels)
print(report)
cm=confusion_matrix(true_classes,predicted_classes)
sns.heatmap(cm, annot=True)
print(cm)
plt.show()
while this is the Tkinter Code I Used for the Model Prediction
import tensorflow as tf
model = tf.keras.models.load_model(r'C:\Users\felix\PycharmProjects\CatsDogs\working.h5')
classes = ["Health", "Unhealthy"]
top=tk.Tk()
top.geometry('800x600')
top.title('Health Detector')
top.configure(background='white')
label=Label(top,background='white', font=('arial',20,'bold'))
sign_image = Label(top)
def prepare(filepath):
IMG_SIZE = 50 # 50 in txt-based
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE) # read in the image, convert to grayscale
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) # resize image to match model's expected sizing
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1) # return the image with shaping that TF wants.
def classify(file_path):
global label_packed
pred = (model.predict(file_path) > 0.5).astype("int32")
sign = classes[pred[0, 0]]
print(sign)
label.configure(foreground='black', text=sign)
def show_classify_button(file_path):
classify_b=Button(top,text="Authenticate",
command=lambda: classify(file_path),padx=10,pady=5)
classify_b.configure(background='black', foreground='white',
font=('arial',10,'bold'))
classify_b.place(relx=0.43,rely=0.93)
def upload_image():
try:
file_path=filedialog.askopenfilename()
uploaded=Image.open(file_path)
uploaded.thumbnail(((top.winfo_width()/2.25),
(top.winfo_height()/2.25)))
im=ImageTk.PhotoImage(uploaded)
sign_image.configure(image=im)
sign_image.image=im
label.configure(text='')
show_classify_button(file_path)
except:
pass
upload=Button(top,text="Upload the Findings",command=upload_image,
padx=10,pady=5)
upload.configure(background='black', foreground='white',
font=('arial',10,'bold'))
upload.pack(side=BOTTOM,pady=50)
sign_image.pack(side=BOTTOM,expand=True)
label.pack(side=BOTTOM,expand=True)
heading = Label(top, text="Health Detector",pady=20, font=('arial',20,'bold'))
heading.configure(background='white',foreground='black')
heading.pack()
top.mainloop()
I tried to Change the IMG_SIZE into img_width, img_height Also I have tried to change the Input Shapes but still same problem Maybe I did it wrong or that was not the right fix. I was Expecting for Tkinter to have an Output of Either Healthy or Unhealthy
here are the traceback
Traceback (most recent call last):
File "C:\Users\felix\anaconda3\envs\pythonProject\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\felix\Dropbox\PC\Downloads\64x300-CNN.model-20230115T145146Z-001\64x300-CNN.model\fly.py", line 35, in <lambda>
command=lambda: classify(file_path),padx=10,pady=5)
File "C:\Users\felix\Dropbox\PC\Downloads\64x300-CNN.model-20230115T145146Z-001\64x300-CNN.model\fly.py", line 28, in classify
pred = (model.predict(file_path) > 0.5).astype("int32")
File "C:\Users\felix\anaconda3\envs\pythonProject\lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:\Users\felix\anaconda3\envs\pythonProject\lib\site-packages\tensorflow\python\framework\tensor_shape.py", line 906, in __getitem__
return self._dims[key]
I want to train a 1D CNN on time series. I get the following error message 1D target tensor expected, multi-target not supported
Here is the code with simulated data corresponding to the structures of my data as well as the error message
import torch
from torch.utils.data import DataLoader
import torch.utils.data as data
import torch.nn as nn
import numpy as np
import random
from tqdm.notebook import tqdm
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
train_dataset = []
n_item = 20
for i in range(0,n_item):
train_data = np.random.uniform(-10, 10, 500)
train_dataset.append(train_data)
train_dataset = np.asarray(train_dataset)
train_dataset.shape
ecg_train = torch.from_numpy(train_dataset).float()
labels_train = np.random.randint(2, size=n_item)
labels_train = torch.from_numpy(labels_train).long()
val_dataset = []
n_item = 10
for i in range(0,n_item):
val_data = np.random.uniform(-10, 10, 500)
val_dataset.append(val_data)
val_dataset = np.asarray(val_dataset)
val_dataset.shape
ecg_validation = torch.from_numpy(val_dataset).float()
labels_validation = np.random.randint(2, size=n_item)
labels_validation = torch.from_numpy(labels_validation).long()
class ECGNet(data.Dataset):
"""ImageNet Limited dataset."""
def __init__(self, ecgs, labls, transform=None):
self.ecg = ecgs
self.target = labls
self.transform = transform
def __getitem__(self, idx):
ecgVec = self.ecg[idx] #.reshape(10, -1)
labelID = self.target[idx].reshape(1)
return ecgVec,labelID
def __len__(self):
return len(self.ecg)
train_data = ECGNet(ecg_train,
labels_train,
)
print("size of Training dataset: {}".format(len(train_data)))
validation_data = ECGNet(ecg_validation,
labels_validation,
)
print("size of Training dataset: {}".format(len(validation_data)))
batch_size = 1
train_dataloader = DataLoader(dataset = train_data,
batch_size=batch_size,
shuffle = True,
num_workers = 0)
val_dataloader = DataLoader(dataset = validation_data,
batch_size=batch_size,
shuffle = True,
num_workers = 0)
def train_epoch(model, train_dataloader, optimizer, loss_fn):
losses = []
correct_predictions = 0
# Iterate mini batches over training dataset
for images, labels in tqdm(train_dataloader):
images = images.to(device)
#labels = labels.squeeze_()
labels = labels.to(device)
#labels = labels.to(device=device, dtype=torch.int64)
# Run predictions
output = model(images)
# Set gradients to zero
optimizer.zero_grad()
# Compute loss
loss = loss_fn(output, labels)
# Backpropagate (compute gradients)
loss.backward()
# Make an optimization step (update parameters)
optimizer.step()
# Log metrics
losses.append(loss.item())
predicted_labels = output.argmax(dim=1)
correct_predictions += (predicted_labels == labels).sum().item()
accuracy = 100.0 * correct_predictions / len(train_dataloader.dataset)
# Return loss values for each iteration and accuracy
mean_loss = np.array(losses).mean()
return mean_loss, accuracy
def evaluate(model, dataloader, loss_fn):
losses = []
correct_predictions = 0
with torch.no_grad():
for images, labels in dataloader:
images = images.to(device)
#labels = labels.squeeze_()
labels = labels.to(device=device, dtype=torch.int64)
# Run predictions
output = model(images)
# Compute loss
loss = loss_fn(output, labels)
# Save metrics
predicted_labels = output.argmax(dim=1)
correct_predictions += (predicted_labels == labels).sum().item()
losses.append(loss.item())
mean_loss = np.array(losses).mean()
accuracy = 100.0 * correct_predictions / len(dataloader.dataset)
# Return mean loss and accuracy
return mean_loss, accuracy
def train(model, train_dataloader, val_dataloader, optimizer, n_epochs, loss_function):
# We will monitor loss functions as the training progresses
train_losses = []
val_losses = []
train_accuracies = []
val_accuracies = []
for epoch in range(n_epochs):
model.train()
train_loss, train_accuracy = train_epoch(model, train_dataloader, optimizer, loss_fn)
model.eval()
val_loss, val_accuracy = evaluate(model, val_dataloader, loss_fn)
train_losses.append(train_loss)
val_losses.append(val_loss)
train_accuracies.append(train_accuracy)
val_accuracies.append(val_accuracy)
print('Epoch {}/{}: train_loss: {:.4f}, train_accuracy: {:.4f}, val_loss: {:.4f}, val_accuracy: {:.4f}'.format(epoch+1, n_epochs,
train_losses[-1],
train_accuracies[-1],
val_losses[-1],
val_accuracies[-1]))
return train_losses, val_losses, train_accuracies, val_accuracies
class Simple1DCNN(torch.nn.Module):
def __init__(self):
super(Simple1DCNN, self).__init__()
self.layer1 = torch.nn.Conv1d(in_channels=50,
out_channels=20,
kernel_size=5,
stride=2)
self.act1 = torch.nn.ReLU()
self.layer2 = torch.nn.Conv1d(in_channels=20,
out_channels=10,
kernel_size=1)
self.fc1 = nn.Linear(10* 3, 2)
def forward(self, x):
print(x.shape)
x = x.view(1, 50,-1)
print(x.shape)
x = self.layer1(x)
print(x.shape)
x = self.act1(x)
print(x.shape)
x = self.layer2(x)
print(x.shape)
x = x.view(1,-1)
print(x.shape)
x = self.fc1(x)
print(x.shape)
print(x)
return x
model_a = Simple1DCNN()
model_a = model_a.to(device)
criterion = nn.CrossEntropyLoss()
loss_fn = torch.nn.CrossEntropyLoss()
n_epochs_a = 50
learning_rate_a = 0.01
alpha_a = 1e-5
momentum_a = 0.9
optimizer = torch.optim.SGD(model_a.parameters(),
momentum = momentum_a,
nesterov = True,
weight_decay = alpha_a,
lr=learning_rate_a)
train_losses_a, val_losses_a, train_acc_a, val_acc_a = train(model_a,
train_dataloader,
val_dataloader,
optimizer,
n_epochs_a,
loss_fn
)
Error message:
cpu
size of Training dataset: 20
size of Training dataset: 10
0%| | 0/20 [00:00<?, ?it/s]
torch.Size([1, 500])
torch.Size([1, 50, 10])
torch.Size([1, 20, 3])
torch.Size([1, 20, 3])
torch.Size([1, 10, 3])
torch.Size([1, 30])
torch.Size([1, 2])
tensor([[ 0.5785, -1.0169]], grad_fn=<AddmmBackward>)
Traceback (most recent call last):
File "SO_question.py", line 219, in <module>
train_losses_a, val_losses_a, train_acc_a, val_acc_a = train(model_a,
File "SO_question.py", line 137, in train
train_loss, train_accuracy = train_epoch(model, train_dataloader, optimizer, loss_fn)
File "SO_question.py", line 93, in train_epoch
loss = loss_fn(output, labels)
File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/modules/loss.py", line 961, in forward
return F.cross_entropy(input, target, weight=self.weight,
File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/functional.py", line 2468, in cross_entropy
return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/functional.py", line 2264, in nll_loss
ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
RuntimeError: 1D target tensor expected, multi-target not supported
What am I doing wrong?
You are using nn.CrossEntropyLoss as the criterion for your training. You correctly passed the labels as indices of the ground truth class: 0s and 1s. However, as the error message suggests, it needs to be a 1D tensor!
Simply remove the reshape in ECGNet's __getitem__:
def __getitem__(self, idx):
ecgVec = self.ecg[idx]
labelID = self.target[idx]
return ecgVec,labelID
Edit
I want to increase the batch_size to 8. But now I get the error [...]
You are doing a lot of broadcasting (flattening) which surely will affect the batch size. As a general rule of thumb never fiddle with axis=0. For instance, if you have an input shape of (8, 500), straight off you have a problem when doing x.view(1, 50, -1). Since the resulting tensor will be (1, 50, 80) (the desired shape would have been (8, 50, 10)). Instead, you could broadcast with x.view(x.size(0), 50, -1).
Same with x.view(1, -1) later down forward. You are looking to flatten the tensor, but you should not flatten it along with the batches, they need to stay separated! It's safer to use torch.flatten, yet I prefer nn.Flatten which flattens from axis=1 to axis=-1 by default.
My personal advice is to start with a simple setup (without train loops etc...) to verify the architecture and intermediate output shapes. Then, add the necessary logic to handle the training.
class ECGNet(data.Dataset):
"""ImageNet Limited dataset."""
def __init__(self, ecgs, labls, transform=None):
self.ecg = ecgs
self.target = labls
self.transform = transform
def __getitem__(self, idx):
ecgVec = self.ecg[idx]
labelID = self.target[idx]
return ecgVec, labelID
def __len__(self):
return len(self.ecg)
class Simple1DCNN(nn.Module):
def __init__(self):
super(Simple1DCNN, self).__init__()
self.layer1 = nn.Conv1d(in_channels=50,
out_channels=20,
kernel_size=5,
stride=2)
self.act1 = nn.ReLU()
self.layer2 = nn.Conv1d(in_channels=20,
out_channels=10,
kernel_size=1)
self.fc1 = nn.Linear(10*3, 2)
self.flatten = nn.Flatten()
def forward(self, x):
x = x.view(x.size(0), 50, -1)
x = self.layer1(x)
x = self.act1(x)
x = self.layer2(x)
x = self.flatten(x)
x = self.fc1(x)
return x
batch_size = 8
train_data = ECGNet(ecg_train, labels_train)
train_dl = DataLoader(dataset=train_data,
batch_size=batch_size,
shuffle=True,
num_workers=0)
model = Simple1DCNN()
criterion = nn.CrossEntropyLoss()
Then
>>> x, y = next(iter(train_dl))
>>> y_hat = model(x)
>>> y_hat.shape
torch.Size([8, 2])
Also, make sure your loss works:
>>> criterion(y_hat, y)
tensor(..., grad_fn=<NllLossBackward>)
I'm trying to create a model with PyTorch but during the forward, I encounter this issue "RuntimeError: expected scalar type Long but found Float".
Source code:
dataset_loader.py:
import h5py
import torch
import numpy as np
from PIL import Image
from os import listdir
from sklearn.utils import shuffle
WIDTH = 64
HEIGHT = 64
CREATE_DATASET = False
def load_set(path: str):
dataset = []
for f in listdir(path):
dataset.append(np.asarray(Image.open(path + f).resize((WIDTH, HEIGHT)).convert('RGB'), dtype=np.int32).reshape(3, WIDTH, HEIGHT))
return np.array(dataset, dtype=np.int32)
def create_batch(dataset, labels, batch_size):
dataset_result = []
labels_result = []
data_batch = []
label_batch = []
for index in range(len(dataset)):
if len(data_batch) == batch_size:
# dataset_result.append(np.array(data_batch, dtype=np.int32))
# labels_result.append(np.array(label_batch, dtype=np.int32))
dataset_result.append(data_batch)
labels_result.append(label_batch)
data_batch = []
label_batch = []
else:
# data_batch.append(torch.tensor(dataset[index]))
# label_batch.append(torch.tensor(labels[index]))
data_batch.append(np.array(dataset[index], dtype=np.int32))
label_batch.append(np.array(labels[index], dtype=np.int32))
dataset_result = np.array(dataset_result, dtype=np.int32)
labels_result = np.array(labels_result, dtype=np.int32)
return torch.from_numpy(dataset_result), torch.from_numpy(labels_result)
# return dataset_result, labels_result
def create_dataset():
dataset_file = h5py.File("dataset.hdf5", "w")
train_normal = load_set("chest_xray/train/NORMAL/")
dataset_file.create_dataset("train_normal", train_normal.shape, dtype=np.int32, data=train_normal)
train_pneumonia = load_set("chest_xray/train/PNEUMONIA/")
dataset_file.create_dataset("train_pneumonia", train_pneumonia.shape, dtype=np.int32, data=train_pneumonia)
test_normal = load_set("chest_xray/test/NORMAL/")
dataset_file.create_dataset("test_normal", test_normal.shape, dtype=np.int32, data=test_normal)
test_pneumonia = load_set("chest_xray/test/PNEUMONIA/")
dataset_file.create_dataset("test_pneumonia", test_pneumonia.shape, dtype=np.int32, data=test_pneumonia)
val_normal = load_set("chest_xray/val/NORMAL/")
dataset_file.create_dataset("val_normal", val_normal.shape, dtype=np.int32, data=val_normal)
val_pneumonia = load_set("chest_xray/val/PNEUMONIA/")
dataset_file.create_dataset("val_pneumonia", val_pneumonia.shape, dtype=np.int32, data=val_pneumonia)
def load_dataset():
dataset = h5py.File('dataset.hdf5', 'r')
train_set = np.array(list(dataset["train_normal"]) + list(dataset["train_pneumonia"]), dtype=np.int32)
test_set = np.array(list(dataset["test_normal"]) + list(dataset["test_pneumonia"]), dtype=np.int32)
val_set = np.array(list(dataset["val_normal"]) + list(dataset["val_pneumonia"]), dtype=np.int32)
train_labels = [0] * len(dataset["train_normal"]) + [1] * len(dataset["train_pneumonia"])
test_labels = [0] * len(dataset["test_normal"]) + [1] * len(dataset["test_pneumonia"])
val_labels = [0] * len(dataset["val_normal"]) + [1] * len(dataset["val_pneumonia"])
BATCH_SIZE = 32
train_set, train_labels = shuffle(np.array(train_set, dtype=np.int32), np.array(train_labels, dtype=np.int32))
train_set, train_labels = create_batch(train_set, train_labels, BATCH_SIZE)
test_set, test_labels = shuffle(np.array(test_set, dtype=np.int32), np.array(test_labels, dtype=np.int32))
test_set, test_labels = create_batch(test_set, test_labels, BATCH_SIZE)
val_set, val_labels = shuffle(np.array(val_set, dtype=np.int32), np.array(val_labels, dtype=np.int32))
val_set, val_labels = create_batch(val_set, val_labels, BATCH_SIZE)
return train_set, train_labels, test_set, test_labels, val_set, val_labels, BATCH_SIZE
network.py:
import torch.nn as nn
import torch.nn.functional as F
class Network(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
self.fc1 = nn.Linear(in_features=12*5*5, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=60)
self.out = nn.Linear(in_features=60, out_features=2)
def forward(self, t):
t = self.conv1(t)
t = F.relu()
t = F.max_pool2d(t, kernel_size=2, stride=2)
t = F.relu(self.conv2(t))
t = F.max_pool2d(t, kernel_size=2, stride=2)
t = t.reshape(-1, 12 * 4 * 4)
t = F.relu(self.fc1(t))
t = F.relu(self.fc2(t))
t = self.out(t)
return t
main.py:
import numpy as np
import torch
import torch.optim as optim
import torch.nn.functional as F
import network
import dataset_loader
import matplotlib.pyplot as plt
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
WIDTH = 64
HEIGHT = 64
NEED_TO_CREATE_DATASET = False
if NEED_TO_CREATE_DATASET:
dataset_loader.create_dataset()
train_set, train_labels, test_set, test_labels, val_set, val_labels, BATCH_SIZE = dataset_loader.load_dataset()
TRAINING_SIZE = len(train_set) * BATCH_SIZE
TESTING_SIZE = len(test_set) * BATCH_SIZE
EPOCHS = 5
LEARNING_RATE = 0.01
network = network.Network().to(device)
optimizer = optim.Adam(network.parameters(), lr=LEARNING_RATE)
training_losses = []
training_accuracies = []
testing_losses = []
testing_accuracies = []
def get_num_correct(preds, labels):
return preds.argmax(dim=1).eq(labels).sum().item()
def train():
network.train()
correct_in_episode = 0
episode_loss = 0
for index, images in enumerate(train_set):
labels = train_labels[index]
print(images.shape)
# exit()
predictions = network(images.type(torch.LongTensor)) # TODO: fix crash "RuntimeError: expected scalar type Long but found Float"
# predictions = network(images)
loss = F.cross_entropy(predictions, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
episode_loss += loss.item()
correct_in_episode += get_num_correct(predictions, labels)
training_losses.append(episode_loss)
training_accuracies.append(correct_in_episode * 100 / TRAINING_SIZE)
print(f"Epoch: {epoch + 1} accuracy: {correct_in_episode * 100 / TRAINING_SIZE:.2f} loss: {episode_loss:.3f}", end="\t")
def test():
network.eval()
episode_loss = 0
correct_in_episode = 0
with torch.no_grad():
for index, images in enumerate(test_set):
labels = test_labels[index]
predictions = network(images)
loss = F.cross_entropy(predictions, labels)
episode_loss = loss.item()
correct_in_episode += get_num_correct(predictions, labels)
testing_losses.append(episode_loss)
testing_accuracies.append(correct_in_episode * 100 / TESTING_SIZE)
print(f'Validation: Accuracy: {correct_in_episode * 100 / TESTING_SIZE:.2f} loss: {episode_loss:.3f}')
for epoch in range(EPOCHS):
train()
test()
fig = plt.figure()
plt.plot(list(range(1, len(training_losses)+1)), training_losses, color='blue')
plt.plot(list(range(1, len(testing_losses)+1)), testing_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('Loss')
fig = plt.figure()
plt.plot(list(range(1, len(training_accuracies)+1)), training_accuracies, color='blue')
plt.plot(list(range(1, len(testing_accuracies)+1)), testing_accuracies, color='red')
plt.legend(['Train Accuracy', 'Test Accuracy'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('Accuracy')
Error:
torch.Size([32, 3, 64, 64])
Traceback (most recent call last):
File "Soluce.py", line 86, in <module>
train()
File "Soluce.py", line 50, in train
predictions = network(images.type(torch.LongTensor)) # TODO: fix crash "RuntimeError: expected scalar type Long but found Float"
File "/home/thytu/.local/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/home/thytu/Prog/PoC/pool_2021/Day3/Admin-XRAI/Admin/network.py", line 15, in forward
t = self.conv1(t)
File "/home/thytu/.local/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/home/thytu/.local/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 423, in forward
return self._conv_forward(input, self.weight)
File "/home/thytu/.local/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 419, in _conv_forward
return F.conv2d(input, weight, self.bias, self.stride,
RuntimeError: expected scalar type Long but found Float
Do you have any ideas chat the issue is?
Thanks for your time and your help.
(PS: It's not about Cross-Entropy, it happens before)
I also encountered the same problem. My code is as follows:
my code:
import torch
from torchvision.models import alexnet
model = alexnet(pretrained=True)
input_data = torch.randint(255, size=(1, 3, 224, 224), dtype=torch.long)
outputs = model(input_data)
print(outputs)
very simple operation, but it's error:
Traceback (most recent call last):
File "D:\Program Files\JetBrains\PyCharm 2021.1.3\plugins\python\helpers\pydev\pydevd.py", line 1483, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "D:\Program Files\JetBrains\PyCharm 2021.1.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "F:/Python/TF2/main.py", line 9, in <module>
outputs = model(input_data)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torchvision\models\alexnet.py", line 46, in forward
x = self.features(x)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\container.py", line 139, in forward
input = module(input)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\conv.py", line 443, in forward
return self._conv_forward(input, self.weight, self.bias)
File "D:\Anaconda\envs\tf2x\lib\site-packages\torch\nn\modules\conv.py", line 440, in _conv_forward
self.padding, self.dilation, self.groups)
RuntimeError: expected scalar type Long but found Float
and but I think it's the weight problem, but I immediately changed this idea. Because it's only an official model, the problem is located in input data. So I changed the code again:
Changed code:
input_data = torch.rand(size=(1, 3, 224, 224))
outputs = model(input_data)
print(outputs)
and then, it's ok:
tensor([[-1.5024e+00, -1.1394e+00, -3.7661e-01, 1.1497e+00, 1.1878e-01,
-6.6696e-01, 3.8399e-01, -1.0095e+00, -1.3813e+00, -1.4772e+00,
...
Process finished with exit code 0
Therefore, my suggestion is that you can try to change the type of input data.
No idea what's happening in my case:
Error message:
Traceback (most recent call last):
File "plot_parametric_pytorch.py", line 127, in <module>
ops = opfun(X_train[smpl])
File "plot_parametric_pytorch.py", line 81, in <lambda>
opfun = lambda X: model.forward(Variable(torch.from_numpy(X)))
File "/mnt_home/klee/LBSBGenGapSharpnessResearch/vgg.py", line 43, in forward
x = self.features(x).to(device)
File "/home/klee/anaconda3/envs/sharpenv/lib/python3.7/site-packages/torch/nn/modules/module.py", line 550, in __call__
result = self.forward(*input, **kwargs)
File "/home/klee/anaconda3/envs/sharpenv/lib/python3.7/site-packages/torch/nn/modules/container.py", line 100, in forward
input = module(input)
File "/home/klee/anaconda3/envs/sharpenv/lib/python3.7/site-packages/torch/nn/modules/module.py", line 550, in __call__
result = self.forward(*input, **kwargs)
File "/home/klee/anaconda3/envs/sharpenv/lib/python3.7/site-packages/torch/nn/modules/conv.py", line 349, in forward
return self._conv_forward(input, self.weight)
File "/home/klee/anaconda3/envs/sharpenv/lib/python3.7/site-packages/torch/nn/modules/conv.py", line 346, in _conv_forward
self.padding, self.dilation, self.groups)
RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same
Source code:
[import statements]
cudnn.benchmark = True
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train.astype('float32')
X_train = np.transpose(X_train, axes=(0, 3, 1, 2))
X_test = X_test.astype('float32')
X_test = np.transpose(X_test, axes=(0, 3, 1, 2))
X_train /= 255
X_test /= 255
device = torch.device('cuda:0')
# This is where you can load any model of your choice.
# I stole PyTorch Vision's VGG network and modified it to work on CIFAR-10.
# You can take this line out and add any other network and the code
# should run just fine.
model = vgg.vgg11_bn()
model.to(device)
# Forward pass
opfun = lambda X: model.forward(Variable(torch.from_numpy(X))) <------
# Forward pass through the network given the input
predsfun = lambda op: np.argmax(op.data.numpy(), 1)
# Do the forward pass, then compute the accuracy
accfun = lambda op, y: np.mean(np.equal(predsfun(op), y.squeeze()))*100
# Initial point
x0 = deepcopy(model.state_dict())
# Number of epochs to train for
# Choose a large value since LB training needs higher values
# Changed from 150 to 30
nb_epochs = 30
batch_range = [25, 40, 50, 64, 80, 128, 256, 512, 625, 1024, 1250, 1750, 2048, 2500, 3125, 4096, 5000]
# parametric plot (i.e., don't train the network)
hotstart = False
if not hotstart:
for batch_size in batch_range:
optimizer = torch.optim.Adam(model.parameters())
model.load_state_dict(x0)
model.to(device)
average_loss_over_epoch = '-'
print('Optimizing the network with batch size %d' % batch_size)
np.random.seed(1337) #So that both networks see same sequence of batches
for e in range(nb_epochs):
model.eval()
print('Epoch:', e, ' of ', nb_epochs, 'Average loss:', average_loss_over_epoch)
average_loss_over_epoch = 0
# Checkpoint the model every epoch
torch.save(model.state_dict(), "./models/30EpochC3ExperimentBatchSize" + str(batch_size) + ".pth")
array = np.random.permutation(range(X_train.shape[0]))
slices = X_train.shape[0] // batch_size
beginning = 0
end = 1
# Training loop!
for _ in range(slices):
start_index = batch_size * beginning
end_index = batch_size * end
smpl = array[start_index:end_index]
model.train()
optimizer.zero_grad()
ops = opfun(X_train[smpl]) <-----
tgts = Variable(torch.from_numpy(y_train[smpl]).long().squeeze())
loss_fn = F.nll_loss(ops, tgts)
average_loss_over_epoch += loss_fn.data.numpy() / fractions_of_dataset
loss_fn.backward()
optimizer.step()
beginning += 1
end += 1
And here is where the model is constructed (and the forward method) [vgg.py]
import torch
import torch.nn as nn
F = nn.functional
import torch.utils.model_zoo as model_zoo
import math
__all__ = [
'VGG', 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn',
'vgg19_bn', 'vgg19',
]
model_urls = {
'vgg11': 'https://s3.amazonaws.com/pytorch/models/vgg11-fb7e83b2.pth',
'vgg13': 'https://s3.amazonaws.com/pytorch/models/vgg13-58758d87.pth',
'vgg16': 'https://s3.amazonaws.com/pytorch/models/vgg16-82412952.pth',
'vgg19': 'https://s3.amazonaws.com/pytorch/models/vgg19-341d7465.pth',
}
class VGG(nn.Module):
def __init__(self, features):
super(VGG, self).__init__()
self.features = features.cuda()
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(512, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Linear(4096, 10),
)
self._initialize_weights()
def forward(self, x):
device = torch.device('cuda:0')
x.cuda()
x.to(device)
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return F.log_softmax(x)
My full source code is here https://github.com/kristyelee/LBSBGenGapSharpnessResearch/blob/master/plot_parametric_pytorch.py
https://github.com/kristyelee/LBSBGenGapSharpnessResearch/blob/master/vgg.py
I read this for some information, RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same but I'm not sure how to put the input tensors on the GPU.. I kind of tried to do this with x.cuda() not sure if this is right or not though. I really want to put my model on the GPU to train faster (because I'm currently just using the CPU otherwise, which is slow)
I've been trying to train a CNN using Keras with data augmentation applied to a series of images and their segmentation masks. The online example says that in order to do this, I should create two separate generators using flow_from_directory() and then zip them.
But instead can I just have two numpy arrays for the images and masks, use the flow() function and instead do this:
# Create image generator
data_gen_args = dict(rotation_range=5,
width_shift_range=0.1,
height_shift_range=0.1,
validation_split=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
seed = 1
# Create training and validation generators including masks
train_generator = image_datagen.flow(images, masks, seed=seed, subset='training')
val_train_generator = image_datagen.flow(images, masks, seed=seed, subset='validation')
# Train model
model.fit_generator(train_generator, steps_per_epoch=50,
validation_data = val_train_generator,
validation_steps = 10, shuffle=True, epochs=20)
And if not, why not? It seems that if I run through the generator, I can only output the images and not the masks as well so I'm concerned it's not doing what I'd like it to.
You need a custom generator that applies the same augmentation to image and mask.
Keras ImageDataGenerator takes 2 arguments (image,label or mask) and apply transformations to only to first (image). You can use my generator below:
# Create image generator
data_gen_args = dict(rotation_range=5,
width_shift_range=0.1,
height_shift_range=0.1,
validation_split=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
seed = 1
def XYaugmentGenerator(X1, y, seed, batch_size):
genX1 = gen.flow(X1, y, batch_size=batch_size, seed=seed)
genX2 = gen.flow(y, X1, batch_size=batch_size, seed=seed)
while True:
X1i = genX1.next()
X2i = genX2.next()
yield X1i[0], X2i[0]
# Train model
model.fit_generator(XYaugmentGenerator(images, masks, seed, batch_size), steps_per_epoch=np.ceil(float(len(images)) / float(batch_size)),
validation_data = XYaugmentGenerator(images_valid, masks_valid, batch_size),
validation_steps = np.ceil(float(len(images_valid)) / float(batch_size))
, shuffle=True, epochs=20)
In deep learning, for segmentation problem, one can use customer 'DataGenerator' function instead of keras ImageDataGenerator.
How to write a customer DataGenerator?
Writing a customer DataGenerator helps when dealing with Image Segmentation problem.
Solution:
If your training and test images are in a folder and the masks and labels are in a csv, use the below function-- a custom-- DataGenerator:
class DataGenerator(keras.utils.Sequence):
'Generates data for Keras'
def __init__(self, list_IDs, df, target_df=None, mode='fit',
base_path='../train_images',
batch_size=16, dim=(1400, 2100), n_channels=3, reshape=None,
augment=False, n_classes=2, random_state=42, shuffle=True):
self.dim = dim
self.batch_size = batch_size
self.df = df
self.mode = mode
self.base_path = base_path
self.target_df = target_df
self.list_IDs = list_IDs
self.reshape = reshape
self.n_channels = n_channels
self.augment = augment
self.n_classes = n_classes
self.shuffle = shuffle
self.random_state = random_state
self.on_epoch_end()
np.random.seed(self.random_state)
def __len__(self):
'Denotes the number of batches per epoch'
return int(np.floor(len(self.list_IDs) / self.batch_size))
def __getitem__(self, index):
'Generate one batch of data'
# Generate indexes of the batch
indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
# Find list of IDs
list_IDs_batch = [self.list_IDs[k] for k in indexes]
X = self.__generate_X(list_IDs_batch)
if self.mode == 'fit':
y = self.__generate_y(list_IDs_batch)
if self.augment:
X, y = self.__augment_batch(X, y)
return X, y
elif self.mode == 'predict':
return X
else:
raise AttributeError('The mode parameter should be set to "fit" or "predict".')
def on_epoch_end(self):
'Updates indexes after each epoch'
self.indexes = np.arange(len(self.list_IDs))
if self.shuffle == True:
np.random.seed(self.random_state)
np.random.shuffle(self.indexes)
def __generate_X(self, list_IDs_batch):
'Generates data containing batch_size samples'
# Initialization
if self.reshape is None:
X = np.empty((self.batch_size, *self.dim, self.n_channels))
else:
X = np.empty((self.batch_size, *self.reshape, self.n_channels))
# Generate data
for i, ID in enumerate(list_IDs_batch):
im_name = self.df['ImageId'].iloc[ID]
img_path = f"{self.base_path}/{im_name}"
img = self.__load_rgb(img_path)
if self.reshape is not None:
img = np_resize(img, self.reshape)
# Store samples
X[i,] = img
return X
def __generate_y(self, list_IDs_batch):
if self.reshape is None:
y = np.empty((self.batch_size, *self.dim, self.n_classes), dtype=int)
else:
y = np.empty((self.batch_size, *self.reshape, self.n_classes), dtype=int)
for i, ID in enumerate(list_IDs_batch):
im_name = self.df['ImageId'].iloc[ID]
image_df = self.target_df[self.target_df['ImageId'] == im_name]
rles = image_df['EncodedPixels'].values
if self.reshape is not None:
masks = build_masks(rles, input_shape=self.dim, reshape=self.reshape)
else:
masks = build_masks(rles, input_shape=self.dim)
y[i, ] = masks
return y
def __load_grayscale(self, img_path):
img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
img = img.astype(np.float32) / 255.
img = np.expand_dims(img, axis=-1)
return img
def __load_rgb(self, img_path):
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32) / 255.
return img
def __random_transform(self, img, masks):
composition = albu.Compose([
albu.HorizontalFlip(),
albu.VerticalFlip(),
albu.ShiftScaleRotate(rotate_limit=30, shift_limit=0.1)
#albu.ShiftScaleRotate(rotate_limit=90, shift_limit=0.2)
])
composed = composition(image=img, mask=masks)
aug_img = composed['image']
aug_masks = composed['mask']
return aug_img, aug_masks
def __augment_batch(self, img_batch, masks_batch):
for i in range(img_batch.shape[0]):
img_batch[i, ], masks_batch[i, ] = self.__random_transform(
img_batch[i, ], masks_batch[i, ])
return img_batch, masks_batch
Reference:
http://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly
According my experiment, you can't just use zip(img_generator,mask_generator).Although error won't occur, it will run forever. Seems that it return a infinite generator. To solve this problem, you may use while true:yield(img_generator.next(),mask_generator.next()).