Clear Filters
Clear Filters

How to read a 'CompactSVMModel' saved in a .mat file from a C++/Qt program

28 views (last 30 days)
I tried to save a machine learning model into a .mat file, and then read it from a Qt/C++ application. Following the documentation, I managed to read files containing basic types like double or int. As my model is of type 'classreg.learning.classif.CompactClassificationSVM', I wonder if it is still possible to read it.
As and example, i saved this iosnosphere model on matlab
load ionosphere
SVMModel = fitcsvm(X,Y,'Standardize',true,'ClassNames',{'b','g'})
CompactSVMModel = compact(SVMModel)
save("CompactSVMModel.mat", "CompactSVMModel")
I imported the relevant library in the CMakeLists.txt
find_package(Matlab "x.xx" EXACT COMPONENTS "MX_LIBRARY" "MAT_LIBRARY" "DATAARRAY_LIBRARY" )
target_link_libraries(target PRIVATE Matlab::mat )
I used the "mat.h" library to open and read the data.
#include "mat.h"
int main () {
std::string stdFilename = "/filepath/CompactSVMModel.mat";
const char *variableName = "CompactSVMModel";
// Open the MAT-File
MATFile *matFile = matOpen(stdFilename.c_str(), "r");
if (!matFile) {
qDebug() << "Error opening MAT file: " << stdFilename;
}
// Read the variable from the MAT-File
mxArray *dataArray = matGetVariable(matFile, variableName);
if (!dataArray) {
qDebug() << "Error reading variable: " << variableName << " from MAT file: " << stdFilename;
}
...
// read a save the diffrent fields into containers
return 0;
}
At the first if statement, matFile is NULL.

Accepted Answer

Arnav
Arnav on 26 Jul 2024 at 9:17
Hi,
I tried executing your code with the particulars provided in the CMakeLists.txt with MATLAB R2022b libraries.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(ML_Answers)
find_package(Matlab "9.13.0.2553342"EXACT COMPONENTS MX_LIBRARY MAT_LIBRARY DATAARRAY_LIBRARY)
include_directories(${Matlab_INCLUDE_DIRS})
add_executable(ML_Answers main.cpp)
target_link_libraries(ML_Answers PRIVATE Matlab::mat)
I built and ran the project using the following commands:
$ cmake -G "MinGW Makefiles" -DCMAKE_CXX_COMPILER=C:\ProgramData\MATLAB\SupportPackages\R2022b\3P.instrset\mingw_w64.instrset\bin\g++.exe .
$ mingw32-make.exe
$./ML_Answers.exe
This executes as expected. I encountered the issue you mentioned when I built the project in a different build subdirectory (instead of the project root directory) and tried executing the executable from inside the build subdirectory. This was due to the relative path of the CompactSVMModel.mat file not being correct. You might try rechecking to see if you made a similar error.
For the task of reading a class instance from CompactSVMModel.mat file using a standalone C++ program, a workaround would be to save the different properties as different variables in the CompactSVMModel.mat file as follows:
% Extract the SupportVectors property
SupportVectors = CompactSVMModel.SupportVectors;
save('CompactSVMModel.mat', 'SupportVectors', 'CompactSVMModel');
Following this, the SupportedVectors variable can be read using C++ program in the following way (I substituted qDebug() for std::cerr and std::cout):
#include "mat.h"
#include <string>
#include <iostream>
int main() {
std::string stdFilename = "./CompactSVMModel.mat";
const char* variableName = "SupportVectors"; // Change to read the SupportVectors property
// Open the MAT-File
MATFile *matFile = matOpen(stdFilename.c_str(), "r");
if (!matFile) {
std::cerr << "Error opening MAT file: " << stdFilename << std::endl;
return 1; // Exit with error code
}
// Read the variable from the MAT-File
mxArray *dataArray = matGetVariable(matFile, variableName);
if (!dataArray) {
std::cerr << "Error reading variable: " << variableName << " from MAT file: " << stdFilename << std::endl;
matClose(matFile);
return 1; // Exit with error code
}
// Print the dimensions of the SupportVectors matrix
mwSize numRows = mxGetM(dataArray);
mwSize numCols = mxGetN(dataArray);
std::cout << "SupportVectors dimensions: " << numRows << " x " << numCols << std::endl;
// Clean up and close the MAT-File
mxDestroyArray(dataArray);
matClose(matFile);
std::cout << "SupportVectors have been successfully read from the MAT file." << std::endl;
return 0;
}
Output for the C++ Program:
SupportVectors dimensions: 89 x 2
SupportVectors have been successfully read from the MAT file.
You can learn more about how to read variables here:
Alternatively, you can build your project using MEX and use C++ MEX API. You can read more about the C++ MEX API here:
  1 Comment
MahnnUser
MahnnUser on 31 Jul 2024 at 13:53
Hi @Arnav,
Thank you for your response. In the end, I used a different approach. My goal was to translate my MATLAB program into a C++ program using MATLAB Coder. Since the MATLAB program used a model, I needed to import it. However, I found that the model could be integrated into the C++ library generated by MATLAB Coder. https://fr.mathworks.com/help/stats/loadlearnerforcoder.html

Sign in to comment.

More Answers (0)

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!