Comments (5)
Nice to see your progressions like this ;)
Good point about the documentation. I think we finally need some proper docs on rtd.
from pyshader.
It seems there is a stdlib
folder with some core functions, which have allowed me to get the spirv to compile. I still seem to have strange behaviour on the model as the outputs don't align with the C++ implementation, and given it's deterministic, the outputs should be the same.
However it does look quite positive, but would be good to get further clarity if the function extensions are in usable state, and whether there are best practices. Also whether there are any ideas why the behaviour is not the same as the shader provided above.
from kp import Tensor, Manager, Sequence, log_level
from pyshader import python2shader, f32, ivec3, Array, vec2
from pyshader.stdlib import exp, log
@python2shader
def compute_shader(
index = ("input", "GlobalInvocationId", ivec3),
x_i = ("buffer", 0, Array(f32)),
x_j = ("buffer", 1, Array(f32)),
y = ("buffer", 2, Array(f32)),
w_in = ("buffer", 3, Array(f32)),
w_out_i = ("buffer", 4, Array(f32)),
w_out_j = ("buffer", 5, Array(f32)),
b_in = ("buffer", 6, Array(f32)),
b_out = ("buffer", 7, Array(f32)),
l_out = ("buffer", 8, Array(f32)),
M = ("buffer", 9, Array(f32))):
i = index.x
m = M[0]
w_curr = vec2(w_in[0], w_in[1])
b_curr = b_in[0]
x_curr = vec2(x_i[i], x_j[i])
y_curr = y[i]
z_dot = (w_curr.x * x_curr.x) + (w_curr.y + x_curr.y)
z = z_dot + b_curr
y_hat = 1.0 / (1.0 + exp(-z))
d_z = y_hat - y_curr
d_w = (1.0 / m) * x_curr * d_z
d_b = (1.0 / m) * d_z
loss = -(y_curr * log(y_hat) + ((1.0 + y_curr) * log(1.0 - y_hat)))
w_out_i[i] = d_w.x
w_out_j[i] = d_w.y
b_out[i] = d_b
l_out[i] = loss
# First we create input and ouput tensors for shader
tensor_x_i = Tensor([0.0, 1.0, 1.0, 1.0, 1.0])
tensor_x_j = Tensor([0.0, 0.0, 0.0, 1.0, 1.0])
tensor_y = Tensor([0.0, 0.0, 0.0, 1.0, 1.0])
tensor_w_in = Tensor([0.001, 0.001])
tensor_w_out_i = Tensor([0.0, 0.0, 0.0, 0.0, 0.0])
tensor_w_out_j = Tensor([0.0, 0.0, 0.0, 0.0, 0.0])
tensor_b_in = Tensor([0.0])
tensor_b_out = Tensor([0.0, 0.0, 0.0, 0.0, 0.0])
tensor_l_out = Tensor([0.0, 0.0, 0.0, 0.0, 0.0])
tensor_m = Tensor([ 5.0 ])
# We store them in an array for easier interaction
params = [tensor_x_i, tensor_x_j, tensor_y, tensor_w_in, tensor_w_out_i,
tensor_w_out_j, tensor_b_in, tensor_b_out, tensor_l_out, tensor_m]
mgr = Manager()
# Initalise GPU buffer and memory
mgr.eval_tensor_create_def(params)
ITERATIONS = 100
learning_rate = 0.1
# Perform machine learning training and inference across all input X and Y
for i_iter in range(ITERATIONS):
mgr.eval_tensor_sync_device_def([tensor_w_in, tensor_b_in])
mgr.eval_algo_data_def(params, compute_shader.to_spirv())
mgr.eval_tensor_sync_local_def([tensor_w_out_i, tensor_w_out_j, tensor_b_out, tensor_l_out])
# Calculate the parameters based on the respective derivatives calculated
w_in_i_val = tensor_w_in.data()[0]
w_in_j_val = tensor_w_in.data()[1]
b_in_val = tensor_b_in.data()[0]
for j_iter in range(tensor_b_out.size()):
w_in_i_val -= learning_rate * tensor_w_out_i.data()[j_iter]
w_in_j_val -= learning_rate * tensor_w_out_j.data()[j_iter]
b_in_val -= learning_rate * tensor_b_out.data()[j_iter]
# Update the parameters to process inference again
tensor_w_in.set_data([w_in_i_val, w_in_j_val])
tensor_b_in.set_data([b_in_val])
# Print learned parameters of logistic regression algorithm
print(tensor_w_in.data())
print(tensor_b_in.data())
print(tensor_l_out.data())
In this implementation all functions were removed, and were added in-line. The specialisation / constant was changed into a simple input parameter.
from pyshader.
For completeness, I can confirm that if I run the same glsl shader outlined above with the Python script, I get the same results as with the C++.
To run the script above the only changes required on the GLSL script is to add the extra binding to account for the variable M that otherwise is provided as specialization constant - ie:
//...
layout(set = 0, binding = 9) buffer bMb { float Mb[]; };
float m = Mb[0];
//...
The spirv contents of this shader result in the same output as per the C++, so it seems there is either something wrong with the way I implemented the shader, or perhaps the instructions for exp
, log
or other components may not be correct.
from pyshader.
Ok I have found the issue, it seems that there is a function provided to calculate the dot product, which is mainly using the @
operator. The manual implementation of the dot product in z_dot = (w_curr.x * x_curr.x) + (w_curr.y + x_curr.y)
was incorrect, and re-implementing it as z_dot = w_curr @ x_curr
fixed the issue.
Now both the C++ and Python implementation with PyShader have the same output for the Machine Learning Logistic Regression implementation.
from pyshader.
Changed the focus of this issue towards documenting the math / standard lib functions, as it seems from this that it worked as required.
from pyshader.
Related Issues (20)
- Syntax for defining input and output HOT 10
- First release to PyPi HOT 1
- pypi package is broken because readme is not included in the package. HOT 4
- Implicit type conversions HOT 4
- Trace debug info so we can produce more useful error messages. HOT 1
- Be more consistent about exception types raised by the parsers
- Add support for runtime constants (specialization)? HOT 1
- WebGPU shading language (WGSL) HOT 5
- Option to spell co_select in Python?
- Is our use of annotations ok? HOT 6
- Support shaders with jumps in bytecode >255 bytes
- Compute example crashes in create_compute_pipeline HOT 19
- Support some form of templating of entry points? HOT 2
- Compiling to file HOT 2
- Error processing resulting SPIR-V shader in Vulkan 1.2.x (Kompute v0.4.2) HOT 2
- [FEATURE] Add support for layout local size(s) HOT 4
- Support for Python 3.9
- Is this worth it? HOT 9
- Archive this repo
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pyshader.