how to use model.fit in spatial pyramid pooling net with keras - keras

SPP net is used for variable size input images. SPP Net implementation in keras in here uses two model.fit for two sizes of images. I have 278 images of all different sizes, so how to use model.fit in this case? and how keras calculating efficiency and other performance parameter after two model.fit uses? I am quoting some lines from spp paper where author write that
For a single network to accept variable input sizes, we approximate it by multiple networks that share all parameters, while each of these networks is trained using a fixed input size. In each epoch we train the network with a given input size, and switch to another input size for the next epoch. Experiments show that this multi-size training converges just as the traditional single-size training,and leads to better testing accuracy.
Should we have to use as many epoch as we have no. of variable size images?

You can try generator (see stanford.edu).
If all images are different sizes, then the batch size should be 1. Pay attention to the X and y shapes.
class WordImageGeneratorSPP(object):
def __init__(self, shuffle=True):
self.shuffle = shuffle
def generate(self, items):
while 1:
if self.shuffle:
random.shuffle(items)
for item in items:
X = item[0]
y = item[1]
yield X, y
train_gen = WordImageGeneratorSPP().generate(train_data)
model.fit_generator(generator=train_gen, ...)
You can plot the generator output, but you should also pay attention to the X and y shapes.
import matplotlib.pyplot as plt
train_gen = WordImageGeneratorSPP().generate(train_data)
for X, y in train_gen:
plt.imshow(X)
plt.title(y)
plt.show()

Related

Ideal number of nodes in an autoencoder for small dataset with few features in PyTorch

I am dealing with a dataset with 6 features and around 1000 samples total. I am hoping to use unsupervised learning -- with dimensionality reduction followed by clustering -- as there are labels for these data which are often incorrect. I tested linear methods like PCA first, and found that the data are not linearly separable. I am now using an autoencoder to perform dimensionality reduction, but am coming across some questions regarding the number of nodes. I am testing a simple autoencoder in PyTorch at the moment, with one hidden layers. However, I am uncertain of the number of nodes that would be appropriate for this problem. I am a bit confused about whether the advice here about node selection references to 'input layer size' as the total training data size (0.2*1000 samples), total dataset (1000 samples), or features themself (6 features).
Here is my current PyTorch code aimed at handling this problem:
class Autoencoder(nn.Module):
def __init__(self,input_dim = 6, latent_dim = 2):
super(Autoencoder, self).__init__()
self.input_dim = input_dim
self.latent_dim = latent_dim
self.encode = nn.Sequential(nn.Linear(self.input_dim,32),
nn.LeakyReLU(0.02),
nn.Linear(16, self.latent_dim),
)
self.decode = nn.Sequential(nn.Linear(self.latent_dim,32),
nn.LeakyReLU(0.02),
nn.Linear(32,self.input_dim)
)
self.apply(weights_init)
def encoded(self, x):
#encodes data to latent space
return self.encode(x)
def decoded(self, x):
#decodes latent space data to 'real' space
return self.decode(x)
def forward(self, x):
en = self.encoded(x)
de = self.decoded(en)
return de`
This yields a training/test loss as follows:
and latent space as follows:
I would greatly appreciate any advice on this subject. I recognize this is likely a rather simple question, so apologies in advance!

How to code Pytorch to fit a different polynomal to every column/row in an image?

Fitting a single polynomial to a bunch of data is pretty easy in Pytorch using an nn.Linear layer. I've included a trivial example at the end of this post. But suppose I have tons of data split into groups, and I want to fit a different polynomial to each group. As an example, find the particular quadratic coefficients that fit each column in this image:
In other words, I want to simultaneously find the coefficients for N polynomials of order n, given m data per set to be fit:
In the image above, there are m=80 points per dataset, and N=100 sets to fit.
This perfectly lends itself to tensor manipulation and Pytorch on a gpu should make this blindingly fast by fitting all N at once. Problem is, I'm having a terrible brain fart, and haven't been able to wrap my head around the right layer configuration. Basically I need N nn.Linear layers, each operating on its own dataset. If this were convolution, I'd use a depthwise layer...
Example network to fit one polynomial where X are the m x p abscissa data, y are the m ordinate data, and we want to find the p coefficients.
class polyfit(torch.nn.Module):
def __init__(self,n=2):
super(polyfit, self).__init__()
self.poly = torch.nn.Linear(n,1,bias=False,)
def forward(self, x):
print(x.shape,self.poly)
return self.poly(x)
model = polyfit(n)
loss = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
for epoch in range(100): # or however I want to run the loops
output = model(X)
mse = loss(output, y)
optimizer.zero_grad()
mse.backward()
optimizer.step()
Figured it out after thinking about my Depthwise Convolution comment. A Conv1D with just 3 parameters times a tensor with values [1,x,x**2] is a quadratic, same as with a Linear layer with n=3. So the layer needs to be:
self.poly = torch.nn.Conv1d(N,N,n+1,bias=False,groups=N)
Just have to make sure the X,y tensors are the right dimensions of [m, N, n] and [m, N, 1] respectively.

Fit a Gaussian curve with a neural network using Pytorch

Suppose the following model :
import torch.nn as nn
class PGN(nn.Module):
def __init__(self, input_size):
super(PGN, self).__init__()
self.linear = nn.Sequential(
nn.Linear(in_features=input_size, out_features=128),
nn.ReLU(),
nn.Linear(in_features=128, out_features=1)
)
def forward(self, x):
return self.linear(x)
I figure I have to modify the model to fit a 2-dimensional curve.
Is there a way to fit a Gaussian curve with mu=0 and sigma=0 using Pytorch? If so, can you show me?
A neural network can approximate an arbitrary function of any number of parameters to a space of any dimension.
To fit a 2 dimensional curve your network should be fed with vectors of size 2, that is a vector of x and y coordinates. The output is a single value of size 1.
For training you must generate ground truth data, that is a mapping between coordinates (x and y) and the value (z). The loss function should compare this ground truth value with the estimate of your network.
If it is just a tutorial to learn Pytorch and not a real application, you can define a function that for a given x and y output the gaussian value according to your parameters.
Then during training you randomly choose a x and y and feed this to the networks then do backprop with the true value.
For a function y = a*exp(-((x-b)^2)/2c^2),
Create this mathematical equation, for some values of x, (and a,b,c), get the outputs y. This will be your training set with x values as inputs and y values as output labels. Since this is not a linear equation, you will have to experiment with no of layers/neurons and other stuff, but it will give you a good enough approximation. For different values of a,b,c, generate your data for that and maybe try different things like adding those as inputs with x.

Why my deep learning model always give an output of 1 class?

I'm training a CNN model on Keras to classify images belong to 2 classes. I have about 600 images of class 0 and 1000 images of class 1. My model is shown below. The problem is it always gave me the output of the class with higher samples. I tried to change the last activation function into sigmoid but it did not help at all. I also tried to add batch normalization as well as regularization and dropout.
def model(input_shape):
#Define the input placeholder as a tensor with shape input_shape
X_input = Input(input_shape)
# First layer
X = Conv2D(32,(5,5),strides=(1,1),padding='same',name='conv1')(X_input)
X = BatchNormalization()(X)
X = Activation('relu')(X)
X = MaxPooling2D((3,3),strides=2,name='pool1')(X)
# Second layer
X = Conv2D(32,(5,5),strides=(1,1),padding='same',name='conv2')(X)
X = BatchNormalization()(X)
X = Activation('relu')(X)
X = AveragePooling2D((3,3),strides=2,name='pool2')(X)
# Third layer
X = Conv2D(64,(5,5),strides=(1,1),padding='same',name='conv3')(X)
X = BatchNormalization()(X)
X = Activation('relu')(X)
X = AveragePooling2D((3,3),strides=2,name='pool3')(X)
# Flatten
X = Flatten()(X)
X = Dense(64,activation='softmax',name='fc1')(X)
X = dropout(0.5)(X)
X = Dense(2,activation='softmax',name='fc2')(X)
# Create the model
model = Model(inputs = X_input,outputs = X)
return model
Okay, you have a 2-class classification problem, where the number of samples in the classes are imbalanced. This problem is especially common for medical diagnostics, and causes a lot of headache not only to you.
You have stated that the specific problem you are solving is classifying tumor histopathological images. These images are very rich in patterns, so 1600 images in total is typically not enough to learn meaningful features and representations. The distribution in minibatches is also imbalanced, so the gradient will always be slightly shifted (given that other filters are producing random noise since they didn't have time to learn meaningful features) towards the local minimum of one-class classification.
There are, however, several techniques to improve the performance:
Trim the larger class, so that the number of samples in each class is roughly the same. So in your case, reduce the class with 1000 samples to around 600.
If you don't want to train on less data, try assign a weight to each class. Here is a link to short example. So, in your specific case, you have 600 images of class A and 1000 images of class B. So, you can assign a weight 1.0 for class B and 10/6 to class A.
As stated above, 1600 samples is not enough to learn meaningful features. Especially when you have a Deep Neural Network. So, what you can try is Transfer Learning. A very detailed tutorial (which was one on SO Documentation) can be found here. Make sure to look closely at the layer's visualization in the tutorial.
Also, to test the model's capability, you might want to try intentional overfitting. A quick checklist can be found here.

How to get Conv2D layer filter weights

How do I get the weights of all filters (like 32 ,64, etc.) of a Conv2D layer in Keras after each epoch? I mention that, because initial weights are random but after optimization they will change.
I checked this answer but did not understand. Please help me find a solution of getting the weights of all the filter and after every epoch.
And one more question is that in Keras documentation for the Conv2D layer input shape is (samples, channels, rows, cols). What exactly does samples mean? Is it the total number of inputs we have (like in MNIST data set it is 60.000 training images) or the batch size (like 128 or other)?
Samples = batch size = number of images in a batch
Keras will often use None for this dimension, meaning it can vary and you don't have to set it.
Although this dimension actually exists, when you create a layer, you pass input_shape without it:
Conv2D(64,(3,3), input_shape=(channels,rows,cols))
#the standard it (rows,cols,channels), depending on your data_format
To have actions done after each epoch (or batch), you can use a LambdaCallback, passing the on_epoch_end function:
#the function to call back
def get_weights(epoch,logs):
wsAndBs = model.layers[indexOfTheConvLayer].get_weights()
#or model.get_layer("layerName").get_weights()
weights = wsAndBs[0]
biases = wsAndBs[1]
#do what you need to do with them
#you can see the epoch and the logs too:
print("end of epoch: " + str(epoch)) for instance
#the callback
from keras.callbacks import LambdaCallback
myCallback = LambdaCallback(on_epoch_end=get_weights)
Pass this callback to the training function:
model.fit(...,...,... , callbacks=[myCallback])

Resources