im trying to make a 3d renderer but i can only get at most 20fps on idle.
i tried using #functools.lru_cache(maxsize=None) on project_and_rotate() and got it up to 40fps on idle.
is there any way i could make this any faster
im using a long math formula i found a few month ago but it seems to be to slow for the map in projected_des
from math import *
import pygame
import numpy
from functools import lru_cache
#lru_cache(maxsize=None)
def project_and_rotate(x, y, z,rotx,roty,rotz,posx,posy,posz,cx,cy,cz,scale,render_distance):
x,y,z=x-posx,y-posy,z-posz
if abs(x)>render_distance or abs(z)>render_distance:return None
px = (((x * cos(rotz) - sin(rotz) * y) * cos(roty) - z * sin(roty)) * (315 / ((((z * cos(roty) + (x * cos(rotz) - sin(rotz) * y) * sin(roty)) * cos(rotx) + (y * cos(rotz) + x * sin(rotz)) * sin(rotx)) + 5) + cz))) * scale + cx
py = (((y * cos(rotz) + x * sin(rotz)) * cos(rotx) - (z * cos(roty) + (x * cos(rotz) - sin(rotz) * y) * sin(roty)) * sin(rotx)) * (315 / ((((z * cos(roty) + (x * cos(rotz) - sin(rotz) * y) * sin(roty)) * cos(rotx) + (y * cos(rotz) + x * sin(rotz)) * sin(rotx)) + 5) + cz))) * scale + cy
return [round(px),round(py)]
class coordinate:
def __init__(self,x,y,z):
self.x=x
self.y=y
self.z=z
class verticies_structure:
def __init__(self):
self._verts=[]
def add_vert(self,x,y,z):
self._verts.append(coordinate(x,y,z))
def get_coords(self,indexes):
return self._verts[indexes[0]:indexes[1]]
class camera:
def __init__(self,w,h,render_distance,fov=45):
self.fov=360-fov
self.w=w
self.h=h
self.x=0
self.rx=0
self.cx=0
self.y=0
self.ry=0
self.cy=0
self.z=0
self.rz=0
self.cz=0
self.render_distance=render_distance
def false(f,value):
if value==f:
value=f+0.01
return value
def inf360(value):
if value>359:value=0
if value<0:value=359
return value
class mesh(object):
def __init__(self,file_obj,cam):
self.cam=cam
self.verts=verticies_structure()
self.source=file_obj
self.read_object_file()
self.verts=verticies_structure()
size=100
for x in range(size):
for z in range(size):
self.verts.add_vert(x-size//2,0,z-size//2)
self.w2s_vect=numpy.vectorize(self.w2s)
self.array_verts=numpy.array(self.verts._verts)
def w2s(self,coord):
cam=self.cam
return project_and_rotate(coord.x,coord.y,coord.z,cam.ry,cam.rx,cam.rz,cam.x,cam.y,cam.z,cam.cx,cam.cy,cam.cz,10,cam.render_distance)
def projected_des(self,cam):
#return self.w2s_vect(self.array_verts).tolist()
return map( lambda coord:project_and_rotate(coord.x,coord.y,coord.z,cam.ry,cam.rx,cam.rz,cam.x,cam.y,cam.z,cam.cx,cam.cy,cam.cz,10,cam.render_distance),self.verts.get_coords([0,-1]))
def read_object_file(self):
self.verts=verticies_structure()
import re
reComp = re.compile("(?<=^)(v |vn |vt |f )(.*)(?=$)", re.MULTILINE)
with open(self.source) as f:
data = [txt.group() for txt in reComp.finditer(f.read())]
v_arr, vn_arr, vt_arr, f_arr = [], [], [], []
for line in data:
tokens = line.split(' ')
if tokens[0] == 'v':
v_arr.append([float(c) for c in tokens[1:]])
elif tokens[0] == 'vn':
vn_arr.append([float(c) for c in tokens[1:]])
elif tokens[0] == 'vt':
vn_arr.append([float(c) for c in tokens[1:]])
elif tokens[0] == 'f':
f_arr.append([[int(i) if len(i) else 0 for i in c.split('/')] for c in tokens[1:]])
vertices, normals = [], []
for face in f_arr:
for tp in face:
self.verts.add_vert(*v_arr[tp[0]-1])
self.array_verts=numpy.array(self.verts._verts)
class draw:
class frame:
class pygame_uitl:
def grid(rowx,rowy,px,color=(255,255,255)):
display=pygame.display.get_surface()
for r in range(rowx):
r+=1
pygame.draw.line(display,color,(0,(display.get_height()/(rowx+1))*r),(display.get_width(),(display.get_height()/(rowx+1))*r),px)
for r in range(rowy):
r+=1
pygame.draw.line(display,color,((display.get_width()/(rowy+1))*r,0),((display.get_width()/(rowy+1))*r,display.get_height()),px)
class system:
class pygame_util:
def get_orientation():
inf=pygame.display.Info()
w,h=inf.current_w,inf.current_h
if w>h:
return 1
else:
return 0
class Drivers:
class Pygame:
DEFAULT="PG-default"
SDL2="PG-sdl2"
class master:
class scene:
def __init__(self,wh:list,display_driver:str,render_distance:int,fps:int):
self._model={
"class 1":[],
"class 2":[],
"class 3":[],
"class 4":[]}
self._fps=fps
self._window_wh=wh
self._driver=display_driver
self._camera=camera(*wh,render_distance)
self._mode="mesh"
self._super_ls=0
if display_driver==Drivers.Pygame.DEFAULT:
self._render_pygame_def_setup()
def add_model(self,file):
model=mesh(file,self._camera)
vertexes=len(model.verts._verts)
if vertexes>100:
self._model["class 4"].append(model)
elif vertexes>50:
self._model["class 3"].append(model)
elif vertexes>25:
self._model["class 2"].append(model)
else:
self._model["class 1"].append(model)
def regulate_camera(self):
self._camera.rx,self._camera.ry,self._camera.rz=false(0,self._camera.rx),false(0,self._camera.ry),false(0,self._camera.rz)
self._camera.cx,self._camera.cy,self._camera.cz=false(0,self._camera.cx),false(0,self._camera.cy),false(0,self._camera.cz)
def correct_camera(self,orient=1):
self._orient=orient
if orient:
self._camera.cx=self._window_wh[1]//2
self._camera.cy=self._window_wh[0]
self._camera.ry=0.4
else:
self._camera.cx=self._window_wh[0]//2
self._camera.cy=self._window_wh[1]
self._camera.ry=0.2
def auto_render_distance(self):
if self._driver==Drivers.Pygame.DEFAULT:
if self._pygame_clock.get_fps()+5>self._fps:
self._camera.render_distance+=1
else:
self._camera.render_distance-=1
def landscape_super(self):
self._super_ls=1
self._lss_hdri_file_jpg_surf=pygame.Surface([self._window_wh[0],self._window_wh[1]//2.01])
self._lss_hdri_file_jpg_surf.fill((200,220,255))
def _render_pygame_def_setup(self):
self._pygame_clock=pygame.time.Clock()
self._pygame_screen=pygame.display.set_mode((self._camera.w,self._camera.h),pygame.DOUBLEBUF|pygame.HWACCEL|pygame.HWSURFACE)
def _render_pygame_def_update(self):
self._pygame_screen.fill((0,70,0))
self.regulate_camera()
for idx,vclass in self._model.items():
for model in vclass:
for point in model.projected_des(self._camera):
if point!=None:
try:self._pygame_screen.set_at(point,(255,255,255))
except:pass
if self._super_ls:
self._pygame_screen.blit(self._lss_hdri_file_jpg_surf,(0,0))
def _render_pygame_def_finish(self):
pygame.display.flip()
self._pygame_clock.tick(self._fps)
scene=master.scene([2176,1080],Drivers.Pygame.DEFAULT,render_distance=25,fps=60)
scene.add_model("cube.obj")
scene.correct_camera(0)
scene.landscape_super()
#make the sky mapped to edge of render
pygame.font.init()
while 1:
rx,ry=pygame.mouse.get_rel()
scene._camera.rx+=rx/200
scene._render_pygame_def_update()
#scene.auto_render_distance()
scene._pygame_screen.blit(pygame.font.SysFont(None,60).render(str(scene._pygame_clock.get_fps()),None,(255,0,0)),(0,0))
scene._render_pygame_def_finish()
Related
import re
import math
from random
import randint
import hashlib
P = (-0.15, 2.645)
Q = (0.7, 2.71)
max_mod = 1.158 * 10 ** 77
def SHA256_INT(text):
return int(f'0x{hashlib.sha256(text.encode("ascii")).hexdigest()}', 0)
def ecc_double_slope(P):
slope = (3 * P[0] ** 2) / (2 * P[1])
return slope
def ecc_add(P, Q, slope):
xr = slope ** 2 - P[0] - Q[0]
yr = slope * (P[0] - xr) - P[1]
return (xr, yr)
def ecc_double(P):
slope = ecc_double_slope(P)
sum0 = ecc_add(P, P, slope)
return sum0
def ecc_double_for(P, limit):
lis = []
for i in range(limit):
b = ecc_double(P)
P = b
lis.append((2 ** i, b))
return lis
def greedy2(number):
x = 0
dub_lis = []
add_lis = []
while 2 ** x < number:
dub_lis.append(2 ** x)
x += 1
x -= 1
n = 2 ** x
while n != number:
y = x
while n + (2 ** y) > number:
y -= 1
n += (2 ** y)
x += 1
add_lis.append(2 ** y)
return len(dub_lis), add_lis
def ecc_main_add(P, Q):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
slope = (y2 - y1) / (x2 - y1)
xr = slope ** 2 - x1 - x2
yr = slope * (x1 - xr) - y1
return xr, yr
def gen_points(gen, points):
if gen == 1:
return points
elif gen > 1:
if type(points) == int:
point_curve = (points, math.sqrt(points ** 3 + 7))
elif type(points) == tuple:
point_curve = points
point_steps = greedy2(gen)
point_dub = point_steps[0]
point_add = point_steps[1]
dub_list = ecc_double_for(point_curve, point_dub)
for i in point_add:
b = ecc_main_add(dub_list[int(math.log(i, 2))][1], dub_list[-1][1])
return b, gen
elif gen == 0:
return 0
def sign(messsage, private_key, public_key, G):
global max_mod
msg_hash = SHA256_INT(messsage)
randnum = randint(2, max_mod)
r = gen_points(randnum, G)[0]
r_x = r[0]
msg_hash = SHA256_INT(messsage)
s = (r_x * private_key + msg_hash) / randnum
p1 = gen_points(msg_hash/s, G)
p2 = gen_points(r_x/s, public_key)
p3 = ecc_main_add(p1, p2)
return p3
pub, priv = gen_points(9756, P)
print(sign('hello', priv, pub, P))
Hello, I'm trying to implement a way to sign messages using this tutorial:
https://learnmeabitcoin.com/beginners/digital_signatures_signing_verifying
I've tried to follow the tutorial before, but it's either my key generation is wrong, I didn't follow the tutorial correctly, or both.
My current code generates an error, I've already debugged it and it generates the error: TypeError: 'NoneType' object is not subscriptable.
Does anyone know how to solve this?
I would like to construct an ellipse given the major/minor axes (or radii) and two points. I would like the line between the two points to be on the major axis. This just means that I would like the two points to lie on the major axis, and then construct the ellipse around the major axis. I originally constructed the ellipse at the origin and attempted to rotate and translate the ellipse, which didn't work. The unfinished code I have is listed below. How can I go about constructing an ellipse in this manner? Ideally, this would just return a list. Any insights would be greatly appreciated, and if you have any code for this please feel free to share.
import numpy
import matplotlib.pyplot as plt
import random
import math
from math import sin, cos
# Returns theta in [-pi/2, 3pi/2]
def generate_theta(a, b):
u = random.random() / 4.0
theta = numpy.arctan(b/a * numpy.tan(2*numpy.pi*u))
v = random.random()
if v < 0.25:
return theta
elif v < 0.5:
return numpy.pi - theta
elif v < 0.75:
return numpy.pi + theta
else:
return -theta
def radius(a, b, theta):
return a * b / numpy.sqrt((b*numpy.cos(theta))**2 + (a*numpy.sin(theta))**2)
def random_point(a, b, third_point, center=(0, 0)):
angle = None
if a > b:
random_theta = generate_theta(a, b)
max_radius = radius(a, b, random_theta)
random_radius = max_radius * numpy.sqrt(random.random())
f = round(random_radius * numpy.cos(random_theta))
s = round(random_radius * numpy.sin(random_theta))
angle = math.atan2(third_point[1], third_point[0]) - math.atan2(center[1], center[0])
else:
random_theta = generate_theta(b, a)
max_radius = radius(b, a, random_theta)
random_radius = max_radius * numpy.sqrt(random.random())
f = round(random_radius * numpy.cos(random_theta))
s = round(random_radius * numpy.sin(random_theta))
angle = math.atan2(third_point[1], third_point[0]) - math.atan2(center[1], center[0])
lio = rotate(center, (f, s), angle)
lio = (int(lio[0]), int(lio[1]))
return numpy.array([third, ward])
def rotate(origin, point, angle):
#Rotate a point counterclockwise by a given angle around a given origin.
#The angle should be given in radians.
x = origin[0] + cos(angle) * (point[0] - origin[0]) - sin(angle) * (point[1] - origin[1])
y = origin[1] + sin(angle) * (point[0] - origin[0]) + cos(angle) * (point[1] - origin[1])
return (x, y)
#height
a = 95
#length
b = 25
#rand_p = (-random.randint(300, 400), -random.randint(100, 300))
rand_p = (0, 0)
points = numpy.array([random_point(a, b, (100, 100), (-25, 0)) for _ in range(200)])
#rando = rotate((0, 0), right_most_point, angle)
iopoints = []
# t = x[0] - (int(centroid[0]) - 100)
# t2 = x[1] - (int(centroid[1]) - 100)
centroid = numpy.mean(points, axis=0)
print(centroid)
#plt.plot(rando[0], rando[1], 'ro')
plt.plot(rand_p[0], rand_p[1], 'ro')
plt.scatter(points[:,0], points[:,1])
plt.show()
class ELLIPSE:
def __init__(self, a, b, num_points, start, end):
self.a = a
self.b = b
self.num_points = num_points
self.start = start
self.end = end
self.angle_gen = math.atan2(self.end[1]-self.start[1], self.end[0]-self.start[0])
def generate_theta(self, a, b):
u = random.random() / 4.0
theta = np.arctan(self.b/self.a * np.tan(2*np.pi*u))
v = random.random()
if v < 0.25:
return theta
elif v < 0.5:
return np.pi - theta
elif v < 0.75:
return np.pi + theta
else:
return -theta
def radius(self, a, b, theta):
return self.a * self.b / np.sqrt((b*np.cos(theta))**2 + (a*np.sin(theta))**2)
def random_point(self, major_axis, minor_axis, center, qa):
random_theta = self.generate_theta(self.a, self.b)
max_radius = self.radius(self.a, self.b, random_theta)
random_radius = max_radius * np.sqrt(random.random())
f = round(random_radius * np.cos(random_theta))
s = round(random_radius * np.sin(random_theta))
lio = self.rotate((0, 0), (f, s), self.angle_gen)
return (int(lio[0]+center[0]), int(lio[1]+center[1]))
def rotate(self, origin, point, angle):
"""
Rotate a point counterclockwise by a given angle around a given origin.
The angle should be given in radians.
"""
ox, oy = origin
px, py = point
qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy)
qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy)
return qx, qy
def midpoint(self, p1, p2):
return ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2)
def ret_list(self):
points = [self.random_point(self.a, self.b, self.midpoint(self.start, self.end), self.angle_gen) for _ in range(self.num_points)]
return points
I have a few questions about python
In the code I will add below, I want to draw with qpainter in qlabel and I want it to happen when the button is clicked.But I couldn't assign it to the button anyway. When the form is opened, the code works directly. How to change it and run it only when the button is clicked.Also when I click this button, I will make a calculation and then make this drawing.
enter image description here
from PyQt5 import QtGui
from math import *
from Dere_Kesit_Hesabi_python import Ui_MainWindow
import os
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class dere_example(QMainWindow):
def __init__(self):
super().__init__()
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
self.setFixedSize(self.size())
n=0
h=0
b=0
Q100=0
Q500=0
J=0
m=0
user = os.environ['USERNAME']
self.setWindowTitle("Dere Kesit Hesabı-" + user)
self.ui.btnhesap.clicked.connect(self.hesapkitap)
self.ui.btnhesap.clicked.connect(self.paintEvent)
def paintEvent(self, e):
pixmap = QPixmap(self.ui.lblciz.size())
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
painter.setPen(QPen(Qt.blue, 2, Qt.SolidLine))
x = 100
y = 100
h=3
b=4
painter.drawLine(x, y, x + h, y - h)
painter.drawLine(x + h, y - h, x + b + h, y - h)
painter.drawLine(x + b + h, y - h, x + b + 2 * h, y)
self.ui.lblciz.setPixmap(pixmap)
painter.end()
def hesapkitap(self):
global n
global h
global b
global Q100
global Q500
global J
global m
try:
n = float(self.ui.txtn.text().replace(",", "."))
Q500 = float(self.ui.txtq500.text().replace(",", "."))
Q100 = float(self.ui.txtq100.text().replace(",", "."))
j = float(self.ui.txtj.text().replace(",", "."))
h = float(self.ui.txth.text().replace(",", "."))
b = float(self.ui.txtb.text().replace(",", "."))
byan = sqrt(h * h + h * h)
büst = 2 * h + b
A = round(((büst + b) / 2 * h), 4)
Ç = round((b + 2 * byan), 4)
R = round((A / Ç), 4)
V = round((1 / n * pow(R, (2 / 3)) * pow(j, (1 / 2))), 4)
Q = round((A * V), 2)
self.ui.lblAlan.setText(str(A) + " m2")
self.ui.lblcevre.setText(str(Ç) + " m")
self.ui.lblyaricap.setText(str(R))
self.ui.lblhiz.setText(str(V) + " s")
self.ui.lblmaxdebi.setText(str(Q) + " m3/s")
h500 =round(( Q500 * h / Q),2)
h1000 = round((Q100 * h / Q),2)
if (Q500 <= Q):
self.ui.lblQ500sonuc.setText("Q500 : "+str(Q500)+" < "+"Q : "+str(Q)+" olduğundan kesit gelen Q500 debisi için yeterli!")
self.ui.lblQ500sonuc.setStyleSheet("color:rgb(0,150,0)")
else:
self.ui.lblQ500sonuc.setText("Q500 : "+str(Q500)+" > "+"Q : "+str(Q)+" olduğundan kesit gelen Q500 debisi için yetersiz!")
self.ui.lblQ500sonuc.setStyleSheet("color:rgb(255,0,0)")
if (Q100 <= Q):
self.ui.lblQ100sonuc.setText("Q100 : "+str(Q100)+" < "+"Q : "+str(Q)+" olduğundan kesit gelen Q100 debisi için yeterli!")
self.ui.lblQ100sonuc.setStyleSheet("color:rgb(0,150,0)")
else:
self.ui.lblQ100sonuc.setText("Q100 : "+str(Q100)+" > "+"Q : "+str(Q)+" olduğundan kesit gelen Q100 debisi için yetersiz!")
self.ui.lblQ100sonuc.setStyleSheet("color:rgb(255,0,0)")
except:
self.ui.statusbar.showMessage("Lütfen bilgileri eksiksiz doldurunuz!", 3000)
self.ui.statusbar.setStyleSheet("color:rgb(255,0,0)")
I am working on a program in python OCC where the user can click the screen, which will send the ray out based on window coordinates. I wrote a ray direction function, but even when the mouse moves, the values in the direction vector dont change much at all, the biggest change in value i have seen is in the 14th decimal point of each x, y, and z value. I was curious if I have a problem in my code.
My code is pictured below:
from PyQt5 import QtCore, QtGui, QtOpenGL, QtWidgets
from OpenGL.GL import *
from OpenGL.GLU import *
def generate_ray(mouse_x, mouse_y):
projection_matrix = glGetDoublev(GL_PROJECTION_MATRIX)
model_matrix = glGetDoublev(GL_MODELVIEW_MATRIX)
view_matrix = glGetIntegerv(GL_VIEWPORT)
corrected_y = view_matrix[3] - mouse_y
near_x, near_y, near_z = gluUnProject(mouse_x,corrected_y,0,model_matrix,projection_matrix,view_matrix)
far_x, far_y, far_z = gluUnProject(mouse_x,corrected_y,1,model_matrix,projection_matrix,view_matrix)
direction = [far_x - near_x]
direction.append(far_y - near_y)
direction.append(far_z - near_z)
print("ray direction: x: {} y: {} z: {}".format(direction[0], direction[1], direction[2]))
return direction
If this helps, my ray-triangle intersection test is below. the ray direction, origin, and vertice list are all numpy arrays.
import numpy
def crossProduct(x1, x2):
"""array[0] is the x-coord, array[1] is the y coord, and array[2] is the z coord """
COORDS_PER_VERTEX = 3
cross_product_array = numpy.empty([COORDS_PER_VERTEX])
#print(x1[0])
#print(x2[2])
cross_product_array[0] = x1[1] * x2[2] - x1[2] * x2[1]
cross_product_array[1] = x1[2] * x2[0] - x1[0] * x2[2]
cross_product_array[2] = x1[0] * x2[1] - x1[1] * x2[0]
return cross_product_array
def dotProduct(x1, x2):
"""array[0] is the x-coord, array[1] is the y coord, and array[2] is the z coord """
result = x1[0] * x2[0] + x1[1] * x2[1] + x1[2] * x2[2]
return result
def ray_triangle_intersection_test(ray_origin, ray_direction, vertice_list):
EPSILON = 0.0000001
NEG_EPSILON = -0.0000001
edge1 = vertice_list[1] - vertice_list[0]
#print(edge1)
edge2 = vertice_list[2] - vertice_list[0]
#print(edge2)
pvec = crossProduct(ray_direction,edge2)
print("pvec: %s" %pvec)
det = dotProduct(edge1,pvec)
print("det: %s" %det)
if det > NEG_EPSILON and det < EPSILON:
print("parallel")
return # This ray is parallel to this triangle.
invDet = 1.0/det
print("invDet: %s" %invDet)
svec = ray_origin - vertice_list[0]
u = invDet * (dotProduct(svec,pvec))
print("u: %s" %u)
"""
if u < 0.0 or u > 1.0:
print("false1")
return
"""
qvec = crossProduct(svec, edge1)
v = invDet * dotProduct(ray_direction, qvec)
"""
if v < 0.0 or u + v > 1.0:
print("false2")
return
"""
# At this stage we can compute t to find out where the intersection point is on the line.
t = invDet * dotProduct(edge2, qvec)
print("t: %s" %t)
if t > EPSILON: # ray intersection
outIntersectionPoint = numpy.multiply((ray_origin + ray_direction),t)
return outIntersectionPoint
else: # This means that there is det line intersection but not det ray intersection.
print("false3")
return
I am trying to parallelize a loop that is very costly.
Here is the code:
import numpy as np
class em:
def __init__(self, k, x, iterations):
self.k = k
self.x = x
self.iterations = iterations
self.n = self.x.shape[0]
self.pi = np.array([1 / self.k for _ in range(self.k)])
self.z = np.ndarray(shape=(self.k, self.n))
def fit(self):
for i in range(self.iterations):
print('iteration', i)
self.expectation_step()
self.maximization_step()
def expectation_step(self):
# update z
pass
def maximization_step(self):
# update pi and parameters
pass
class bmm_em(em):
def __init__(self, k, x, iterations=1000, d=784):
super().__init__(k, x, iterations)
self.d = d
self.mu = np.random.rand(self.k, self.d)
for m in range(self.k):
normalization_factor = 0.0
for i in range(self.d):
self.mu[m,i] = np.random.random() * 0.5 + 0.25
normalization_factor += self.mu[m, i]
for i in range(self.d):
self.mu[m,i] /= normalization_factor
def expectation_step(self):
prod = np.zeros(self.k)
for n in range(self.n):
for m in range(self.k):
t = self.pi[m]
t *= np.prod(np.power(self.mu[m], self.x[n]))
t *= np.prod(np.power((1.0 - self.mu[m]), (1.0 - self.x[n])))
prod[m] = t
s = sum(prod)
for n in range(self.n):
for m in range(self.k):
if s > 0.0:
self.z[m,n] = prod[m] / s
else:
self.z[m,n] = prod[m] / float(self.k)
def maximization_step(self):
for m in range(self.k):
n_m = np.sum(self.z[m])
self.pi[m] = n_m / self.n # update pi
self.mu[m] = 0
for i in range(self.n):
self.mu[m] += self.z[m,i] * self.x[i].T
self.mu[m] /= n_m
The very costly part is the first loop in bmm_em.expectation_step.
I looked at the joblib module but couldn't figure out how I can rewrite my code to make it work.
Can anyone give me a hint? :)
As #Sergei noted, the use of numpy is preferred here.
Here is what my code became, it's way way faster
def _log_support(self):
pi = self.pi; mu = self.mu
log_support = np.ndarray(shape=(self.k, self.n))
for k in range(self.k):
log_support[k, :] = np.log(pi[k]) \
+ np.sum(self.x * np.log(mu[k, :].clip(min=1e-20)), 1) \
+ np.sum(self.xc * np.log((1 - mu[k, :]).clip(min=1e-20)), 1)
return log_support
def expectation_step(self, log_support):
log_normalisation = np.logaddexp.reduce(log_support, axis=0)
log_responsibilities = log_support - log_normalisation
self.z = np.exp(log_responsibilities)