Python: Point in polygon, boundary and vertex check (ray casting) - python

So I have written some code to check whether a point [(x,y)] lies within a polygon [(x,y), (x,y), (x,y), (x,y)] but the code fails if the point lies on a boundary or a vertex, I need this to be classed as lying within the polygon. This is the code:
def areasign(poly):
sumarea = 0
for i in range(0, len(poly)-1):
xi = poly[i][0]
yi = poly[i][1]
xj = poly[i+1][0]
yj = poly[i+1][1]
sumarea = sumarea + ((xi*yj)-(yi*xj))
if sumarea == 0: return 0
if sumarea < 0: return -1
if sumarea > 0: return 1
def lineintersection(xy, ij):
xyi = []
xyj = []
ijx = []
ijy = []
xyi.extend(xy)
xyj.extend(xy)
xyi.append(ij[0])
xyj.append(ij[1])
xyi.append(xy[0])
xyj.append(xy[0])
ijx.extend(ij)
ijy.extend(ij)
ijx.append(xy[0])
ijy.append(xy[1])
ijx.append(ij[0])
ijy.append(ij[0])
a = areasign(xyi)
b = areasign(xyj)
c = areasign(ijx)
d = areasign(ijy)
if (a!= b) and (c!=d):
return True
else:
return False
def openpointfile(fname):
p = []
f = open(fname)
for line in f:
line = line.replace('POINT(', '')
line = line.replace(')', '')
vals = line.split(' ')
res = map(float, vals)
ctuple = tuple(res)
p.append(ctuple)
print ctuple
f.close()
return p
points = openpointfile('C:/Users/Dan/Documents/Informatics/Data/Point_On_Line.txt')
def openpolygonfile(fname):
p = []
f = open(fname)
for line in f:
line = line.replace('POLYGON((', '')
line = line.replace('))', '')
s = line.split(',')
poly = []
for coord in s:
vals = coord.split(' ')
res = map(float, vals)
ctuple = tuple(res)
poly.append(ctuple)
p.append(poly)
f.close()
return p
polys = openpolygonfile('C:/Users/Dan/Documents/Informatics/Data/Polygon_On_Line.txt')
def pointinpoly(points, polys):
infinity = tuple([100000000.0, 100000010.0])
sum = 0
testline = (points, infinity)
for i in range(0, len(poly)-1):
start = poly[i]
end = poly[i+1]
line = (start, end)
l = lineintersection(line, testline)
if l == True:
sum = sum + 1
if sum % 2 == 0:
return False
else:
return True
pointcount = 0
for point in points:
pointcount = pointcount + 1
polycount = 0
for poly in polys:
polycount = polycount + 1
l = pointinpoly(point, poly)
res = 'Point ' + str(pointcount) + ' lies within Polygon ' + str(polycount) + ' = ' + str(l)
print l
print (res)
Like i said before this doesnt work if the point lies on a boundary or a vertex, i have this function that i found on here that seems to work but i can't find a way to get it my files into the correct format for the function and to get it to iterate oer a list of polygons.
def point_in_poly(x,y,poly):
# check if point is a vertex
if (x,y) in poly: return "IN"
# check if point is on a boundary
for i in range(len(poly)):
p1 = None
p2 = None
if i==0:
p1 = poly[0]
p2 = poly[1]
else:
p1 = poly[i-1]
p2 = poly[i]
if p1[1] == p2[1] and p1[1] == y and x > min(p1[0], p2[0]) and x < max(p1[0], p2[0]):
return "IN"
n = len(poly)
inside = False
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xints:
inside = not inside
p1x,p1y = p2x,p2y
if inside: return "IN"
else: return "OUT"
Any help on how to build that function into my existing code or any help on a new function that could be used to check if the point lies on the boundary of a polygon or on a vertex

Related

k means algorithm python

Whenever k = 2, the code runs in a loop
if k > 2 it sets all, but one of the centroids location to 0,0
I've reviewed it a couple of times , and it doesn't seem like there are any errors probably some sort of logic flaw. The code starts by having a class and its methods which initiate the centroids, calculate the Euclidean distance, and reassign centroids to the average positions of the points that are in the cluster. It then runs a loop that consists of reassigning and calculating distance until a list of the assignments are equal and then plots it.
class Kmeans:
def __init__(self, K, dataset, centroids, sorting):
self.K = K
self.dataset = dataset
self.centroids = centroids
self.sorting = sorting
#sets starting position of centroids
def initializeCentroids(self):
bigX = 0
bigY = 0
self.centroids = []
for i in self.dataset:
if i[0] > bigX:
bigX = i[0]
if i[1] > bigY:
bigY = i[1]
for q in range(self.K):
self.centroids.append([random.randint(0, bigX), random.randint(0, bigY)])
plt.scatter((self.centroids[0][0], self.centroids[1][0]), (self.centroids[0][1], self.centroids[1][1]))
return self.centroids
#calculates euclidean distance
def calcDistance(self):
self.sorting = []
for w in self.dataset:
print(w)
distances = []
counter = 0
for centr in self.centroids:
distances.append(math.sqrt(abs((centr[0] - w[0] * centr[0] - w[0]) + (centr[1] - w[1] * centr[1] - w[1]))))
counter += 1
if counter > 0:
try:
if distances[0] > distances[1]:
distances.pop(0)
if distances[1] > distances[0]:
distances.pop(1)
counter -= 1
except IndexError:
pass
self.sorting.append([w, counter, distances[0]])
return self.sorting
def reassignCentroids(self):
counter3 = 1
for r in range(len(self.centroids)):
positionsX = []
positionsY = []
for t in self.sorting:
if t[1] == counter3:
positionsX.append(t[0][0])
positionsY.append(t[0][1])
population = len(positionsY)
if population == 0:
population = 1
self.centroids.append([sum(positionsX) / population, sum(positionsY) / population])
counter3 += 1
self.centroids.pop(0)
return
k = 4
dataSetSize = input("Enter the amount of tuples you want generated: ")
data_set = []
for o in range(int(dataSetSize)):
data_set.append((random.randint(0, 1000), random.randint(0, 1000)))
attempt = Kmeans(k, data_set, 0, 0)
attempt.initializeCentroids()
xvals = []
yvals = []
sortCompare = []
# plots
for p in data_set:
xvals.append(p[0])
yvals.append(p[1])
running = True
while running:
if len(sortCompare) > 1:
centroidChoice0 = []
centroidChoice1 = []
for p in sortCompare[0]:
centroidChoice0.append(p[1])
for d in sortCompare[1]:
centroidChoice1.append(d[1])
print(centroidChoice1)
print(attempt.centroids)
if centroidChoice1 == centroidChoice0:
running = False
for m in attempt.centroids:
plt.scatter((attempt.centroids[0][0], attempt.centroids[1][0]), (attempt.centroids[0][1], attempt.centroids[1][1]))
running = False
sortCompare.pop(0)
attempt.calcDistance()
sortCompare.append(attempt.sorting)
attempt.reassignCentroids()

I'm having a problem with determining the intersection of two lines in this python code

I tried a math formula from analytic geometry but I didn't get the desired results.
As you can see in the code, the user draw two lines and a green circle(point of intersection) appear.
I have tried to fix the problem for hours but I failed. Sometimes the point doesn't appear or appear but in the wrong position.
Source of the formula I used in the code
Docs of pygame the library I used
#!/usr/bin/env python
from pygame import *
from time import sleep
init();
win = display.set_mode((500,500));
lines = []
cords = []
preview = False
xi = -100
yi = -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
while True:
win.fill((255,255,255))
for ev in event.get():
if ev.type == QUIT:
quit();
exit();
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = mouse.get_pos()
cords.append(mouse.get_pos())
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(mouse.get_pos())
lines.append((cords))
cords = []
preview = False
######################################## THIS BROKEN PART #################################
if len(lines) == 2:
#line 1
points_line1 = lines[0]
point1_line1 = points_line1[0]
point2_line1 = points_line1[1]
line1_vector = (point2_line1[0]-point1_line1[0],point2_line1[1]-point1_line1[1])
a_line1 = line1_vector[1]
b_line1 = -line1_vector[0]
c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1]))
#line2
points_line2 = lines[1]
point1_line2 = points_line2[0]
point2_line2 = points_line2[1]
line2_vector = (point2_line2[0]-point1_line2[0],point2_line2[1]-point1_line2[1])
a_line2 = line2_vector[1]
b_line2 = -line2_vector[0]
c_line2 = -((a_line2*point1_line2[0]) + (b_line2*point1_line2[1]))
if (a_line2 != 0 and b_line2 != 0):
if (a_line1 / a_line2) != ( b_line1/b_line2):
#intersection between line1 and line2
yi = ((((a_line1*c_line2) / a_line2) + c_line1) / -b_line1)
xi = (((-b_line1*yi)-c_line1) / a_line1)
###########################################################################################
elif preview:
draw.line(win,(0,0,0),a,mouse.get_pos(),4)
drawlines(lines)
draw.circle(win,(0,200,0),(int(xi),int(yi)),10)
display.flip()
It's hard to dig through your code. Especially c_line1 = -((a_line1*point1_line1[0]) + (b_line1*point1_line1[1])) seems to be odd, because it calculates the Dot product of vector and a point.
Therefore I don't know exactly what's wrong with your code, but I know how to intersect lines. See Problem with calculating line intersections and Collision and Intersection - Line and line.
Write functions that can add, subtract, scale vectors and rotate vectors by 90°. Write a function which calculates the Dot product:
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
Calculate the vector from the beginning of the lines to the end of the lines and the normal vectors to the lines. The normal vector is obtained by rotating the line vector by 90°:
#line 1
point1_line1, point2_line1 = lines[0]
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = lines[1]
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
Calculate the intersection of the line segments. Make sure the lines are not parallel and that the intersection point is on the line segments:
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
Minimal example:
from pygame import *
init()
win = display.set_mode((500,500))
lines = []
cords = []
preview = False
xi, yi = -100, -100
def drawlines(flines):
for fcords in flines:
draw.line(win,(0,0,0),fcords[0],fcords[1],4)
def add(a, b):
return a[0]+b[0], a[1]+b[1]
def sub(a, b):
return a[0]-b[0], a[1]-b[1]
def rot90(v):
return -v[1], v[0]
def mul(v, s):
return v[0]*s, v[1]*s
def dot(a, b):
return a[0]*b[0] + a[1]*b[1]
run = True
while run:
for ev in event.get():
if ev.type == QUIT:
run = False
elif ev.type == MOUSEBUTTONDOWN:
if ev.button == 1:
preview = True
a = ev.pos
cords.append(a)
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
cords.append(ev.pos)
lines.append((cords))
cords = []
preview = False
intersections = []
for i, line1 in enumerate(lines):
for line2 in lines[i+1:]:
#line 1
point1_line1, point2_line1 = line1
line1_vector = sub(point2_line1, point1_line1)
line1_norml = rot90(line1_vector)
#line2
point1_line2, point2_line2 = line2
line2_vector = sub(point2_line2, point1_line2)
line2_norml = rot90(line2_vector)
# vector from start point of line 2 to start point of line 1
l2p1_l1p1 = sub(point1_line1, point1_line2)
# intersection
d = dot(line2_vector, line1_norml)
if d != 0: # prallel lines
t = dot(l2p1_l1p1, line1_norml) / d
u = dot(l2p1_l1p1, line2_norml) / d
if 0 <= t <= 1 and 0 <= u <= 1: # intersection on line segments
xi, yi = add(point1_line2, mul(line2_vector, t))
intersections.append((xi, yi))
win.fill((255,255,255))
if len(cords) % 2 == 1:
draw.line(win,(0,0,0), a, mouse.get_pos(), 4)
drawlines(lines)
for p in intersections:
draw.circle(win, (0,200,0), (round(p[0]), round(p[1])), 10)
display.flip()
quit()
exit()

tuple index out of range in dfs

This is my code:
class solution:
lot = [[1,0,0], [1,0,0], [1,9,1]]
def move(lot):
if lot is None:
return -1
if (len(lot) <= 0 or len(lot[0]) <= 0):
return -1
q = []
visited = [len(lot)], [len(lot[0])]
direction= [(0,1), (0,-1), (1,0), (-1,0)]
q.append((0,0))
result = 0
while (len(q) > 0):
size = len(q)
for i in range(size):
node= q.pop(0)
x = node[0]
y = node[1]
visited[x][y]= True
if(lot[x][y] == 9):
return result
for dir in direction:
nx = x+ dir[0]
ny = y + dir[1]
r= len(lot[nx])
if (nx < 0 or nx >= len(lot) or ny < 0 or ny > r or lot[nx][ny] == 0 or visited[nx][ny] == True):
continue
q.append((nx,ny))
result += result
return result
print(move(lot))
It generates the following error:
File "prog.py", line 29, in move
if (nx < 0 or nx >= len(lot) or ny < 0 or ny > r or lot[nx][ny] == 0 or visited[nx][ny] == True):
IndexError: tuple index out of range
Your error is because of your visited variable. You're trying to access visited[nx][ny] which doesn't exist.
Separately, your DFS algorithm is incorrect. See here for how to implement DFS correctly.
Your function should be like this:
def move(lot):
if lot is None:
return -1
if (len(lot) <= 0 or len(lot[0]) <= 0):
return -1
q = []
visited = set()
q.append((0,0))
result = 0
while len(q)>0:
x,y = q.pop(0)
if(lot[x][y]==9):
return result
if (x,y) in visited:
continue
visited.add((x,y))
for d in [(0,1), (0,-1), (1,0), (-1,0)]:
nx = x + d[0]
ny = y + d[1]
if (nx<0 or nx>=len(lot) or ny<0 or ny>len(lot[0]) or lot[nx][ny]==0 or (nx,ny) in visited):
continue
q.append((nx,ny))
result += 1
return result

SVM: problems with SMO algorithm

I'm currently trying to code a non linear SVM for handwritten digits recognition using the MNIST data base.
I chose to use the SMO algorithm (based on Platt's paper and other books), but I have some trouble implementing it.
When I run the code over the training set, the bias goes higher and higher, sometimes until "Inf" value, leading the SVM to "classify" every example in the same class.
Here is my code:
import numpy
import gzip
import struct
import matplotlib
from sklearn import datasets
from copy import copy
class SVM:
def __init__(self, constant, data_set, label_set):
self._N = len(data_set)
if self._N != len(label_set):
raise Exception("Data size and label size don't match.")
self._C = constant
self._epsilon = 0.001
self._tol = 0.001
self._data = [numpy.ndarray.flatten((1/255)*elt) for elt in data_set]
self._dimension = len(self._data[0])
self._label = label_set
self._alphas = numpy.zeros((1, self._N))
self._b = 0
self._errors = numpy.ndarray((2, 0))
def kernel(self, x1, x2):
x1 = x1.reshape(1,self._dimension)
result = numpy.power(numpy.dot(x1, x2), 3)
return result
def evaluate(self, x):
result = 0
i = 0
while i < self._N:
result += self._alphas[0, i]*self._label[i]*self.kernel(x, self._data[i])
i += 1
result += self._b
return result
def update(self, i1, i2, E2):
i1 = int(i1)
i2 = int(i2)
if i1 == i2:
return 0
y1 = self._label[i1]
y2 = self._label[i2]
alpha1 = self._alphas[0, i1]
alpha2 = self._alphas[0, i2]
#If alpha1 is non-bound, its error is in the cache.
#So we check its position to extract its error.
#Else, we compute it.
if alpha1 > 0 and alpha1 < self._C :
position = 0
for i, elt in enumerate(self._errors[0, :]):
if elt == i1:
position = i
E1 = self._errors[1, position]
else:
E1 = self.evaluate(self._data[i1]) - y1
s = y1*y2
H = L = 0
if y1 != y2:
L = max(0, alpha2 - alpha1)
H = min(self._C, self._C + alpha2 - alpha1)
else:
L = max(0, alpha2 + alpha1 - self._C)
H = min(self._C, alpha2 + alpha1)
if H == L:
return 0
K11 = self.kernel(self._data[i1], self._data[i1])
K12 = self.kernel(self._data[i1], self._data[i2])
K22 = self.kernel(self._data[i2], self._data[i2])
eta = K11 + K22 - 2*K12
if eta > 0:
alpha2_new = alpha2 + (y2*(E1 - E2)/eta)
if alpha2_new < L:
alpha2_new = L
elif alpha2_new > H:
alpha2_new = H
else:
f1 = y1*(E1 + self._b) - alpha1*K11 - s*alpha2*K12
f2 = y2*(E2 + self._b) - alpha2*K22 - s*alpha1*K12
L1 = alpha1 + s*(alpha2 - L)
H1 = alpha1 + s*(alpha2 - H)
FuncL = L1*f1 + L*f2 + (1/2)*numpy.square(L1)*K11 + (1/2)*numpy.square(L)*K22 + s*L1*L*K12
FuncH = H1*f1 + H*f2 + (1/2)*numpy.square(H1)*K11 + (1/2)*numpy.square(H)*K22 + s*H1*H*K12
if FuncL < FuncH - self._epsilon:
alpha2_new = L
elif FuncL > FuncH + self._epsilon:
alpha2_new = H
else:
alpha2_new = alpha2
if numpy.abs(alpha2_new - alpha2) < self._epsilon*(alpha2_new+alpha2+ self._epsilon):
return 0
alpha1_new = alpha1 + s*(alpha2 - alpha2_new)
#Update of the threshold.
b1 = E1 + y1*(alpha1_new - alpha1)*K11 + y2*(alpha2_new - alpha2)*K12 + self._b
b2 = E2 + y1*(alpha1_new - alpha1)*K12 + y2*(alpha2_new - alpha2)*K22 + self._b
if L < alpha1_new < H:
b_new = b1
elif L < alpha2_new < H:
b_new = b2
else:
b_new = (b1+b2)/2
#Update the cache error
#If alpha2 was bound and its new value is non-bound, we add its index and its error to the cache.
#If alpha2 was unbound and its new value is bound, we delete it from the cache.
if (alpha2 == 0 or alpha2 == self._C) and (alpha2_new > 0 and alpha2_new < self._C):
vector_alpha2_new = numpy.array([i2, E2])
vector_alpha2_new = vector_alpha2_new.reshape((2, 1))
self._errors = numpy.concatenate((self._errors, vector_alpha2_new), 1)
if (alpha2 > 0 and alpha2 < self._C) and (alpha2_new == 0 or alpha2_new == self._C):
l = 0
position = 0
while l < len(self._errors[0, :]):
if self._errors[0, l] == i2:
position = l
l += 1
self._errors = numpy.delete(self._errors, position, 1)
#We do the exact same thing with alpha1.
if (alpha1 == 0 or alpha1 == self._C) and (alpha1_new > 0 and alpha1_new < self._C):
vector_alpha1_new = numpy.array([i1, E1])
vector_alpha1_new = vector_alpha1_new.reshape((2, 1))
self._errors = numpy.concatenate((self._errors, vector_alpha1_new), 1)
if (alpha1 > 0 and alpha1 < self._C) and (alpha1_new == 0 or alpha1_new == self._C):
l = 0
position = 0
while l < len(self._errors[0, :]):
if self._errors[0, l] == i1:
position = l
l += 1
self._errors = numpy.delete(self._errors, position, 1)
#Then we update the error for each non bound point using the new values for alpha1 and alpha2.
for i,error in enumerate(self._errors[1, :]):
self._errors[1, i] = error + (alpha2_new - alpha2)*y2*self.kernel(self._data[i2], self._data[int(self._errors[0, i])]) + (alpha1_new - alpha1)*y1*self.kernel(self._data[i1], self._data[int(self._errors[0, i])]) - self._b + b_new
#Storing the new values of alpha1 and alpha2:
self._alphas[0, i1] = alpha1_new
self._alphas[0, i2] = alpha2_new
self._b = b_new
print(self._errors)
return 1
def examineExample(self, i2):
i2 = int(i2)
y2 = self._label[i2]
alpha2 = self._alphas[0, i2]
if alpha2 > 0 and alpha2 < self._C:
position = 0
for i, elt in enumerate(self._errors[0, :]):
if elt == i2:
position = i
E2 = self._errors[1, position]
else:
E2 = self.evaluate(self._data[i2]) - y2
r2 = E2*y2
if (r2< -self._tol and alpha2 < self._C) or (r2 > self._tol and alpha2 > 0):
n = numpy.shape(self._errors)[1]
if n > 1:
i1 = 0
if E2 > 0:
min = self._errors[1, 0]
position = 0
for l, elt in enumerate(self._errors[1, :]):
if elt < min:
min = elt
position = l
i1 = self._errors[0, position]
else:
max = self._errors[1, 0]
position = 0
for l, elt in enumerate(self._errors[1, :]):
if elt > max:
max = elt
position = l
i1 = self._errors[0, position]
if self.update(i1, i2, E2):
return 1
#loop over all non bound examples starting at a random point.
list_index = [i for i in range(n)]
numpy.random.shuffle(list_index)
for i in list_index:
i1 = self._errors[0, i]
if self.update(i1, i2, E2):
return 1
#Loop over all the training examples, starting at a random point.
list_bound = [i for i in range(self._N) if not numpy.any(self._errors[0, :] == i)]
numpy.random.shuffle(list_bound)
for i in list_bound:
i1 = i
if self.update(i1, i2, E2):
return 1
return 0
def SMO(self):
numChanged = 0
examineAll = 1
cpt = 1
while(numChanged > 0 or examineAll):
numChanged = 0
if examineAll == 1:
for i in range(self._N):
numChanged += self.examineExample(i)
else:
for i in self._errors[0, :]:
numChanged += self.examineExample(i)
if examineAll == 1:
examineAll = 0
elif numChanged == 0:
examineAll = 1
cpt += 1
def load_training_data(a, b):
train = gzip.open("train-images-idx3-ubyte.gz", "rb")
labels = gzip.open("train-labels-idx1-ubyte.gz", "rb")
train.read(4)
labels.read(4)
number_images = train.read(4)
number_images = struct.unpack(">I", number_images)[0]
rows = train.read(4)
rows = struct.unpack(">I", rows)[0]
cols = train.read(4)
cols = struct.unpack(">I", cols)[0]
number_labels = labels.read(4)
number_labels = struct.unpack(">I", number_labels)[0]
image_list = []
label_list = []
if number_images != number_labels:
raise Exception("The number of labels doesn't match with the number of images")
else:
for l in range(number_labels):
if l % 1000 == 0:
print("l:{}".format(l))
mat = numpy.zeros((rows, cols), dtype = numpy.uint8)
for i in range(rows):
for j in range(cols):
pixel = train.read(1)
pixel = struct.unpack(">B", pixel)[0]
mat[i][j] = pixel
image_list += [mat]
lab = labels.read(1)
lab = struct.unpack(">B", lab)[0]
label_list += [lab]
train.close()
labels.close()
i = 0
index_a = []
index_b = []
while i < number_labels:
if label_list[i] == a:
index_a += [i]
elif label_list[i] == b:
index_b += [i]
i += 1
image_list = [m for i,m in enumerate(image_list) if (i in index_a) | (i in index_b)]
mean = (a+b)/2
label_list = [ numpy.sign(m - mean) for l,m in enumerate(label_list) if l in index_a+index_b]
return ([image_list, label_list])
def load_test_data():
test = gzip.open("t10k-images-idx3-ubyte.gz", "rb")
labels = gzip.open("t10k-labels-idx1-ubyte.gz", "rb")
test.read(4)
labels.read(4)
number_images = test.read(4)
number_images = struct.unpack(">I", number_images)[0]
rows = test.read(4)
rows = struct.unpack(">I", rows)[0]
cols = test.read(4)
cols = struct.unpack(">I", cols)[0]
number_labels = labels.read(4)
number_labels = struct.unpack(">I", number_labels)[0]
image_list = []
label_list = []
if number_images != number_labels:
raise Exception("The number of labels doesn't match with the number of images")
else:
for l in range(number_labels):
if l % 1000 == 0:
print("l:{}".format(l))
mat = numpy.zeros((rows, cols), dtype = numpy.uint8)
for i in range(rows):
for j in range(cols):
pixel = test.read(1)
pixel = struct.unpack(">B", pixel)[0]
mat[i][j] = pixel
image_list += [mat]
lab = labels.read(1)
lab = struct.unpack(">B", lab)[0]
label_list += [lab]
test.close()
labels.close()
return ([image_list, label_list])
data = load_training_data(0, 7)
images_training = data[0]
labels_training = data[1]
svm = SVM(0.1, images_training[0:200], labels_training[0:200])
svm.SMO()
def view(image, label=""):
print("Number : {}".format(label))
pylab.imshow(image, cmap = pylab.cm.gray)
pylab.show()
First, SMO is a fairly complicated algorithm - it is not one easy to debug in this kind of format.
Second, you are starting too high up in your testing. Some advice to help you debug your problems.
1) First, switch to using the linear kernel. Its much easier for you to compute the exact linear solution with another algorithm and compare what you are getting with the exact solution. This way its only the weight vectors and bias term. If you stay in the dual space, you'll have to compare all the coefficients and make sure things stay in the same order.
2) Start with a much simpler 2D problem where you know what the general solution should look like. You can then visualize the solution, and watch as it changes at each step - this can be a visual tool to help you find where something goes wrong.
One important thing is you said this:
b1 = E1 + y1*(alpha1_new - alpha1)*K11 + y2*(alpha2_new - alpha2)*K12 + self._b
b2 = E2 + y1*(alpha1_new - alpha1)*K12 + y2*(alpha2_new - alpha2)*K22 + self._b
Basically you're just adding to b every time with this code. Your b's should look more like this:
b1 = smo.b - E1 - y1 * (a1 - alpha1) * smo.K[i1, i1] - y2 * (a2 - alpha2) * smo.K[i1, i2]
b2 = smo.b - E2 - y1 * (a1 - alpha1) * smo.K[i1, i2] - y2 * (a2 - alpha2) * smo.K[i2, i2]
This version is not perfect, but I recommend checking apex51's version on Github for pointers:
SVM-and-sequential-minimal-optimization
The mathematical basis in the notes are very strong (despite some minor discrepancies with Platt's paper) and the code is not perfect, but a good direction for you. I would also suggest looking at other, completed SMOs and trying to tweak that code to math your needs instead of writing from scratch.

Can't return an element in python at a certain position on a grid

i am a beginner to Python and i'm having some problem with a project.
My grid looks like this :
class World(object):
def __init__(self):
self.grid = []
xsize = 20
ysize = 20
self.maxX = xsize
self.maxY = ysize
for irow in range(self.maxY):
row = []
for icol in range(self.maxX):
row.append(None)
self.grid.append(row)
positions = []
for i in range(self.maxX):
for j in range(self.maxY):
positions.append((i,j))
numteam1 = 0
numteam2 = 0
numrobot = 0
randpos = random.sample(positions, numteam1 + numteam2)
team1 = randpos[0:numrobot-1]
team2 = randpos[numrobot:]
for point in team1:
x = point[0]
y = point[1]
self.grid[y][x] = AttackRobot(1, x, y, self)
self.grid[y][x] = MedicRobot(1, x, y, filename)
for point in team2:
x = point[0]
y = point[1]
self.grid[y][x] = AttackRobot(2,x,y,self)
self.grid[y][x] = MedicRobot(2,x,y,self, filename)
and then i have this method:
def test_position(self, x, y):
if x <0 or x >= 20:
return None
if y <0 or y >= 20:
return None
else:
return ( self.grid[y][x] = Robot)
this fonction is supposed to return element at (x,y) on the grid
Then i use this method in this method :
def print_board(w):
print "-" * 60
for y in range(19,-1,-1):
line = ""
for x in range(0,20):
r = w.test_position(x, y)
if r == None:
line += ".... "
else:
if isinstance(r, AttackRobot):
rtype = "A"
elif isinstance(r, MedicRobot):
rtype = "M"
else:
rtype = "!"
if r.get_team() == 1:
line += "%s%02i%s " % (rtype, r.get_health(), r.get_direction())
else:
line += "%s%02i%s " % (rtype.lower(), r.get_health(), r.get_direction())
print line
print "-" * 60
and i get an error.
Traceback (most recent call last):
File "T05.py", line 10, in <module>
print_board(world)
File "/Users/quentindumoulin/Desktop/test.py", line 19, in print_board
if r.get_team() == 1:
AttributeError: 'bool' object has no attribute 'get_team'
return ( self.grid[y][x] = Robot)
What is it? Maybe you want
return self.grid[y][x]
?

Categories