This is my first question here, I apologize if this is the wrong place or my formatting is not correct. My experience with machine learning and data science, in general, is a graduate-level survey course I took as an undergrad about a year ago. I decided to refamiliarize myself by starting to work on little projects. This is my first one, you may get the data here.
I downloaded some 1090 photos from Flickr that I might like as my wallpaper. Then I labeled them (with a score between 0-10, 10 being high), so now I have 1093 wallpapers with their respective scores. The final goal is to make a little program that downloads pictures off the internet and decides how much I will like them and if the score is above a certain threshold, it will set the picture as my wallpaper. For machine learning, I standardized them into 75 by 75 pixels. The pictures are RGB.
The file data.npy is 1093*(75*75*3) numpy matrix(array of arrays), meaning 1093 rows and 16875 columns. Each row is a photo and can be reshaped as (75, 75, 3) into a picture. The label.npy is the parallel array of scores.
This makes every RGB pixel value a feature so we have 16875 features (inspired by the features on MNSIT dataset). I thought of starting with Logistic Regression by sklearn and then Linear. I am using the usual numpy, sklearn. I am getting an accuracy of about 0.5 (50%). I am guessing this is because of having a very small dataset compared to the number of features. I have thought of feature extraction but either I did not do it right or something else but it did not work well.
So by the feedback, I abandoned vanilla logistic/linear regression and tried to lower the number of features by resizing the file, data_50.npy now has the matrix of shape (1093, (50*50*3)) which makes my image of shape (50,50,3). I tried PCA feature extraction, revised neural networks, and built one on my own with an input, a hidden, and an output layer. Finally, I also implemented the Keras Mobilenet CNN. I placed the code for all of these in the same link with the data.
As suggested, I added an output layer for classification into two classes and froze all other layers. I am also using ImageNet weights. I tried to follow the "Fine-tune InceptionV3 on a new set of classes" section at https://keras.io/applications. I am not sure if I set everything up right but here is what I have,
# !/usr/bin/env python3 from keras.applications.mobilenet import MobileNet from keras.layers import Dense from keras.applications.mobilenet import preprocess_input from keras.models import Model from keras.optimizers import SGD import numpy as np data_address = '../data/' cut = 6 split_ratio = 0.7 resolution = 224 # getting data matrix = np.load(data_address + 'data_' + str(resolution) + '.npy') label = np.load(data_address + 'label.npy') # preparing data matrix = preprocess_input(matrix) N = matrix.shape label = label > cut indicies = np.arange(N) np.random.shuffle(indicies) # testing and training split train_x = matrix[indicies][:int(split_ratio * N)] train_x = train_x.reshape((-1, resolution, resolution, 3)) train_y = label[indicies][:int(split_ratio * N)] train_y = np.array([train_y, -(train_y - 1)]).T # one hoting test_x = matrix[indicies][int(split_ratio * N):] test_x = test_x.reshape((-1, resolution, resolution, 3)) test_y = label[indicies][int(split_ratio * N):] test_y = np.array([test_y, -(test_y - 1)]).T # one hoting base_model = MobileNet(weights='imagenet') x = base_model.output # Add logistic layer for 2 output classes predictions = Dense(2, activation='softmax')(x) # this is the model we will train model = Model(inputs=base_model.input, outputs=predictions) # for i, layer in enumerate(model.layers): # print(i, layer.name) for layer in model.layers[:len(model.layers) - 1]: layer.trainable = False model.layers[len(model.layers) - 1].trainable = True # we need to compile the model for these modifications to take effect # we use SGD with a low learning rate model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy']) model.fit(train_x, train_y) score = model.evaluate(test_x, test_y, verbose=0) print('Test loss:', score) print('Test accuracy:', score)
The accuracy stays at base-line.
I'd really appreciate it if someone had a look and I apologize since this has gotten a bit lengthy.