202 lines
8.1 KiB
Python
202 lines
8.1 KiB
Python
|
# GammaRegressor.py
|
||
|
# The code demonstrates the process of training GammaRegressor model, exporting it to ONNX format (both float and double), and making predictions using the ONNX models.
|
||
|
# Copyright 2023, MetaQuotes Ltd.
|
||
|
# https://www.mql5.com
|
||
|
|
||
|
# function to compare matching decimal places
|
||
|
def compare_decimal_places(value1, value2):
|
||
|
# convert both values to strings
|
||
|
str_value1 = str(value1)
|
||
|
str_value2 = str(value2)
|
||
|
|
||
|
# find the positions of the decimal points in the strings
|
||
|
dot_position1 = str_value1.find(".")
|
||
|
dot_position2 = str_value2.find(".")
|
||
|
|
||
|
# if one of the values doesn't have a decimal point, return 0
|
||
|
if dot_position1 == -1 or dot_position2 == -1:
|
||
|
return 0
|
||
|
|
||
|
# calculate the number of decimal places
|
||
|
decimal_places1 = len(str_value1) - dot_position1 - 1
|
||
|
decimal_places2 = len(str_value2) - dot_position2 - 1
|
||
|
|
||
|
# find the minimum of the two decimal places counts
|
||
|
min_decimal_places = min(decimal_places1, decimal_places2)
|
||
|
|
||
|
# initialize a count for matching decimal places
|
||
|
matching_count = 0
|
||
|
|
||
|
# compare characters after the decimal point
|
||
|
for i in range(1, min_decimal_places + 1):
|
||
|
if str_value1[dot_position1 + i] == str_value2[dot_position2 + i]:
|
||
|
matching_count += 1
|
||
|
else:
|
||
|
break
|
||
|
|
||
|
return matching_count
|
||
|
|
||
|
# import necessary libraries
|
||
|
import numpy as np
|
||
|
import matplotlib.pyplot as plt
|
||
|
from sklearn.linear_model import GammaRegressor
|
||
|
from sklearn.metrics import r2_score,mean_absolute_error,mean_squared_error
|
||
|
import onnx
|
||
|
import onnxruntime as ort
|
||
|
from skl2onnx import convert_sklearn
|
||
|
from skl2onnx.common.data_types import FloatTensorType
|
||
|
from skl2onnx.common.data_types import DoubleTensorType
|
||
|
from sys import argv
|
||
|
|
||
|
# define the path for saving the model
|
||
|
data_path = argv[0]
|
||
|
last_index = data_path.rfind("\\") + 1
|
||
|
data_path = data_path[0:last_index]
|
||
|
|
||
|
# generate synthetic data for regression
|
||
|
X = np.arange(0,100,1).reshape(-1,1)
|
||
|
y = 10+4*X + 10*np.sin(X*0.5)
|
||
|
|
||
|
model_name="GammaRegressor"
|
||
|
onnx_model_filename = data_path + "..\\models\\gamma_regressor"
|
||
|
|
||
|
# create a Gamma Regressor model
|
||
|
regression_model = GammaRegressor()
|
||
|
|
||
|
# fit the model to the data
|
||
|
regression_model.fit(X, y.ravel())
|
||
|
|
||
|
# predict values for the entire dataset
|
||
|
y_pred = regression_model.predict(X)
|
||
|
|
||
|
# evaluate the model's performance
|
||
|
r2 = r2_score(y, y_pred)
|
||
|
mse = mean_squared_error(y, y_pred)
|
||
|
mae = mean_absolute_error(y, y_pred)
|
||
|
|
||
|
print("\n"+model_name+" Original model (double)")
|
||
|
print("R-squared (Coefficient of determination):", r2)
|
||
|
print("Mean Absolute Error:", mae)
|
||
|
print("Mean Squared Error:", mse)
|
||
|
|
||
|
# convert to ONNX-model (float)
|
||
|
# define the input data type as FloatTensorType
|
||
|
initial_type_float = [('float_input', FloatTensorType([None, X.shape[1]]))]
|
||
|
|
||
|
# export the model to ONNX format
|
||
|
onnx_model_float = convert_sklearn(regression_model, initial_types=initial_type_float, target_opset=12)
|
||
|
|
||
|
# save the model to a file
|
||
|
onnx_filename=onnx_model_filename+"_float.onnx"
|
||
|
onnx.save_model(onnx_model_float, onnx_filename)
|
||
|
|
||
|
print("\n"+model_name+" ONNX model (float)")
|
||
|
# print model path
|
||
|
print(f"ONNX model saved to {onnx_filename}")
|
||
|
|
||
|
# load the ONNX model and make predictions
|
||
|
onnx_session = ort.InferenceSession(onnx_filename)
|
||
|
input_name = onnx_session.get_inputs()[0].name
|
||
|
output_name = onnx_session.get_outputs()[0].name
|
||
|
|
||
|
# display information about input tensors in ONNX
|
||
|
print("Information about input tensors in ONNX:")
|
||
|
for i, input_tensor in enumerate(onnx_session.get_inputs()):
|
||
|
print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}")
|
||
|
|
||
|
# display information about output tensors in ONNX
|
||
|
print("Information about output tensors in ONNX:")
|
||
|
for i, output_tensor in enumerate(onnx_session.get_outputs()):
|
||
|
print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}")
|
||
|
|
||
|
# define the input data type as FloatTensorType
|
||
|
initial_type_float = X.astype(np.float32)
|
||
|
|
||
|
# predict values for the entire dataset using ONNX
|
||
|
y_pred_onnx_float = onnx_session.run([output_name], {input_name: initial_type_float})[0]
|
||
|
|
||
|
# calculate and display the errors for the original and ONNX models
|
||
|
r2_onnx_float = r2_score(y, y_pred_onnx_float)
|
||
|
mse_onnx_float = mean_squared_error(y, y_pred_onnx_float)
|
||
|
mae_onnx_float = mean_absolute_error(y, y_pred_onnx_float)
|
||
|
print("R-squared (Coefficient of determination)", r2_onnx_float)
|
||
|
print("Mean Absolute Error:", mae_onnx_float)
|
||
|
print("Mean Squared Error:", mse_onnx_float)
|
||
|
print("R^2 matching decimal places: ",compare_decimal_places(r2, r2_onnx_float))
|
||
|
print("MAE matching decimal places: ",compare_decimal_places(mae, mae_onnx_float))
|
||
|
print("MSE matching decimal places: ",compare_decimal_places(mse, mse_onnx_float))
|
||
|
print("float ONNX model precision: ",compare_decimal_places(mae, mae_onnx_float))
|
||
|
|
||
|
# set the figure size
|
||
|
plt.figure(figsize=(8, 5))
|
||
|
# plot the original data and the regression line
|
||
|
plt.scatter(X, y, label='Original Data', marker='o')
|
||
|
plt.scatter(X, y_pred, color='blue', label='Scikit-Learn '+model_name+' Output', marker='o')
|
||
|
plt.scatter(X, y_pred_onnx_float, color='red', label='ONNX '+model_name+' Output', marker='o', linestyle='--')
|
||
|
plt.xlabel('X')
|
||
|
plt.ylabel('y')
|
||
|
plt.legend()
|
||
|
plt.title(model_name+' Comparison (with float ONNX)')
|
||
|
#plt.show()
|
||
|
plt.savefig(data_path + model_name+'_plot_float.png')
|
||
|
|
||
|
# convert to ONNX-model (double)
|
||
|
# define the input data type as DoubleTensorType
|
||
|
initial_type_double = [('double_input', DoubleTensorType([None, X.shape[1]]))]
|
||
|
|
||
|
# export the model to ONNX format
|
||
|
onnx_model_double = convert_sklearn(regression_model, initial_types=initial_type_double, target_opset=12)
|
||
|
|
||
|
# save the model to a file
|
||
|
onnx_filename=onnx_model_filename+"_double.onnx"
|
||
|
onnx.save_model(onnx_model_double, onnx_filename)
|
||
|
|
||
|
print("\n"+model_name+" ONNX model (double)")
|
||
|
# print model path
|
||
|
print(f"ONNX model saved to {onnx_filename}")
|
||
|
|
||
|
# load the ONNX model and make predictions
|
||
|
onnx_session = ort.InferenceSession(onnx_filename)
|
||
|
input_name = onnx_session.get_inputs()[0].name
|
||
|
output_name = onnx_session.get_outputs()[0].name
|
||
|
|
||
|
# display information about input tensors in ONNX
|
||
|
print("Information about input tensors in ONNX:")
|
||
|
for i, input_tensor in enumerate(onnx_session.get_inputs()):
|
||
|
print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}")
|
||
|
|
||
|
# display information about output tensors in ONNX
|
||
|
print("Information about output tensors in ONNX:")
|
||
|
for i, output_tensor in enumerate(onnx_session.get_outputs()):
|
||
|
print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}")
|
||
|
|
||
|
# define the input data type as DoubleTensorType
|
||
|
initial_type_double = X.astype(np.float64)
|
||
|
|
||
|
# predict values for the entire dataset using ONNX
|
||
|
y_pred_onnx_double = onnx_session.run([output_name], {input_name: initial_type_double})[0]
|
||
|
|
||
|
# calculate and display the errors for the original and ONNX models
|
||
|
r2_onnx_double = r2_score(y, y_pred_onnx_double)
|
||
|
mse_onnx_double = mean_squared_error(y, y_pred_onnx_double)
|
||
|
mae_onnx_double = mean_absolute_error(y, y_pred_onnx_double)
|
||
|
print("R-squared (Coefficient of determination)", r2_onnx_double)
|
||
|
print("Mean Absolute Error:", mae_onnx_double)
|
||
|
print("Mean Squared Error:", mse_onnx_double)
|
||
|
print("R^2 matching decimal places: ",compare_decimal_places(r2, r2_onnx_double))
|
||
|
print("MAE matching decimal places: ",compare_decimal_places(mae, mae_onnx_double))
|
||
|
print("MSE matching decimal places: ",compare_decimal_places(mse, mse_onnx_double))
|
||
|
print("double ONNX model precision: ",compare_decimal_places(mae, mae_onnx_double))
|
||
|
|
||
|
# set the figure size
|
||
|
plt.figure(figsize=(8, 5))
|
||
|
# plot the original data and the regression line
|
||
|
plt.scatter(X, y, label='Original Data', marker='o')
|
||
|
plt.scatter(X, y_pred, color='blue', label='Scikit-Learn '+model_name+' Output', marker='o')
|
||
|
plt.scatter(X, y_pred_onnx_float, color='red', label='ONNX '+model_name+' Output', marker='o', linestyle='--')
|
||
|
plt.xlabel('X')
|
||
|
plt.ylabel('y')
|
||
|
plt.legend()
|
||
|
plt.title(model_name+' Comparison (with double ONNX)')
|
||
|
#plt.show()
|
||
|
plt.savefig(data_path + model_name+'_plot_double.png')
|