Switched from LibSVM to ThunderSVM for better performance.
This commit is contained in:
parent
ac95537694
commit
e854036e56
10 changed files with 708 additions and 61 deletions
|
|
@ -273,12 +273,10 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
|||
startedSilVisemes = Time.time;
|
||||
}
|
||||
wasSilViseme = true;
|
||||
Debug.Log("Got sil");
|
||||
} else {
|
||||
if (wasSilViseme)
|
||||
startedSilVisemes = Time.time;
|
||||
wasSilViseme = false;
|
||||
Debug.Log("Not sil " + current + " " + weight);
|
||||
if (hybridLipSync && Time.time - startedSilVisemes < silVisemeHybridThreshold)
|
||||
ApplyMouthShape(true);
|
||||
}
|
||||
|
|
|
|||
201
Licenses/ThunderSVM.txt
Normal file
201
Licenses/ThunderSVM.txt
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
216
Source/ThunderSVMWrapper.cpp
Normal file
216
Source/ThunderSVMWrapper.cpp
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
// ThunderSVMWrapper.cpp : Defines the exported functions for the DLL.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
#include "framework.h"
|
||||
#include "ThunderSVMWrapper.h"
|
||||
#include "thundersvm/thundersvm.h"
|
||||
#include "thundersvm/model/svmmodel.h"
|
||||
#include "thundersvm/model/svc.h"
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern "C" void __cdecl print_log(const char *str) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct problem {
|
||||
int r;
|
||||
int c;
|
||||
DataSet::node2d x;
|
||||
vector<double> y;
|
||||
DataSet dataset;
|
||||
};
|
||||
|
||||
struct SVMWrapper {
|
||||
SVC *model;
|
||||
int cols;
|
||||
int classes;
|
||||
double *means;
|
||||
double *sdevs;
|
||||
SvmParam param;
|
||||
struct problem problem;
|
||||
};
|
||||
|
||||
typedef struct svm_node svmnode;
|
||||
|
||||
void make_svmnode_array(DataSet::node2d &dataset, float features[], int rows, int cols, double *means, double *sdevs, int rescale) {
|
||||
double row_factor = 1.0 / (double)rows;
|
||||
if (rescale) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
means[c] = 0;
|
||||
sdevs[c] = 0;
|
||||
}
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
means[c] += (double)features[r * cols + c];
|
||||
}
|
||||
}
|
||||
for (int c = 0; c < cols; c++) {
|
||||
means[c] *= row_factor;
|
||||
}
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
double sq_diff = ((double)features[r * cols + c] - means[c]);
|
||||
sq_diff *= sq_diff;
|
||||
sdevs[c] += sq_diff;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c < cols; c++) {
|
||||
sdevs[c] *= row_factor;
|
||||
sdevs[c] = sqrt(sdevs[c]);
|
||||
sdevs[c] = 1.0 / sdevs[c];
|
||||
}
|
||||
}
|
||||
|
||||
for (int r = 0; r < rows; r++) {
|
||||
dataset[r] = vector<DataSet::node>(cols);
|
||||
int idx = 0;
|
||||
for (int c = 0; c < cols; c++) {
|
||||
dataset[r][c].index = c + 1;
|
||||
dataset[r][c].value = (float)((features[r * cols + c] - means[c]) * sdevs[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void make_problem(struct problem &problem, float features[], float labels[], int rows, int cols, double *means, double *sdevs) {
|
||||
problem.r = rows;
|
||||
problem.c = cols;
|
||||
problem.y = vector<double>(rows);
|
||||
for (int i = 0; i < rows; i++)
|
||||
problem.y[i] = (double)labels[i];
|
||||
problem.x = DataSet::node2d(rows);
|
||||
make_svmnode_array(problem.x, features, rows, cols, means, sdevs, 1);
|
||||
problem.dataset = DataSet(problem.x, cols, problem.y);
|
||||
}
|
||||
|
||||
void destroy_problem(struct problem &problem) {
|
||||
problem.y.clear();
|
||||
problem.x.clear();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
__declspec(dllexport) void *__cdecl trainModel(float features[], float labels[], float weights[], int rows, int cols, int classes, int probability, float C) {
|
||||
if (!(rows > 0 && cols > 0))
|
||||
return NULL;
|
||||
|
||||
//svm_set_print_string_function(print_log);
|
||||
|
||||
struct SVMWrapper *sw = new SVMWrapper();
|
||||
sw->cols = cols;
|
||||
sw->classes = classes;
|
||||
sw->means = new double[cols];
|
||||
sw->sdevs = new double[cols];
|
||||
|
||||
sw->param.svm_type = SvmParam::C_SVC;
|
||||
sw->param.kernel_type = SvmParam::RBF;
|
||||
sw->param.degree = 3;
|
||||
sw->param.gamma = 1.0 / (double)cols;
|
||||
sw->param.coef0 = 0;
|
||||
sw->param.nu = 0.5;
|
||||
sw->param.C = C;
|
||||
sw->param.epsilon = 0.001;
|
||||
sw->param.p = 0.1;
|
||||
sw->param.probability = probability;
|
||||
sw->param.nr_weight = 0;
|
||||
sw->param.weight_label = NULL;
|
||||
sw->param.weight = NULL;
|
||||
|
||||
if (weights != NULL) {
|
||||
sw->param.nr_weight = classes;
|
||||
sw->param.weight_label = new int[classes];
|
||||
sw->param.weight = new double[classes];
|
||||
for (int i = 0; i < classes; i++) {
|
||||
sw->param.weight_label[i] = i;
|
||||
sw->param.weight[i] = (double)weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
make_problem(sw->problem, features, labels, rows, cols, sw->means, sw->sdevs);
|
||||
sw->model = new SVC();//svm_train(sw->problem, &sw->param);
|
||||
sw->model->train(sw->problem.dataset, sw->param);
|
||||
|
||||
if (weights != NULL) {
|
||||
delete sw->param.weight_label;
|
||||
delete sw->param.weight;
|
||||
}
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void __cdecl predict(void *ptr, float features[], float predictions[], double probabilities[], int rows) {
|
||||
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
|
||||
int cols = sw->cols;
|
||||
|
||||
DataSet::node2d instances = DataSet::node2d(rows);
|
||||
make_svmnode_array(instances, features, rows, sw->cols, sw->means, sw->sdevs, 0);
|
||||
vector<double> predicted = sw->model->predict(instances, -1);
|
||||
instances.clear();
|
||||
for (int r = 0; r < rows; r++)
|
||||
predictions[r] = (float)predicted[r];
|
||||
predicted.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void *__cdecl loadModel(char *filename, int cols, int classes, double means[], double sdevs[]) {
|
||||
struct SVMWrapper *sw = new SVMWrapper();
|
||||
sw->cols = cols;
|
||||
sw->model = new SVC();
|
||||
sw->model->load_from_file(filename);
|
||||
sw->classes = classes;
|
||||
sw->means = new double[cols];
|
||||
sw->sdevs = new double[cols];
|
||||
for (int c = 0; c < cols; c++) {
|
||||
sw->means[c] = means[c];
|
||||
sw->sdevs[c] = sdevs[c];
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void *__cdecl loadModelString(char *modelString, int cols, int classes, double means[], double sdevs[]) {
|
||||
struct SVMWrapper *sw = new SVMWrapper();
|
||||
sw->cols = cols;
|
||||
sw->model = new SVC();
|
||||
sw->model->load_from_string(modelString);
|
||||
sw->classes = classes;
|
||||
sw->means = new double[cols];
|
||||
sw->sdevs = new double[cols];
|
||||
for (int c = 0; c < cols; c++) {
|
||||
sw->means[c] = means[c];
|
||||
sw->sdevs[c] = sdevs[c];
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void __cdecl getScales(void *ptr, double means[], double sdevs[]) {
|
||||
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
|
||||
int cols = sw->cols;
|
||||
for (int c = 0; c < cols; c++) {
|
||||
means[c] = sw->means[c];
|
||||
sdevs[c] = sw->sdevs[c];
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(dllexport) const char *__cdecl saveModelString(void *ptr) {
|
||||
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
|
||||
string model = sw->model->save_to_string();
|
||||
return _strdup(model.c_str());
|
||||
}
|
||||
|
||||
__declspec(dllexport) int __cdecl saveModel(void *ptr, char *filename) {
|
||||
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
|
||||
sw->model->save_to_file(string(filename));
|
||||
return 1;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void __cdecl destroyModel(void *ptr) {
|
||||
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
|
||||
delete sw->means;
|
||||
delete sw->sdevs;
|
||||
delete sw->model;
|
||||
destroy_problem(sw->problem);
|
||||
delete sw;
|
||||
}
|
||||
}
|
||||
|
|
@ -152,6 +152,7 @@ public class OpenSeeExpression : MonoBehaviour
|
|||
private string[] classLabels = null;
|
||||
private int[] indices = null;
|
||||
private PointSelection pointSelection;
|
||||
private bool thunderSVM = false;
|
||||
//private bool newModel = false;
|
||||
|
||||
static public void LoadSerialized(byte[] modelBytes, out Dictionary<string, List<float[]>> expressions, out SVMModel model, out string[] classLabels, out int[] indices, ref PointSelection pointSelection) {
|
||||
|
|
@ -163,7 +164,10 @@ public class OpenSeeExpression : MonoBehaviour
|
|||
oser = formatter.Deserialize(gzipStream) as OpenSeeExpressionRepresentation;
|
||||
}
|
||||
expressions = oser.expressions;
|
||||
model = new SVMModel(oser.modelBytes);
|
||||
if (oser.thunderSVM)
|
||||
model = new ThunderSVMModel(oser.modelBytes);
|
||||
else
|
||||
model = new SVMModel(oser.modelBytes);
|
||||
classLabels = oser.classLabels;
|
||||
indices = oser.indices;
|
||||
//pointSelection = oser.pointSelection;
|
||||
|
|
@ -185,6 +189,7 @@ public class OpenSeeExpression : MonoBehaviour
|
|||
oser.classLabels = classLabels;
|
||||
oser.indices = indices;
|
||||
oser.pointSelection = pointSelection;
|
||||
oser.thunderSVM = true;
|
||||
//oser.newModel = true;
|
||||
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
|
|
@ -357,7 +362,7 @@ public class OpenSeeExpression : MonoBehaviour
|
|||
}
|
||||
ResetInfo();
|
||||
expressions = new Dictionary<string, List<float[]>>();
|
||||
model = new SVMModel();
|
||||
model = new ThunderSVMModel();
|
||||
rnd = new System.Random();
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +416,8 @@ public class OpenSeeExpression : MonoBehaviour
|
|||
return false;
|
||||
}
|
||||
modelReady = false;
|
||||
//model = new SVMModel();
|
||||
if (model is SVMModel)
|
||||
model = new ThunderSVMModel();
|
||||
SelectPoints();
|
||||
List<string> keys = new List<string>();
|
||||
List<string> accuracyWarnings = new List<string>();
|
||||
|
|
|
|||
|
|
@ -6,34 +6,61 @@ using System.Runtime.InteropServices;
|
|||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OpenSee {
|
||||
|
||||
public class SVMModel {
|
||||
#region DllImport
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern System.IntPtr trainModel(float[] features, float[] labels, float[] weights, int rows, int cols, int classes, int probability, float C);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, EntryPoint = "trainModel")]
|
||||
private static extern System.IntPtr trainModelDll(float[] features, float[] labels, float[] weights, int rows, int cols, int classes, int probability, float C);
|
||||
protected virtual System.IntPtr trainModel(float[] features, float[] labels, float[] weights, int rows, int cols, int classes, int probability, float C) {
|
||||
Debug.Log("Training LibSVM");
|
||||
return trainModelDll(features, labels, weights, rows, cols, classes, probability, C);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void predict(System.IntPtr model, float[] features, [Out] float[] predictions, [Out] double[] probabilities, int rows);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, EntryPoint = "predict")]
|
||||
private static extern void predictDll(System.IntPtr model, float[] features, [Out] float[] predictions, [Out] double[] probabilities, int rows);
|
||||
protected virtual void predict(System.IntPtr model, float[] features, [Out] float[] predictions, [Out] double[] probabilities, int rows) {
|
||||
predictDll(model, features, predictions, probabilities, rows);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
private static extern System.IntPtr loadModel([MarshalAs(UnmanagedType.LPStr)]string filename, int cols, int classes, double[] means, double[] sdevs);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "loadModel")]
|
||||
private static extern System.IntPtr loadModelDll([MarshalAs(UnmanagedType.LPStr)]string filename, int cols, int classes, double[] means, double[] sdevs);
|
||||
protected virtual System.IntPtr loadModel([MarshalAs(UnmanagedType.LPStr)]string filename, int cols, int classes, double[] means, double[] sdevs) {
|
||||
return loadModelDll(filename, cols, classes, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
private static extern System.IntPtr loadModelString([MarshalAs(UnmanagedType.LPStr)]string modelString, int cols, int classes, double[] means, double[] sdevs);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "loadModelString")]
|
||||
private static extern System.IntPtr loadModelStringDll([MarshalAs(UnmanagedType.LPStr)]string modelString, int cols, int classes, double[] means, double[] sdevs);
|
||||
protected virtual System.IntPtr loadModelString([MarshalAs(UnmanagedType.LPStr)]string modelString, int cols, int classes, double[] means, double[] sdevs) {
|
||||
Debug.Log("Loading LibSVM");
|
||||
return loadModelStringDll(modelString, cols, classes, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void getScales(System.IntPtr model, [Out] double[] means, [Out] double[] sdevs);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, EntryPoint = "getScales")]
|
||||
private static extern void getScalesDll(System.IntPtr model, [Out] double[] means, [Out] double[] sdevs);
|
||||
protected virtual void getScales(System.IntPtr model, [Out] double[] means, [Out] double[] sdevs) {
|
||||
getScalesDll(model, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
private static extern int saveModel(System.IntPtr model, [MarshalAs(UnmanagedType.LPStr)]string filename);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "saveModel")]
|
||||
private static extern int saveModelDll(System.IntPtr model, [MarshalAs(UnmanagedType.LPStr)]string filename);
|
||||
protected virtual int saveModel(System.IntPtr model, [MarshalAs(UnmanagedType.LPStr)]string filename) {
|
||||
return saveModelDll(model, filename);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
private static extern string saveModelString(System.IntPtr model);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "saveModelString")]
|
||||
private static extern string saveModelStringDll(System.IntPtr model);
|
||||
protected virtual string saveModelString(System.IntPtr model) {
|
||||
return saveModelStringDll(model);
|
||||
}
|
||||
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void destroyModel(System.IntPtr model);
|
||||
[DllImport("SVMModel", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroyModel")]
|
||||
private static extern void destroyModelDll(System.IntPtr model);
|
||||
protected virtual void destroyModel(System.IntPtr model) {
|
||||
destroyModelDll(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool haveModel = false;
|
||||
|
|
@ -43,51 +70,51 @@ public class SVMModel {
|
|||
|
||||
[Serializable]
|
||||
private class SVMModelRepresentation {
|
||||
private string modelString;
|
||||
private int cols;
|
||||
private int maxClasses;
|
||||
private double[] means;
|
||||
private double[] sdevs;
|
||||
public string modelString;
|
||||
public int cols;
|
||||
public int maxClasses;
|
||||
public double[] means;
|
||||
public double[] sdevs;
|
||||
}
|
||||
|
||||
static public System.IntPtr LoadSerialized(byte[] modelBytes, out int cols, out int maxClasses, bool compress) {
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
MemoryStream memoryStream = new MemoryStream(modelBytes);
|
||||
memoryStream.Position = 0;
|
||||
SVMModelRepresentation smr;
|
||||
if (compress) {
|
||||
using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) {
|
||||
smr = formatter.Deserialize(gzipStream) as SVMModelRepresentation;
|
||||
}
|
||||
} else {
|
||||
smr = formatter.Deserialize(memoryStream) as SVMModelRepresentation;
|
||||
public System.IntPtr LoadSerialized(byte[] modelBytes, out int cols, out int maxClasses, bool compress) {
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
MemoryStream memoryStream = new MemoryStream(modelBytes);
|
||||
memoryStream.Position = 0;
|
||||
SVMModelRepresentation smr;
|
||||
if (compress) {
|
||||
using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) {
|
||||
smr = formatter.Deserialize(gzipStream) as SVMModelRepresentation;
|
||||
}
|
||||
cols = smr.cols;
|
||||
maxClasses = smr.maxClasses;
|
||||
System.IntPtr model = loadModelString(smr.modelString, smr.cols, smr.maxClasses, smr.means, smr.sdevs);
|
||||
return model;
|
||||
} else {
|
||||
smr = formatter.Deserialize(memoryStream) as SVMModelRepresentation;
|
||||
}
|
||||
cols = smr.cols;
|
||||
maxClasses = smr.maxClasses;
|
||||
System.IntPtr model = loadModelString(smr.modelString, smr.cols, smr.maxClasses, smr.means, smr.sdevs);
|
||||
return model;
|
||||
}
|
||||
|
||||
static public byte[] ToSerialized(System.IntPtr model, int cols, int maxClasses, bool compress) {
|
||||
SVMModelRepresentation smr = new SVMModelRepresentation();
|
||||
smr.cols = cols;
|
||||
smr.maxClasses = maxClasses;
|
||||
smr.means = new double[cols];
|
||||
smr.sdevs = new double[cols];
|
||||
getScales(model, smr.means, smr.sdevs);
|
||||
smr.modelString = saveModelString(model);
|
||||
public byte[] ToSerialized(System.IntPtr model, int cols, int maxClasses, bool compress) {
|
||||
SVMModelRepresentation smr = new SVMModelRepresentation();
|
||||
smr.cols = cols;
|
||||
smr.maxClasses = maxClasses;
|
||||
smr.means = new double[cols];
|
||||
smr.sdevs = new double[cols];
|
||||
getScales(model, smr.means, smr.sdevs);
|
||||
smr.modelString = saveModelString(model);
|
||||
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
if (compress) {
|
||||
using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) {
|
||||
formatter.Serialize(gzipStream, smr);
|
||||
gzipStream.Flush();
|
||||
}
|
||||
} else {
|
||||
formatter.Serialize(memoryStream, smr);
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
if (compress) {
|
||||
using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) {
|
||||
formatter.Serialize(gzipStream, smr);
|
||||
gzipStream.Flush();
|
||||
}
|
||||
return memoryStream.ToArray();
|
||||
} else {
|
||||
formatter.Serialize(memoryStream, smr);
|
||||
}
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
public void DestroyModel() {
|
||||
|
|
@ -99,7 +126,7 @@ public class SVMModel {
|
|||
|
||||
private void LoadModel(byte[] modelBytes, bool compress) {
|
||||
DestroyModel();
|
||||
model = SVMModelRepresentation.LoadSerialized(modelBytes, out cols, out maxClasses, compress);
|
||||
model = LoadSerialized(modelBytes, out cols, out maxClasses, compress);
|
||||
haveModel = true;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +137,7 @@ public class SVMModel {
|
|||
private byte[] SaveModel(bool compress) {
|
||||
if (!haveModel)
|
||||
return null;
|
||||
return SVMModelRepresentation.ToSerialized(model, cols, maxClasses, compress);
|
||||
return ToSerialized(model, cols, maxClasses, compress);
|
||||
}
|
||||
|
||||
public byte[] SaveModel() {
|
||||
|
|
@ -143,7 +170,9 @@ public class SVMModel {
|
|||
|
||||
maxClasses = max + 1;
|
||||
this.cols = cols;
|
||||
float start = Time.realtimeSinceStartup;
|
||||
model = trainModel(features, labels, weights, rows, cols, maxClasses, probability, C);
|
||||
Debug.Log("Training took: " + (Time.realtimeSinceStartup - start).ToString());
|
||||
haveModel = true;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
71
Unity/Plugins/ThunderSVMModel.cs
Normal file
71
Unity/Plugins/ThunderSVMModel.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using OpenSee;
|
||||
using UnityEngine;
|
||||
|
||||
public class ThunderSVMModel : SVMModel {
|
||||
#region DllImport
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, EntryPoint = "trainModel")]
|
||||
private static extern System.IntPtr trainModelDll(float[] features, float[] labels, float[] weights, int rows, int cols, int classes, int probability, float C);
|
||||
protected override System.IntPtr trainModel(float[] features, float[] labels, float[] weights, int rows, int cols, int classes, int probability, float C) {
|
||||
Debug.Log("Training ThunderSVM");
|
||||
return trainModelDll(features, labels, weights, rows, cols, classes, probability, C);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, EntryPoint = "predict")]
|
||||
private static extern void predictDll(System.IntPtr model, float[] features, [Out] float[] predictions, [Out] double[] probabilities, int rows);
|
||||
protected override void predict(System.IntPtr model, float[] features, [Out] float[] predictions, [Out] double[] probabilities, int rows) {
|
||||
predictDll(model, features, predictions, probabilities, rows);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "loadModel")]
|
||||
private static extern System.IntPtr loadModelDll([MarshalAs(UnmanagedType.LPStr)]string filename, int cols, int classes, double[] means, double[] sdevs);
|
||||
protected override System.IntPtr loadModel([MarshalAs(UnmanagedType.LPStr)]string filename, int cols, int classes, double[] means, double[] sdevs) {
|
||||
return loadModelDll(filename, cols, classes, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "loadModelString")]
|
||||
private static extern System.IntPtr loadModelStringDll([MarshalAs(UnmanagedType.LPStr)]string modelString, int cols, int classes, double[] means, double[] sdevs);
|
||||
protected override System.IntPtr loadModelString([MarshalAs(UnmanagedType.LPStr)]string modelString, int cols, int classes, double[] means, double[] sdevs) {
|
||||
Debug.Log("Loading ThunderSVM");
|
||||
return loadModelStringDll(modelString, cols, classes, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, EntryPoint = "getScales")]
|
||||
private static extern void getScalesDll(System.IntPtr model, [Out] double[] means, [Out] double[] sdevs);
|
||||
protected override void getScales(System.IntPtr model, [Out] double[] means, [Out] double[] sdevs) {
|
||||
getScalesDll(model, means, sdevs);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "saveModel")]
|
||||
private static extern int saveModelDll(System.IntPtr model, [MarshalAs(UnmanagedType.LPStr)]string filename);
|
||||
protected override int saveModel(System.IntPtr model, [MarshalAs(UnmanagedType.LPStr)]string filename) {
|
||||
return saveModelDll(model, filename);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "saveModelString")]
|
||||
private static extern string saveModelStringDll(System.IntPtr model);
|
||||
protected override string saveModelString(System.IntPtr model) {
|
||||
return saveModelStringDll(model);
|
||||
}
|
||||
|
||||
[DllImport("ThunderSVMWrapper", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroyModel")]
|
||||
private static extern void destroyModelDll(System.IntPtr model);
|
||||
protected override void destroyModel(System.IntPtr model) {
|
||||
destroyModelDll(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public ThunderSVMModel() {
|
||||
}
|
||||
|
||||
public ThunderSVMModel(byte[] modelBytes) {
|
||||
LoadModel(modelBytes);
|
||||
}
|
||||
}
|
||||
BIN
Unity/Plugins/ThunderSVMWrapper.dll
Normal file
BIN
Unity/Plugins/ThunderSVMWrapper.dll
Normal file
Binary file not shown.
63
Unity/Plugins/ThunderSVMWrapper.dll.meta
Normal file
63
Unity/Plugins/ThunderSVMWrapper.dll.meta
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c58dd9d1f0cf3140bd004d536712abb
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Editor: 0
|
||||
Exclude Linux64: 0
|
||||
Exclude OSXUniversal: 0
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 0
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Unity/Plugins/thundersvm.dll
Normal file
BIN
Unity/Plugins/thundersvm.dll
Normal file
Binary file not shown.
63
Unity/Plugins/thundersvm.dll.meta
Normal file
63
Unity/Plugins/thundersvm.dll.meta
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e549e6cbc6a547748abc7f1b05bfa7b4
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Editor: 0
|
||||
Exclude Linux64: 0
|
||||
Exclude OSXUniversal: 0
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 0
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Add table
Add a link
Reference in a new issue