Using Sklearn with NumPy and Images and get this error 'setting an array element with a sequence' - numpy

I am trying to create a simple image classification tool.
I would like the code below to work with classifying images. It works fine when it is a non image NumPy array.
#https://e2eml.school/images_to_numbers.html
import numpy as np
from sklearn.utils import Bunch
from PIL import Image
monkey = [1]
dog = [2]
example_animals = Bunch(data = np.array([monkey,dog]),target = np.array(['monkey','dog']))
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2) #with KMeans you get to pre specify the number of Clusters
KModel = kmeans.fit(example_animals.data) #fit a model using the training data , in this case original example animal data passed through
import pandas as pd
crosstab = pd.crosstab(example_animals.target,KModel.labels_)
print(crosstab)
I have looked into how to make an image into a NumPy array at https://e2eml.school/images_to_numbers.html
The code below where I have converted images to NumPy array doesn't work.
When run it gets the following error
** 'setting an array element with a sequence'**
#https://e2eml.school/images_to_numbers.html
import numpy as np
from sklearn.utils import Bunch
from PIL import Image
monkey = np.asarray(Image.open("monkey.jpg"))
dog = np.asarray(Image.open("dog.jpeg"))
example_animals = Bunch(data = np.array([monkey,dog]),target = np.array(['monkey','dog']))
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2) #with KMeans you get to pre specify the number of Clusters
KModel = kmeans.fit(example_animals.data) #fit a model using the training data , in this case original example animal data passed through
import pandas as pd
crosstab = pd.crosstab(example_animals.target,KModel.labels_)
print(crosstab)
I would appreciate any insight how I fix the error 'setting an array element with a sequence' so that the images will be compatible with the sklearn processing.

You need to be sure that your images "monkey.jpg" and "dog.jpeg" have the same number of pixels. Otherwise, you will have to resize the images to have the same size. Moreover, the data of your Bunch object need to be of shape (n_samples, n_features) (you can check the documentation https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans.fit)
You need to be aware that you use an unserpervised learning model (Kmeans). So the output of the model is not directly "monkey" or "dog".

I found the solution to error setting an array element with a sequence
Kmeans requires the data arrays for comparison need to be the same size.
This means if importing pictures, the pictures need to be resized, converted into a numpy array (a format that is compatible with Kmeans) and finally made into a 1 dimensional array.
#https://e2eml.school/images_to_numbers.html
#https://machinelearningmastery.com/how-to-load-and-manipulate-images-for-deep-learning-in-python-with-pil-pillow/
import numpy as np
from matplotlib import pyplot as plt
from sklearn.utils import Bunch
from PIL import Image
from sklearn.cluster import KMeans
import pandas as pd
monkey = Image.open("monkey.jpg")
dog = Image.open("dog.jpeg")
#resize pictures
monkey1 = monkey.resize((180,220))
dog1 = dog.resize((180,220))
#make pictures into numpy array
monkey2 = np.asarray(monkey1)
dog2 = np.asarray(dog1)
#https://www.quora.com/How-do-I-convert-image-data-from-2D-array-to-1D-using-python
#make numpy array into 1 dimensional array
monkey3 = monkey2.reshape(-1)
dog3 = dog2.reshape(-1)
example_animals = Bunch(data = np.array([monkey3,dog3]),target = np.array(['monkey','dog']))
kmeans = KMeans(n_clusters=2) #with KMeans you get to pre specify the number of Clusters
KModel = kmeans.fit(example_animals.data) #fit a model using the training data , in this case original example food data passed through
crosstab = pd.crosstab(example_animals.target,KModel.labels_)
print(crosstab)

Related

Problem with manual data for PyTorch's DataLoader

I have a dataset which I have to process in such a way that it works with a convolutional neural network of PyTorch (I'm completely new to PyTorch). The data is stored in a dataframe with a column for pictures (28 x 28 ndarrays with int32 entries) and a column with its class labels. The pixels of the images merely adopt values +1 and -1 (since it is simulation data of a classical 2d Ising Model). The dataframe looks like this.
I imported the following (a lot of this is not relevant for now, but I included everything for completeness. "data_loader" is a custom py file.):
import numpy as np
import matplotlib.pyplot as plt
import data_loader
import pandas as pd
import torch
import torchvision.transforms as T
from torchvision.utils import make_grid
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import Linear
from torch.nn import MaxPool2d
from torch.nn import ReLU
from torch.nn import LogSoftmax
from torch import flatten
from sklearn.metrics import classification_report
import time as time
from torch.utils.data import DataLoader, Dataset
Then, I want to get this in the correct shape in order to make it useful for PyTorch. I do this by defining the following class
class MetropolisDataset(Dataset):
def __init__(self, data_frame, transform=None):
self.data_frame = data_frame
self.transform = transform
def __len__(self):
return len(self.data_frame)
def __getitem__(self,idx):
if torch.is_tensor(idx):
idx = idx.tolist()
label = self.data_frame['label'].iloc[idx]
image = self.data_frame['image'].iloc[idx]
image = np.array(image)
if self.transform:
image = self.transform(image)
return (image, label)
I call instances of this class as:
train_set = MetropolisDataset(data_frame = df_train,
transform = T.Compose([
T.ToPILImage(),
T.ToTensor()]))
validation_set = MetropolisDataset(data_frame = df_validation,
transform = T.Compose([
T.ToPILImage(),
T.ToTensor()]))
test_set = MetropolisDataset(data_frame = df_test,
transform = T.Compose([
T.ToPILImage(),
T.ToTensor()]))
The problem does not yet arise here, because I am able to read out and show images from these instances of the above defined class.
Then, as far as I found out, it is necessary to let this go through the DataLoader of PyTorch, which I do as follows:
batch_size = 64
train_dl = DataLoader(train_set, batch_size, shuffle=True, num_workers=3, pin_memory=True)
validation_dl = DataLoader(validation_set, batch_size, shuffle=True, num_workers=3, pin_memory=True)
test_dl = DataLoader(test_set, batch_size, shuffle=True, num_workers=3, pin_memory=True)
However, if I want to use these instances of the DataLoader, simply nothing happens. I neither get an error, nor the computation seems to get anywhere. I tried to run a CNN but it does not seem to compute anything. Something else I tried was to show some sample images with the code provided by this article, but the same issue occurs. The sample code is:
def show_images(images, nmax=10):
fig, ax = plt.subplots(figsize=(8, 8))
ax.set_xticks([]); ax.set_yticks([])
ax.imshow(make_grid((images.detach()[:nmax]), nrow=8).permute(1, 2, 0))
def show_batch(dl, nmax=64):
for images in dl:
show_images(images, nmax)
break
show_batch(test_dl)
It seems that there is some error in the implementation of my MetropolisDataset class or with the DataLoader itself. How could this problem be solved?
As mentioned in the comments, the problem was partly solved by setting num_workers to zero since I was working in a Jupyter notebook, as answered here. However, this left open one further problem that I got errors when I wanted to apply the DataLoader to run a CNN. The issue was then that my data did consist of int32 numbers instead of float32. I do not include further codes, because this was related directly to my data - however, the issue was (as very often) merely a wrong datatype.

Drawing a community in networkx, anything I am doing incorrectly?

Trying to do something like this but I am not sure what I am doing incorrectly
import networkx as nx
import matplotlib.pyplot as plt
import networkx.algorithms.community as nxcom
G = nx.karate_club_graph()
greedy = nxcom.greedy_modularity_communities(G)
#returns a list with type frozen sets within the list
#[{set1},{set2},{set3}]
pos = nx.spring_layout(G) # compute graph layout
plt.axis('off')
nx.draw_networkx_nodes(G, pos, cmap=plt.cm.RdYlBu, node_color=list(greedy.values()))
plt.show(G)
It looks like your issue comes from the way you are mapping colors to your communities. Since the node_color argument from nx.draw_networkx_nodes is expected to be a list of color (see doc here), you will need to associate each one of your nodes with the color of its community. You can do that by using:
c=plt.cm.RdYlBu(np.linspace(0,1,len(greedy))) #create a list of colors, one for each community
colors={list(g)[j]:c[i] for i,g in enumerate(greedy) for j in range(len(list(g)))} #associate each node with the color of its community
colors_sort=dict(sorted(colors.items())) #sort the dictionary by keys such
You can then convert the values of your sorted dictionnary into a list and pass it to the nx.draw_networkx_nodes with nx.draw_networkx_nodes(G, pos,node_color=list(colors_sort.values())).
See full code below:
import networkx as nx
import matplotlib.pyplot as plt
import networkx.algorithms.community as nxcom
import numpy as np
G = nx.karate_club_graph()
greedy = nxcom.greedy_modularity_communities(G)
c=plt.cm.RdYlBu(np.linspace(0,1,len(greedy)))
colors={list(g)[j]:c[i] for i,g in enumerate(greedy) for j in range(len(list(g)))}
colors_sort=dict(sorted(colors.items()))
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos,node_color=list(colors_sort.values()))
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos,labels={n:str(n) for n in G.nodes()})
plt.axis('off')
plt.show(G)

How to append numpy arrays to txt file

There are a list of image files I want to convert to numpy arrays and append them to a txt file, each array line after line. This is my code:
from PIL import Image
import numpy as np
import os
data = os.listdir("inputs")
print(len(data))
with open('np_arrays.txt', 'a+') as file:
for dt in data:
img = Image.open("inputs\\" + dt)
np_img = np.array(img)
file.write(np_img)
file.write('\n')
but file.write() requires a string and does not accept a numpy ndarray. How can I solve this?
Numpy also allows you to save directly to .txt files with np.savetxt.
I'm still not entirely sure what format you want your text file to be in but a solution might be something like:
from PIL import Image
import numpy as np
import os
data = os.listdir("inputs")
print(len(data))
shape = ( len(data), .., .., ) # input the desired shape
np_imgs = np.empty(shape)
for i, dt in enumerate(data):
img = Image.open("inputs\\" + dt)
np_imgs[i] = np.array(img) # a caveat here is that all images should be of the exact same shape, to fit nicely in a numpy array
np.savetxt('np_arrays.txt', np_imgs)
Note that np.savetxt() has a lot of parameters that allow you to finetune the outputted txt file.
The write() function only allows strings as its input. Try using numpy.array2string.

Reshaping image and Plotting in Python

I am working on mnist_fashion data. The images in mnist_data are 28x28 pixel. For the purpose of feeding it to a neural network(multi-layer perceptron), I transformed the data into (784,) shape.
Further, I need to again reshape it back to the original size.
For this, I used below given code:-
from keras.datasets import fashion_mnist
import numpy as np
import matplotlib.pyplot as plt
(train_imgs,train_lbls), (test_imgs, test_lbls) = fashion_mnist.load_data()
plt.imshow(test_imgs[0].reshape(28,28))
no_of_test_imgs = test_imgs.shape[0]
test_imgs_trans = test_imgs.reshape(test_imgs.shape[1]*test_imgs.shape[2], no_of_test_imgs).T
plt.imshow(test_imgs_trans[0].reshape(28,28))
Unfortunately, I am not getting the similar image. I am not able to understand why this is happening.
expected image:
recieved image:
Kindly help me to resolve the problem.
pay attention when you flatten the images in test_imgs_trans
(train_imgs,train_lbls), (test_imgs, test_lbls) = tf.keras.datasets.fashion_mnist.load_data()
plt.imshow(test_imgs[0].reshape(28,28))
no_of_test_imgs = test_imgs.shape[0]
test_imgs_trans = test_imgs.reshape(no_of_test_imgs, test_imgs.shape[1]*test_imgs.shape[2])
plt.imshow(test_imgs_trans[0].reshape(28,28))

How to convert 2D DICOM slices to 3D image in Python

I am currently sitting on an task in which I need to plot DICOM slices into one 3D model using NumPy, Matplotlib, (Marchingcubes, Triangulation or Volumemodel)
I have tried the method from this website :
https://www.raddq.com/dicom-processing-segmentation-visualization-in-python/
but unfortunately it didn't worked out for me
import pydicom
import numpy as np
import os
import matplotlib.pyplot as plt
import ipywidgets as widgets
from ipywidgets import interact, fixed
filesNew = []
datenSatz = []
output_path = './Head/'
print()
def load_scan(path):
slices = [pydicom.read_file(path + '/' + s) for s in os.listdir(path)]
slices.sort(key = lambda x: int(x.InstanceNumber))
try:
slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])
except:
slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)
for s in slices:
s.SliceThickness = slice_thickness
return slices
for s in load_scan('./Head/'):
h = s.pixel_array
datenSatz.append(s) #dataSet from the patient
filesNew.append(h) #pixel_array
def show_image(image_stack, sliceNumber):
pxl_ar = image_stack[sliceNumber]
#print(np.array_equal(pxl_ar,filesNew[sliceNumber]))
plt.imshow(pxl_ar, cmap= plt.cm.gray)
plt.show()
slider = widgets.IntSlider(min=0,max=len(filesNew)-1,step=1,value = 0, continuous_update=False)
interact(show_image, image_stack = fixed(filesNew), sliceNumber = slider);
DICOM slices visualized
There is an example of loading a set of 2D CT slices and building a 3D array.
https://github.com/pydicom/pydicom/blob/master/examples/image_processing/reslice.py
It does not go on to construct the surface, but it should solve the first half of your problem.