keras(cnn+nn) predicting only one class among 4 classes - machine-learning

I am using two different datasets having 1200 images each. First dataset has 4 classes and second dataset has 6 classes.
This is simple image classification problem. But while training, on each epoch I am getting same value for validation accuracy for both the datasets.
I have resized all the images of both datasets to 100x100 using imagemagick.
I don't know where I am making mistake.
Thanks in advance
terminal output :
Using Theano backend.
Couldn't import dot_parser, loading of dot files will not be possible.
X_train shape: (880, 3, 100, 100)
880 train samples
220 test samples
train:
0 418
3 179
2 174
1 109
dtype: int64
test:
0 98
3 55
2 43
1 24
dtype: int64
Train on 880 samples, validate on 220 samples
Epoch 1/5
880/880 [==============================] - 582s - loss: 1.3444 - acc: 0.4500 - val_loss: 1.2752 - val_acc: 0.4455
Epoch 2/5
880/880 [==============================] - 540s - loss: 1.2624 - acc: 0.4750 - val_loss: 1.2802 - val_acc: 0.4455
Epoch 3/5
880/880 [==============================] - 540s - loss: 1.2637 - acc: 0.4750 - val_loss: 1.2712 - val_acc: 0.4455
Epoch 4/5
880/880 [==============================] - 538s - loss: 1.2484 - acc: 0.4750 - val_loss: 1.2623 - val_acc: 0.4455
Epoch 5/5
880/880 [==============================] - 537s - loss: 1.2375 - acc: 0.4750 - val_loss: 1.2486 - val_acc: 0.4455
prediction on test data:
In [26]: model.predict_classes(X_test)
220/220 [==============================] - 37s
Out[26]:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
code:
from __future__ import print_function
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten, Reshape
from keras.layers.convolutional import Convolution2D, MaxPooling2D, Convolution1D, MaxPooling1D
from keras.optimizers import SGD
from keras.utils import np_utils, generic_utils
import numpy as np
from sklearn.cross_validation import train_test_split
import pandas as pd
batch_size = 30
nb_classes = 4
nb_epoch = 10
img_rows, img_cols = 100, 100
img_channels = 3
X = np.load( 'image-data.npy' )
y = np.load( 'image-class.npy' )
# the data, shuffled and split between train and test sets
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=100 )
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
print("train:\n ",pd.value_counts(y_train))
print("test:\n",pd.value_counts(y_test))
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(img_channels, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(1,1) ))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(1,1) ))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train , batch_size = batch_size, nb_epoch = nb_epoch,shuffle=True, show_accuracy=True,validation_data=(X_test,Y_test) )
out = model.predict_classes(X_test)

Related

Image Processing - Skimage or other

I am new to image processing. I am trying out a few experiments.
I have binarized my image with otsu
Found connected pixels with skimage
from PIL import Image
import numpy as np
import skimage
im = Image.open("DMSO_Resized.png")
imgr = im.convert("L")
im2arr = np.array(imgr)
arr2im = Image.fromarray(im2arr)
thresh = skimage.filters.threshold_otsu(im2arr)
binary = im2arr > thresh
connected = skimage.morphology.label(binary)
I'd now like to count the number of background pixels that are either "completely" covered by other background pixels or "partially" covered.
For example, pixel[1][1] is partially covered
1 0 2
0 0 0
3 0 8
AND
For example, pixel[1][1] is completely covered
0 0 0
0 0 0
0 0 0
Is there a skimage or other package that has a method to do these ? Or would I have to implement them as an array processing loop ?
import numpy as np
from skimage import morphology
bad_connection = np.array([[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 0, 0, 1]], dtype=np.uint8)
expected_good = np.array([[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=np.uint8)
another_bad = np.array([[1, 0, 0, 0, 1],
[1, 1, 0, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 0, 1, 1],
[1, 0, 0, 0, 1]], dtype=np.uint8)
another_good = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=np.uint8)
footprint = np.array([[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1]], dtype=np.uint8)
Outputs (incorrect or not as expected):

How to perform Bilinear Interpolation to a masked image?

Suppose I have an image with mask, valid pixels are masked as 1 and others 0, how to perform bilinear interpolation to fill all the invalid pixels?
for example, image:
1, 0, 0, 4
mask:
1, 0, 0, 1
interpolation result should be:
1, 2, 3, 4
The valid pixels are not regularly arranged, a more complicated sample, image:
4, 0, 6, 0,
0, 8, 5, 0
5, 3, 0, 0
mask:
1, 0, 1, 0,
0, 1, 1, 0
1, 1, 0, 0
interpolate with scipy.interpolate.interp2d and the result has many holes and noise

Expected 2D array, got 1D array instead: after fitting the model

I don't understand where i'm getting wrong. Both of the arrays are of same shape and has same no. of elements. i'm getting - "Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample."
I'll provide my code below -
y_pred:
array([1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1,
0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1,
0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1,
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1,
1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0,
1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1,
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0,
1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1], dtype=int64)
y_pred.shape - (200,)
y_test :array([1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1,
1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1,
0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0,
0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1,
1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0,
1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1], dtype=int64)
y_test.shape - (200,)
Now when i tried to evaluate this (dtc.score(y_test,y_pred_dtr)) , I'm getting this error -
ValueError: Expected 2D array, got 1D array instead:
array=[1. 0. 0. 0. 0. 0. 1. 0. 0. 1. 1. 1. 0. 0. 1. 0. 1. 0. 0. 1. 1. 1. 1. 1.
0. 1. 0. 0. 0. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 1.
1. 0. 1. 1. 1. 0. 1. 0. 1. 0. 0. 0. 1. 1. 1. 0. 1. 1. 0. 1. 0. 1. 1. 0.
0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 1. 1. 1. 0. 1. 0. 0. 0. 1. 0. 0. 1. 1. 0.
0. 0. 0. 1. 0. 0. 1. 0. 0. 1. 1. 0. 0. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 1.
1. 1. 0. 0. 0. 1. 0. 1. 1. 1. 0. 0. 0. 1. 1. 0. 1. 1. 1. 0. 0. 0. 1. 1.
0. 1. 0. 0. 0. 0. 1. 0. 0. 1. 1. 0. 0. 0. 0. 1. 1. 0. 1. 0. 1. 0. 1. 1.
0. 0. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 1. 0. 1. 1. 1. 1. 0. 1. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 1.].
Reshape your data either using array.reshape(-1, 1) if your data has a
single feature or array.reshape(1, -1) if it contains a single sample.
here is the thing,
a=np.array([1,2,3]) is 1D array
now in y_pred and y_test it should be
array=np.array([sample1array,sample2array,....])
so it should be,
a=np.array([[1],[2],[3]])
so try reshape(-1,1) so
np.array([1,2,3]) will be converted 'n' rows '1' column array (2D) = np.array([[1],[2],[3]]).
try this.
EDIT:
because it may be possible that your output length is greater than 1 then? ,like y=[[1,0],[0,0],[1,0]]. this is the only way to do that. thanks.

Calculate accuracy score of kmeans model

This works as expected and returns 1 for one of the groups.
from sklearn import metrics
labels_true = [0, 0, 0, 1, 1, 1]
labels_pred = [6, 6, 6, 1, 2, 2]
metrics.homogeneity_completeness_v_measure(labels_true, labels_pred)
(1.0, 0.6853314789615865, 0.8132898335036762)
But this returns 0.75 for all 3 groups while I expected "1.0" for one of the groups like the example mentioned above.
y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
labels = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2,
2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 0, 0, 2, 2, 2, 2,
2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 0]
metrics.homogeneity_completeness_v_measure(y, labels)
(0.7514854021988339, 0.7649861514489816, 0.7581756800057786)
Expected 1 in one of the groups above!
Update:
As you can see, one of the groups matches with the other and therefore one of the values should have been 1 instead of 0.75 accuracy that I get for all 3 groups. This is not expected!
from collections import Counter
Counter(y)
Counter(labels)
Counter({0: 50, 1: 50, 2: 50})
Counter({1: 50, 0: 62, 2: 38})
Firstly, homogeneity, completeness and v measure score are calculated as follows:
C and K are two random variables. In your case, C is the labels true, while K is the label predicted.
If h = 1, it means that H(C|K) = 0, as H(C) is always less than 0. If H(C|K) = 0, it means that random variable C is completely determined by given random variable K, you can see more detailed definition on conditional entropy. So in your first case, why h = 1? Because when I give a value of random variable K (labels predicted), I know what the random variable C (labels true) will be. If k equals 6, I know c is 0. If k is 1, c is 1, etc. So when talking about the second case, why h != 1 or c != 1. Because even though there is a perfect match between 1 to 0, but there are no perfect match for other classes. If I give k is 1, I know c is 0. But when I give k is 0, I'm not sure whether c is 1 or 2. Thus, the homogeneity score or in reverse, completeness score, you can think about that, will not be 1.

How to calculate the resolution of an undistorted image?

An undistorted image typically have lower resolution than the original image due to non-uniform distribution of pixels and (usually) the cropping of the black edges. (See below as an example)
So given the camera calibration parameters, e.g. in ROS format
image_width: 1600
image_height: 1200
camera_name: camera1
camera_matrix:
rows: 3
cols: 3
data: [1384.355466887268, 0, 849.4355708515795, 0, 1398.17734010913, 604.5570699746268, 0, 0, 1]
distortion_model: plumb_bob
distortion_coefficients:
rows: 1
cols: 5
data: [0.0425049914802741, -0.1347528158561486, -0.0002287009852930437, 0.00641133892300999, 0]
rectification_matrix:
rows: 3
cols: 3
data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
projection_matrix:
rows: 3
cols: 4
data: [1379.868041992188, 0, 860.3000889574832, 0, 0, 1405.926879882812, 604.3997819099422, 0, 0, 0, 1, 0]
How would one calculate the final resolution of the undistorted rectified image?
From Fruchtzwerg's comment, the following will give the effective ROI of the undistorted image
import cv2
import numpy as np
mtx = np.array([
[1384.355466887268, 0, 849.4355708515795],
[ 0, 1398.17734010913, 604.5570699746268],
[0, 0, 1]])
dist = np.array([0.0425049914802741, -0.1347528158561486, -0.0002287009852930437, 0.00641133892300999, 0])
cv2.getOptimalNewCameraMatrix(mtx, dist, (1600, 1200), 1)

Resources