Link to home
Start Free TrialLog in
Avatar of onyourmark
onyourmark

asked on

python error

I am running the code attached. I don't understand why if I run a small number of interations as determined by line 116

color_som.train(25, colors)

I don't get any error but if I run more I get the following error.
For example if I run
color_som.train(35, colors)

Error saving the image, do you have PIL (Python Imaging Library) installed?

Can anyone advise me how to correct this? I am also attaching the test file.
from __future__ import division

## Kyle Dickerson
## kyle.dickerson@gmail.com
## Jan 15, 2008
##
## Self-organizing map using scipy
## This code is licensed and released under the GNU GPL

## This code uses a square grid rather than hexagonal grid, as scipy
#allows for fast square grid computation.
## I designed sompy for speed, so attempting to read the code may not
#be very intuitive.
## If you're trying to learn how SOMs work, I would suggest starting
#with Paras Chopras SOMPython code:
##  http://www.paraschopra.com/sourcecode/SOM/index.php
## It has a more intuitive structure for those unfamiliar with scipy,
#however it is much slower.

## If you do use this code for something, please let me know, I'd like
#to know if has been useful to anyone.

from random import *
from math import *
import sys
import scipy
import numpy as np

class SOM:

   def __init__(self, height=10, width=10, FV_size=10, learning_rate=0.005):
       self.height = height
       self.width = width
       self.FV_size = FV_size
       self.radius = (height+width)/3
       self.learning_rate = learning_rate
       self.nodes = scipy.array([[ [random()*255 for i in
range(FV_size)] for x in range(width)] for y in range(height)])

   # train_vector: [ FV0, FV1, FV2, ...] -> [ [...], [...], [...], ...]
   # train vector may be a list, will be converted to a list of scipy arrays
   def train(self, iterations=1000, train_vector=[[]]):
       for t in range(len(train_vector)):
           train_vector[t] = scipy.array(train_vector[t])
       time_constant = iterations/log(self.radius)
       delta_nodes = scipy.array([[[0 for i in range(self.FV_size)]
for x in range(self.width)] for y in range(self.height)])

       for i in range(1, iterations+1):
           delta_nodes.fill(0)
           radius_decaying=self.radius*exp(-1.0*i/time_constant)
           rad_div_val = 2 * radius_decaying * i
           learning_rate_decaying=self.learning_rate*exp(-1.0*i/time_constant)
           sys.stdout.write("\rTraining Iteration: " + str(i) + "/" +
str(iterations))

           for j in range(len(train_vector)):
               best = self.best_match(train_vector[j])
               for loc in self.find_neighborhood(best, radius_decaying):
                   influence = exp( (-1.0 * (loc[2]**2)) / rad_div_val)
                   inf_lrd = influence*learning_rate_decaying

                   delta_nodes[loc[0],loc[1]] +=inf_lrd*(train_vector[j]-self.nodes[loc[0],loc[1]])
           self.nodes += delta_nodes
       sys.stdout.write("\n")

   # Returns a list of points which live within 'dist' of 'pt'
   # Uses the Chessboard distance
   # pt is (row, column)
   def find_neighborhood(self, pt, dist):
       min_y = max(int(pt[0] - dist), 0)
       max_y = min(int(pt[0] + dist), self.height)
       min_x = max(int(pt[1] - dist), 0)
       max_x = min(int(pt[1] + dist), self.width)
       neighbors = []
       for y in range(min_y, max_y):
           for x in range(min_x, max_x):
               dist = abs(y-pt[0]) + abs(x-pt[1])
               neighbors.append((y,x,dist))
       return neighbors

   # Returns location of best match, uses Euclidean distance
   # target_FV is a scipy array
   def best_match(self, target_FV):
       loc = scipy.argmin((((self.nodes - target_FV)**2).sum(axis=2))**0.5)
       r = 0
       while loc > self.width:
           loc -= self.width
           r += 1
       c = loc
       return (r, c)

   # returns the Euclidean distance between two Feature Vectors
   # FV_1, FV_2 are scipy arrays
   def FV_distance(self, FV_1, FV_2):
       return (sum((FV_1 - FV_2)**2))**0.5

if __name__ == "__main__":
   print "Initialization..."
   #colors = [ [0, 0, 0], [0, 0, 255], [0, 255, 0], [0, 255, 255],
#[255, 0, 0], [255, 0, 255], [255, 255, 0], [255, 255, 255]]
##   colors = [ [0,1, 0, 5,0,7,2,0], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8] ]

   colors = np.genfromtxt("sample.csv", delimiter=",",  skip_header=1)

   width = 32
   height = 32
   color_som = SOM(width,height,26,0.05)
   print "Training colors..."
   color_som.train(35, colors)
   try:
       from PIL import Image
       print "Saving Image: sompy_test_colors.png..."
       img = Image.new("RGB", (width, height))
       for r in range(height):
           for c in range(width):
               img.putpixel((c,r), (int(color_som.nodes[r,c,0]),
int(color_som.nodes[r,c,1]), int(color_som.nodes[r,c,2])))
       img = img.resize((width*10, height*10),Image.NEAREST)
       img.save("sompy_test_colors.png")
   except:
       print "Error saving the image, do you have PIL (Python Imaging Library) installed?"

Open in new window

sample.csv
Avatar of Francisco Igor
Francisco Igor
Flag of Canada image

It seems that your python engine are not compiled with PIL
or the PIL package it's not installed...

See the PIL documentation.
http://www.pythonware.com/products/pil/index.htm


Avatar of onyourmark
onyourmark

ASKER

Hi. Thanks. I am using Eclipse. I don't really know how to fix that.
But it seems to work for the following code

width = 50
   height = 50
   color_som = SOM(width,height,26,0.05)
   print "Training colors..."
   color_som.train(35, colors)



In other words, I change the width and height to 50. But does not work if I up the 35 to something like 75.

??
The problem lies with the conversion from type numpy.float64 to type int. When the iterations with your sample are > 35 the results are too big for a successful conversion. I am taking the mod to 256 out of every color part so that the arguments are within range.

Change the mod which now is 256 to suit the color depth you want.

See the attached code.

Cheers,

John.
from __future__ import division

## Kyle Dickerson
## kyle.dickerson@gmail.com
## Jan 15, 2008
##
## Self-organizing map using scipy
## This code is licensed and released under the GNU GPL

## This code uses a square grid rather than hexagonal grid, as scipy
#allows for fast square grid computation.
## I designed sompy for speed, so attempting to read the code may not
#be very intuitive.
## If you're trying to learn how SOMs work, I would suggest starting
#with Paras Chopras SOMPython code:
##  http://www.paraschopra.com/sourcecode/SOM/index.php
## It has a more intuitive structure for those unfamiliar with scipy,
#however it is much slower.

## If you do use this code for something, please let me know, I'd like
#to know if has been useful to anyone.

from random import *
from math import *
import sys
import scipy
import numpy as np

class SOM:

   def __init__(self, height=10, width=10, FV_size=10, learning_rate=0.005):
       self.height = height
       self.width = width
       self.FV_size = FV_size
       self.radius = (height+width)/3
       self.learning_rate = learning_rate
       self.nodes = scipy.array([[ [random()*255 for i in
range(FV_size)] for x in range(width)] for y in range(height)])

   # train_vector: [ FV0, FV1, FV2, ...] -> [ [...], [...], [...], ...]
   # train vector may be a list, will be converted to a list of scipy arrays
   def train(self, iterations=1000, train_vector=[[]]):
       for t in range(len(train_vector)):
           train_vector[t] = scipy.array(train_vector[t])
       time_constant = iterations/log(self.radius)
       delta_nodes = scipy.array([[[0 for i in range(self.FV_size)]
for x in range(self.width)] for y in range(self.height)])

       for i in range(1, iterations+1):
           delta_nodes.fill(0)
           radius_decaying=self.radius*exp(-1.0*i/time_constant)
           rad_div_val = 2 * radius_decaying * i
           learning_rate_decaying=self.learning_rate*exp(-1.0*i/time_constant)
           sys.stdout.write("\rTraining Iteration: " + str(i) + "/" +
str(iterations))

           for j in range(len(train_vector)):
               best = self.best_match(train_vector[j])
               for loc in self.find_neighborhood(best, radius_decaying):
                   influence = exp( (-1.0 * (loc[2]**2)) / rad_div_val)
                   inf_lrd = influence*learning_rate_decaying

                   delta_nodes[loc[0],loc[1]] +=inf_lrd*(train_vector[j]-self.nodes[loc[0],loc[1]])
           self.nodes += delta_nodes
       sys.stdout.write("\n")

   # Returns a list of points which live within 'dist' of 'pt'
   # Uses the Chessboard distance
   # pt is (row, column)
   def find_neighborhood(self, pt, dist):
       min_y = max(int(pt[0] - dist), 0)
       max_y = min(int(pt[0] + dist), self.height)
       min_x = max(int(pt[1] - dist), 0)
       max_x = min(int(pt[1] + dist), self.width)
       neighbors = []
       for y in range(min_y, max_y):
           for x in range(min_x, max_x):
               dist = abs(y-pt[0]) + abs(x-pt[1])
               neighbors.append((y,x,dist))
       return neighbors

   # Returns location of best match, uses Euclidean distance
   # target_FV is a scipy array
   def best_match(self, target_FV):
       loc = scipy.argmin((((self.nodes - target_FV)**2).sum(axis=2))**0.5)
       r = 0
       while loc > self.width:
           loc -= self.width
           r += 1
       c = loc
       return (r, c)

   # returns the Euclidean distance between two Feature Vectors
   # FV_1, FV_2 are scipy arrays
   def FV_distance(self, FV_1, FV_2):
       return (sum((FV_1 - FV_2)**2))**0.5

if __name__ == "__main__":
   print "Initialization..."
   #colors = [ [0, 0, 0], [0, 0, 255], [0, 255, 0], [0, 255, 255],
#[255, 0, 0], [255, 0, 255], [255, 255, 0], [255, 255, 255]]
##   colors = [ [0,1, 0, 5,0,7,2,0], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0, 5,255,7,2,8], [0,1, 0,
##5,255,7,2,8], [0,1, 0, 5,255,7,2,8] ]

   colors = np.genfromtxt("sample.csv", delimiter=",",  skip_header=1)

   width = 32
   height = 32
   color_som = SOM(width,height,26,0.05)
   print "Training colors..."
   color_som.train(35, colors)#
try:
   from PIL import Image
   print "Saving Image: sompy_test_colors.png..."
   img = Image.new("RGB", (width, height))
   for r in range(height):
       for c in range(width):
           #print type(color_som.nodes[r,c,0])
           img.putpixel((c,r), (int(color_som.nodes[r,c,0] % 256),
int(color_som.nodes[r,c,1] % 256), int(color_som.nodes[r,c,2] % 256)))
   img = img.resize((width*10, height*10),Image.NEAREST)
   img.save("sompy_test_colors.png")
except:
   print "Error saving the image, do you have PIL (Python Imaging Library) installed?"

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of ilalopoulos
ilalopoulos
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi. Thanks. It does not give that error. I ran it with 500 iterations. Can I ask you, do you think that might have any effect on the image being generated?
I am attaching two images. One is called sompy_test_color and this is with 500 iterations on the sample data set. The second is SOM_Test2 and it is on a small data set and 1000 iterations. The first one did not "conjeal" into a clear "map" compared with the second. This may be because I need to do a lot more iterations for a large data set. I am not sure.
sompy-test-colors.png
SOM-Test2.png
I forgot to say that the small data set picture is from the previous code not the new one. I am now trying 1000 iterations on the larger data set. It may take about half an hour.
Hello again. I tried 1000 iterations and it is not congealing. Any idea about that?