How to read a 'CompactSVMModel' saved in a .mat file from a C++/Qt program
28 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
MahnnUser
am 22 Jul. 2024
Kommentiert: MahnnUser
am 31 Jul. 2024 um 13:53
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.
0 Kommentare
Akzeptierte Antwort
Arnav
am 26 Jul. 2024 um 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:
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Write C Functions Callable from MATLAB (MEX Files) finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!