├── python ├── src │ ├── __init__.py │ ├── move_files.sh │ └── xmm.i ├── examples │ ├── using_configurations.py │ ├── data │ │ ├── hhmm_test_data1.txt │ │ ├── hhmm_test_data2.txt │ │ └── hhmm_test_data3.txt │ └── test_gmm.py └── CMakeLists.txt ├── doc └── doc-misc │ ├── footer.html │ ├── xmm_featured.jpg │ ├── xmm_models.jpg │ ├── xmm_featured_.jpg │ ├── xmm_architecture.jpg │ ├── jtabs.css │ ├── header.html │ ├── python_example.py │ └── XmmDoxygenLayout.xml ├── ide └── xcode │ └── xmm-lib.xcodeproj │ └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── xmm-lib.xccheckout ├── dependencies └── jsoncpp │ ├── include │ ├── json.h │ ├── version.h │ ├── autolink.h │ ├── forwards.h │ ├── json-features.h │ ├── assertions.h │ └── config.h │ ├── LICENSE │ └── src │ ├── json_tool.h │ └── json_valueiterator.inl ├── .gitignore ├── test ├── xmmTestsMain.cpp ├── xmmTestsComplexity.cpp ├── xmmTestsUtilities.hpp ├── xmmTestsJsonIO.cpp ├── xmmTestsGaussianCovarianceMode.cpp └── xmmTestsMultithreading.cpp ├── src ├── models │ ├── kmeans │ │ ├── xmmKMeansResults.hpp │ │ ├── xmmKMeansParameters.hpp │ │ ├── xmmKMeansParameters.cpp │ │ └── xmmKMeans.hpp │ ├── hmm │ │ ├── xmmHmmResults.hpp │ │ ├── xmmHmmParameters.hpp │ │ └── xmmHmmParameters.cpp │ └── gmm │ │ ├── xmmGmmParameters.hpp │ │ ├── xmmGmm.hpp │ │ └── xmmGmmParameters.cpp └── core │ ├── model │ ├── xmmModelParameters.hpp │ ├── xmmModelResults.hpp │ ├── xmmModelSharedParameters.hpp │ ├── xmmModelSharedParameters.cpp │ ├── xmmModelConfiguration.hpp │ └── xmmModelSingleClass.cpp │ └── common │ ├── xmmEvents.hpp │ ├── xmmAttribute.cpp │ ├── xmmJson.cpp │ └── xmmCircularbuffer.hpp ├── readme.md └── CMakeLists.txt /python/src/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ["xmm"] 2 | from xmm import * 3 | -------------------------------------------------------------------------------- /doc/doc-misc/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /doc/doc-misc/xmm_featured.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/xmm/HEAD/doc/doc-misc/xmm_featured.jpg -------------------------------------------------------------------------------- /doc/doc-misc/xmm_models.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/xmm/HEAD/doc/doc-misc/xmm_models.jpg -------------------------------------------------------------------------------- /doc/doc-misc/xmm_featured_.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/xmm/HEAD/doc/doc-misc/xmm_featured_.jpg -------------------------------------------------------------------------------- /doc/doc-misc/xmm_architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/xmm/HEAD/doc/doc-misc/xmm_architecture.jpg -------------------------------------------------------------------------------- /python/src/move_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | INSTALL_DIR=bin/xmm 4 | mkdir -p ${INSTALL_DIR} 5 | cp _xmm.so xmm.py src/__init__.py ${INSTALL_DIR} -------------------------------------------------------------------------------- /ide/xcode/xmm-lib.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/json.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_JSON_H_INCLUDED 7 | #define JSON_JSON_H_INCLUDED 8 | 9 | #include "autolink.h" 10 | #include "json-features.h" 11 | #include "reader.h" 12 | #include "value.h" 13 | #include "writer.h" 14 | 15 | #endif // JSON_JSON_H_INCLUDED 16 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/version.h: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. This file (and "version") is generated by CMake. 2 | // Run CMake configure step to update it. 3 | #ifndef JSON_VERSION_H_INCLUDED 4 | # define JSON_VERSION_H_INCLUDED 5 | 6 | # define JSONCPP_VERSION_STRING "1.6.5" 7 | # define JSONCPP_VERSION_MAJOR 1 8 | # define JSONCPP_VERSION_MINOR 6 9 | # define JSONCPP_VERSION_PATCH 5 10 | # define JSONCPP_VERSION_QUALIFIER 11 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) 12 | 13 | #endif // JSON_VERSION_H_INCLUDED 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ide/xcode/build 2 | ide/xcode/xmm-lib.xcodeproj/project.xcworkspace 3 | ide/xcode/xmm-lib.xcodeproj/xcuserdata 4 | dependencies/libjson/ide/build 5 | dependencies/libjson/ide/json.xcodeproj/xcuserdata 6 | dependencies/libjson/ide/json.xcodeproj/project.xcworkspace/xcuserdata 7 | dependencies/libjson/Makefile 8 | doc/html 9 | doc/xml 10 | bin 11 | Makefile 12 | python/Makefile 13 | CMakeFiles 14 | python/bin 15 | python/xmm.py 16 | python/xmm_doc.i 17 | python/xmmPYTHON_wrap.cxx 18 | python/bin 19 | python/_build_tmp 20 | *CMakeCache.txt 21 | *cmake_install.cmake 22 | *pyc 23 | *.a 24 | *.so 25 | *.dylib 26 | *.ipynb_checkpoints 27 | cmake_clean.sh 28 | **/.DS_Store 29 | **/Thumbs.db 30 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/autolink.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_AUTOLINK_H_INCLUDED 7 | #define JSON_AUTOLINK_H_INCLUDED 8 | 9 | #include "config.h" 10 | 11 | #ifdef JSON_IN_CPPTL 12 | #include 13 | #endif 14 | 15 | #if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ 16 | !defined(JSON_IN_CPPTL) 17 | #define CPPTL_AUTOLINK_NAME "json" 18 | #undef CPPTL_AUTOLINK_DLL 19 | #ifdef JSON_DLL 20 | #define CPPTL_AUTOLINK_DLL 21 | #endif 22 | #include "autolink.h" 23 | #endif 24 | 25 | #endif // JSON_AUTOLINK_H_INCLUDED 26 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/forwards.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_FORWARDS_H_INCLUDED 7 | #define JSON_FORWARDS_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "config.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | // writer.h 16 | class FastWriter; 17 | class StyledWriter; 18 | 19 | // reader.h 20 | class Reader; 21 | 22 | // features.h 23 | class Features; 24 | 25 | // value.h 26 | typedef unsigned int ArrayIndex; 27 | class StaticString; 28 | class Path; 29 | class PathArgument; 30 | class Value; 31 | class ValueIteratorBase; 32 | class ValueIterator; 33 | class ValueConstIterator; 34 | 35 | } // namespace Json 36 | 37 | #endif // JSON_FORWARDS_H_INCLUDED 38 | -------------------------------------------------------------------------------- /doc/doc-misc/jtabs.css: -------------------------------------------------------------------------------- 1 | .tabs, .tabs2, .tabs3 { 2 | background-color: #F35757; 3 | background-image: none; 4 | width: 100%; 5 | z-index: 101; 6 | font-size: 13px; 7 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 8 | } 9 | 10 | .tabs2 { 11 | font-size: 10px; 12 | } 13 | .tabs3 { 14 | font-size: 9px; 15 | } 16 | 17 | .tablist { 18 | width: 80%; 19 | margin: 0; 20 | padding: 0; 21 | display: table; 22 | } 23 | 24 | .tablist li { 25 | float: left; 26 | text-align: center; 27 | display: table-cell; 28 | background-color: #F35757; 29 | line-height: 36px; 30 | list-style: none; 31 | width: 16%; 32 | } 33 | 34 | .tablist a { 35 | display: block; 36 | padding: 0 30px; 37 | font-size: 14px; 38 | background-color: #F35757; 39 | border-right: 1px solid #fff; 40 | border-bottom: 1px solid #fff; 41 | color: #FFF; 42 | text-decoration: none; 43 | outline: none; 44 | } 45 | 46 | .tabs3 .tablist a { 47 | padding: 0 10px; 48 | } 49 | 50 | .tablist a:hover { 51 | background-color: #B30303; 52 | color: #fff; 53 | text-decoration: none; 54 | } 55 | 56 | .tablist li.current a { 57 | background-color: #B30303; 58 | color: #fff; 59 | } 60 | -------------------------------------------------------------------------------- /test/xmmTestsMain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsMain.cpp 3 | * 4 | * Test suite for the XMM library 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #define CATCH_CONFIG_MAIN 34 | #include "catch.hpp" 35 | #define XMM_TESTING 36 | #include "xmm.h" 37 | -------------------------------------------------------------------------------- /python/examples/using_configurations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | Example of using configuration to specify class parameters 5 | 6 | Contact: 7 | - Jules Francoise 8 | 9 | Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 10 | 11 | This File is part of XMM. 12 | """ 13 | 14 | # import matplotlib.pyplot as plt 15 | import numpy as np 16 | import xmm 17 | 18 | 19 | # Create the training set 20 | training_set = xmm.TrainingSet() 21 | training_set.dimension.set(3) 22 | labels = ['a', 'b', 'c'] 23 | 24 | # Create the model and set the default configuration 25 | hhmm = xmm.HierarchicalHMM() 26 | hhmm.configuration.states.set(10) # set default number of state per class 27 | 28 | # Record each phrase (random) to the training set and give each class a number 29 | # of states proportional to the phrase length 30 | for i in range(3): 31 | data = np.genfromtxt('data/hhmm_test_data%i.txt' % (i + 1)) 32 | training_set.addPhrase(i, labels[i]) 33 | [training_set.getPhrase(i).record(frame) for frame in data] 34 | num_states = len(data) // 10 35 | # Set the number of states for each class 36 | hhmm.configuration[labels[i]].states.set(num_states) 37 | 38 | # Train the model 39 | hhmm.train(training_set) 40 | 41 | # Print model parameters after training 42 | for label in labels: 43 | print('The HMM for for class %s has %i states' % 44 | (labels[i], hhmm.models[label].parameters.states.get())) 45 | -------------------------------------------------------------------------------- /doc/doc-misc/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | 14 | $treeview 15 | $search 16 | $mathjax 17 | 18 | $extrastylesheet 19 | 20 | 21 |
22 | 23 | 24 |
25 | 26 |

$projectname

27 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /ide/xcode/xmm-lib.xcodeproj/project.xcworkspace/xcshareddata/xmm-lib.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | A24627F6-9023-4A33-8FAC-1E6AC939D566 9 | IDESourceControlProjectName 10 | xmm-lib 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 7D7360FCF28970793D825A67F640E8AA8E8D6FA6 14 | https://github.com/Ircam-RnD/xmm.git 15 | 16 | IDESourceControlProjectPath 17 | ide/xcode/xmm-lib.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 7D7360FCF28970793D825A67F640E8AA8E8D6FA6 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/Ircam-RnD/xmm.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 7D7360FCF28970793D825A67F640E8AA8E8D6FA6 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 7D7360FCF28970793D825A67F640E8AA8E8D6FA6 36 | IDESourceControlWCCName 37 | xmm 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/models/kmeans/xmmKMeansResults.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmKMeansResults.hpp 3 | * 4 | * Results of the K-Means clustering Algorithm 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmKMeansResults_h 34 | #define xmmKMeansResults_h 35 | 36 | #include "../../core/model/xmmModelResults.hpp" 37 | 38 | namespace xmm { 39 | /** 40 | @ingroup KMeans 41 | @brief Results of the clustering process 42 | */ 43 | template <> 44 | struct Results { 45 | /** 46 | @brief Distance of the observation to each cluster 47 | */ 48 | std::vector distances; 49 | 50 | /** 51 | @brief Likeliest Cluster 52 | */ 53 | unsigned int likeliest; 54 | }; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /doc/doc-misc/python_example.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import mhmm 3 | 4 | # Load Training Data 5 | training_motion_1 = np.genfromtxt('training_motion_1.txt') 6 | training_motion_2 = np.genfromtxt('training_motion_2.txt') 7 | training_sound_1 = np.genfromtxt('training_sound_1.txt') 8 | training_sound_2 = np.genfromtxt('training_sound_2.txt') 9 | 10 | dim_gesture = training_motion_1.shape[1] 11 | dim_sound = training_sound_1.shape[1] 12 | 13 | # Create a multimodal training set 14 | training_set = mhmm.TrainingSet(mhmm.BIMODAL) 15 | training_set.set_dimension(dim_gesture + dim_sound) 16 | training_set.set_dimension_input(dim_sound) 17 | 18 | # Record First Phrase 19 | for frame_motion, frame_sound in zip(training_motion_1, training_sound_1): 20 | training_set.recordPhrase_input (0, frame_motion) 21 | training_set.recordPhrase_output(0, frame_sound) 22 | training_set.setPhraseLabel(0, mhmm.Label('one')) 23 | 24 | # Record Second Phrase 25 | for frame_motion, frame_sound in zip(training_motion_2, training_sound_2): 26 | training_set.recordPhrase_input (1, frame_motion) 27 | training_set.recordPhrase_output(1, frame_sound) 28 | training_set.setPhraseLabel(1, mhmm.Label('two')) 29 | 30 | # Instantiate and Train a Hierarchical Multimodal HMM 31 | xmm = mhmm.HierarchicalHMM(mhmm.BIMODAL, training_set) 32 | xmm.set_nbStates(10) 33 | xmm.set_nbMixtureComponents(1) 34 | xmm.set_varianceOffset(0.1, 0.01) 35 | xmm.train() 36 | 37 | # Perform joint recognition and Mapping 38 | test_motion = np.genfromtxt('test_motion.txt') 39 | predicted_sound = np.zeros((len(test_motion), dim_sound)) 40 | log_likelihoods = np.zeros((len(test_motion), xmm.size())) 41 | xmm.performance_init() 42 | for t, frame_motion in enumerate(test_motion): 43 | xmm.performance_update(frame) 44 | predicted_sound[t, :] = xmm.results_predicted_output 45 | log_likelihoods[t, :] = xmm.results_log_likelihoods 46 | 47 | 48 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/json-features.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 7 | #define CPPTL_JSON_FEATURES_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "forwards.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | /** \brief Configuration passed to reader and writer. 16 | * This configuration object can be used to force the Reader or Writer 17 | * to behave in a standard conforming way. 18 | */ 19 | class JSON_API Features { 20 | public: 21 | /** \brief A configuration that allows all features and assumes all strings 22 | * are UTF-8. 23 | * - C & C++ comments are allowed 24 | * - Root object can be any JSON value 25 | * - Assumes Value strings are encoded in UTF-8 26 | */ 27 | static Features all(); 28 | 29 | /** \brief A configuration that is strictly compatible with the JSON 30 | * specification. 31 | * - Comments are forbidden. 32 | * - Root object must be either an array or an object value. 33 | * - Assumes Value strings are encoded in UTF-8 34 | */ 35 | static Features strictMode(); 36 | 37 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 38 | */ 39 | Features(); 40 | 41 | /// \c true if comments are allowed. Default: \c true. 42 | bool allowComments_; 43 | 44 | /// \c true if root must be either an array or an object value. Default: \c 45 | /// false. 46 | bool strictRoot_; 47 | 48 | /// \c true if dropped null placeholders are allowed. Default: \c false. 49 | bool allowDroppedNullPlaceholders_; 50 | 51 | /// \c true if numeric object key are allowed. Default: \c false. 52 | bool allowNumericKeys_; 53 | }; 54 | 55 | } // namespace Json 56 | 57 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 58 | -------------------------------------------------------------------------------- /test/xmmTestsComplexity.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsComplexity.cpp 3 | * 4 | * Test suite for the algorithm complexity (Hierarchical HMM) 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "catch.hpp" 34 | #include "xmmTestsUtilities.hpp" 35 | #define XMM_TESTING 36 | #include "xmm.h" 37 | #include 38 | #include 39 | 40 | using namespace std; 41 | 42 | // TEST_CASE("Profiling: Large number of classes", "[HierarhicalHMM]") { 43 | // xmm::TrainingSet ts; 44 | // int num_classes = 1200; 45 | // std::default_random_engine generator; 46 | // std::normal_distribution dist; 47 | // for (int i = 0; i < num_classes; i++) { 48 | // ts.addPhrase(i, to_string(i + 1)); 49 | // for (int frame_idx = 0; frame_idx < 200; frame_idx++) { 50 | // ts.getPhrase(i)->record({dist(generator)}); 51 | // } 52 | // } 53 | // xmm::HierarchicalHMM model; 54 | // model.train(&ts); 55 | // model.reset(); 56 | // for (int frame_idx = 0; frame_idx < 10000; frame_idx++) { 57 | // model.filter({dist(generator)}); 58 | // } 59 | //} 60 | -------------------------------------------------------------------------------- /test/xmmTestsUtilities.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsUtilities.hpp 3 | * 4 | * Utilities for Unit-Testing 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmm_lib_catch_utilities_h 34 | #define xmm_lib_catch_utilities_h 35 | 36 | #include "catch.hpp" 37 | 38 | /** 39 | * @brief Check for vector approximate equality 40 | */ 41 | template 42 | void CHECK_VECTOR_APPROX(std::vector const& a, std::vector const& b, 43 | double epsilon = -1.) { 44 | REQUIRE(a.size() == b.size()); 45 | std::string errormsg = "CHECK_VECTOR_APPROX:\n{"; 46 | std::string errormsg2 = "}\n==\n{"; 47 | std::ostringstream convert; 48 | std::ostringstream convert2; 49 | for (size_t i = 0; i < a.size(); ++i) { 50 | convert << a[i] << " "; 51 | convert2 << b[i] << " "; 52 | } 53 | INFO(errormsg + convert.str() + errormsg2 + convert2.str()); 54 | if (epsilon > 0.0) { 55 | for (size_t i = 0; i < a.size(); ++i) { 56 | REQUIRE(a[i] == Approx(b[i]).epsilon(epsilon)); 57 | } 58 | } else { 59 | for (size_t i = 0; i < a.size(); ++i) { 60 | REQUIRE(a[i] == Approx(b[i])); 61 | } 62 | } 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/assertions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 7 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #if !defined(JSON_IS_AMALGAMATION) 13 | #include "config.h" 14 | #endif // if !defined(JSON_IS_AMALGAMATION) 15 | 16 | /** It should not be possible for a maliciously designed file to 17 | * cause an abort() or seg-fault, so these macros are used only 18 | * for pre-condition violations and internal logic errors. 19 | */ 20 | #if JSON_USE_EXCEPTION 21 | 22 | // @todo <= add detail about condition in exception 23 | # define JSON_ASSERT(condition) \ 24 | {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} 25 | 26 | # define JSON_FAIL_MESSAGE(message) \ 27 | { \ 28 | std::ostringstream oss; oss << message; \ 29 | Json::throwLogicError(oss.str()); \ 30 | abort(); \ 31 | } 32 | 33 | #else // JSON_USE_EXCEPTION 34 | 35 | # define JSON_ASSERT(condition) assert(condition) 36 | 37 | // The call to assert() will show the failure message in debug builds. In 38 | // release builds we abort, for a core-dump or debugger. 39 | # define JSON_FAIL_MESSAGE(message) \ 40 | { \ 41 | std::ostringstream oss; oss << message; \ 42 | assert(false && oss.str().c_str()); \ 43 | abort(); \ 44 | } 45 | 46 | 47 | #endif 48 | 49 | #define JSON_ASSERT_MESSAGE(condition, message) \ 50 | if (!(condition)) { \ 51 | JSON_FAIL_MESSAGE(message); \ 52 | } 53 | 54 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 55 | -------------------------------------------------------------------------------- /src/core/model/xmmModelParameters.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelParameters.hpp 3 | * 4 | * Model Parameters for each class (label) 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmModelParameters_h 34 | #define xmmModelParameters_h 35 | 36 | #include "../common/xmmAttribute.hpp" 37 | #include "../common/xmmJson.hpp" 38 | 39 | namespace xmm { 40 | /** 41 | @ingroup Model 42 | @brief Class-specific Model Parameters. 43 | @details this structure is then encapsulated in a Configuration object that 44 | propagates default parameters 45 | or class-specific parameters to the SingleClassModel. 46 | */ 47 | template 48 | class ClassParameters : public Writable { 49 | public: 50 | /** 51 | @brief Default Constructor 52 | */ 53 | ClassParameters() : changed(true) {} 54 | 55 | /** 56 | @brief Copy Constructor 57 | @param src Source Object 58 | */ 59 | ClassParameters(ClassParameters const& src) : changed(true) {} 60 | 61 | /** 62 | @brief Constructor from Json Structure 63 | @param root Json value 64 | */ 65 | explicit ClassParameters(Json::Value const& root) : changed(true) {} 66 | 67 | /** 68 | @brief Assignment 69 | @param src Source Object 70 | */ 71 | ClassParameters& operator=(ClassParameters const& src) { changed = true; } 72 | 73 | /** 74 | @brief specifies if parameters have changed (model is invalid) 75 | */ 76 | bool changed; 77 | }; 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/LICENSE: -------------------------------------------------------------------------------- 1 | The JsonCpp library's source code, including accompanying documentation, 2 | tests and demonstration applications, are licensed under the following 3 | conditions... 4 | 5 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all 6 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 7 | this software is released into the Public Domain. 8 | 9 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 10 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 11 | released under the terms of the MIT License (see below). 12 | 13 | In jurisdictions which recognize Public Domain property, the user of this 14 | software may choose to accept it either as 1) Public Domain, 2) under the 15 | conditions of the MIT License (see below), or 3) under the terms of dual 16 | Public Domain/MIT License conditions described here, as they choose. 17 | 18 | The MIT License is about as close to Public Domain as a license can get, and is 19 | described in clear, concise terms at: 20 | 21 | http://en.wikipedia.org/wiki/MIT_License 22 | 23 | The full text of the MIT License follows: 24 | 25 | ======================================================================== 26 | Copyright (c) 2007-2010 Baptiste Lepilleur 27 | 28 | Permission is hereby granted, free of charge, to any person 29 | obtaining a copy of this software and associated documentation 30 | files (the "Software"), to deal in the Software without 31 | restriction, including without limitation the rights to use, copy, 32 | modify, merge, publish, distribute, sublicense, and/or sell copies 33 | of the Software, and to permit persons to whom the Software is 34 | furnished to do so, subject to the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be 37 | included in all copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 42 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 43 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 44 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 45 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | SOFTWARE. 47 | ======================================================================== 48 | (END LICENSE TEXT) 49 | 50 | The MIT license is compatible with both the GPL and commercial 51 | software, affording one all of the rights of Public Domain with the 52 | minor nuisance of being required to keep the above copyright notice 53 | and license text in the source code. Note also that by accepting the 54 | Public Domain "license" you can re-license your copy using whatever 55 | license you like. 56 | -------------------------------------------------------------------------------- /src/models/hmm/xmmHmmResults.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmHmmResults.hpp 3 | * 4 | * Results of Hidden Markov Models for a single class 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmHmmResults_hpp 34 | #define xmmHmmResults_hpp 35 | 36 | #include "../../core/model/xmmModelResults.hpp" 37 | 38 | namespace xmm { 39 | /** 40 | @ingroup HMM 41 | @brief Results of Hidden Markov Models for a single class 42 | */ 43 | template <> 44 | struct ClassResults { 45 | /** 46 | @brief Instantaneous likelihood 47 | */ 48 | double instant_likelihood; 49 | 50 | /** 51 | @brief Cumulative log-likelihood computed on a sliding window 52 | */ 53 | double log_likelihood; 54 | 55 | /** 56 | @brief Predicted Output parameter vector (only used in regression mode) 57 | @warning this variable only allocated if the model is bimodal 58 | */ 59 | std::vector output_values; 60 | 61 | /** 62 | @brief Predicted Output covariance associated with the generated parameter 63 | vector (only used in regression mode) 64 | @warning this variable only allocated if the model is bimodal 65 | */ 66 | std::vector output_covariance; 67 | 68 | /** 69 | @brief Estimated time progression. 70 | @details The time progression is computed as the centroid of the state 71 | probability distribution estimated by the forward algorithm 72 | */ 73 | double progress; 74 | 75 | /** 76 | @brief Likelihood to exit the gesture on the next time step 77 | */ 78 | double exit_likelihood; 79 | 80 | /** 81 | @brief Likelihood to exit the gesture on the next time step (normalized -/- 82 | total likelihood) 83 | */ 84 | double exit_ratio; 85 | 86 | /** 87 | @brief Index of the likeliest state 88 | */ 89 | unsigned int likeliest_state; 90 | }; 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/src/json_tool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 7 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 8 | 9 | /* This header provides common string manipulation support, such as UTF-8, 10 | * portable conversion from/to string... 11 | * 12 | * It is an internal header that must not be exposed. 13 | */ 14 | 15 | namespace Json { 16 | 17 | /// Converts a unicode code-point to UTF-8. 18 | static inline std::string codePointToUTF8(unsigned int cp) { 19 | std::string result; 20 | 21 | // based on description from http://en.wikipedia.org/wiki/UTF-8 22 | 23 | if (cp <= 0x7f) { 24 | result.resize(1); 25 | result[0] = static_cast(cp); 26 | } else if (cp <= 0x7FF) { 27 | result.resize(2); 28 | result[1] = static_cast(0x80 | (0x3f & cp)); 29 | result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); 30 | } else if (cp <= 0xFFFF) { 31 | result.resize(3); 32 | result[2] = static_cast(0x80 | (0x3f & cp)); 33 | result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); 34 | result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); 35 | } else if (cp <= 0x10FFFF) { 36 | result.resize(4); 37 | result[3] = static_cast(0x80 | (0x3f & cp)); 38 | result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); 39 | result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); 40 | result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); 41 | } 42 | 43 | return result; 44 | } 45 | 46 | /// Returns true if ch is a control character (in range [1,31]). 47 | static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 48 | 49 | enum { 50 | /// Constant that specify the size of the buffer that must be passed to 51 | /// uintToString. 52 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 53 | }; 54 | 55 | // Defines a char buffer for use with uintToString(). 56 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 57 | 58 | /** Converts an unsigned integer to string. 59 | * @param value Unsigned interger to convert to string 60 | * @param current Input/Output string buffer. 61 | * Must have at least uintToStringBufferSize chars free. 62 | */ 63 | static inline void uintToString(LargestUInt value, char*& current) { 64 | *--current = 0; 65 | do { 66 | *--current = static_cast(value % 10U + static_cast('0')); 67 | value /= 10; 68 | } while (value != 0); 69 | } 70 | 71 | /** Change ',' to '.' everywhere in buffer. 72 | * 73 | * We had a sophisticated way, but it did not work in WinCE. 74 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 75 | */ 76 | static inline void fixNumericLocale(char* begin, char* end) { 77 | while (begin < end) { 78 | if (*begin == ',') { 79 | *begin = '.'; 80 | } 81 | ++begin; 82 | } 83 | } 84 | 85 | } // namespace Json { 86 | 87 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 88 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | XMM — Probabilistic Models for Continuous Motion Recognition and Mapping 2 | =========================================== 3 | 4 | XMM is a portable, cross-platform C++ library that implements Gaussian Mixture Models and Hidden Markov Models for recognition and regression. The XMM library was developed for movement interaction in creative applications and implements an interactive machine learning workflow with fast training and continuous, real-time inference. 5 | 6 | ### Major Update! [Sept. 2016] 7 | 8 | We just updated XMM to the newest API version! 9 | 10 | This version is not compatible with the initial API, which is still available on a separate branch: https://github.com/Ircam-RnD/xmm/tree/v0-historic-api. 11 | 12 | ### Contact 13 | 14 | Jules Francoise: 15 | 16 | ### author 17 | 18 | This code has been initially authored by Jules Francoise during his PhD thesis, supervised by Frederic Bevilacqua, in the Sound Music Movement Interaction team of the STMS Lab - IRCAM - CNRS - UPMC (2011-2015). 19 | 20 | ### Copyright 21 | 22 | Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 23 | 24 | ### Licence 25 | 26 | This project is released under the GPLv3 license. 27 | For commercial applications, a proprietary license is available upon request to Frederick Rousseau . 28 | 29 | XMM is free software: you can redistribute it and/or modify 30 | it under the terms of the GNU General Public License as published by 31 | the Free Software Foundation, either version 3 of the License, or 32 | (at your option) any later version. 33 | 34 | XMM is distributed in the hope that it will be useful, 35 | but WITHOUT ANY WARRANTY; without even the implied warranty of 36 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37 | GNU General Public License for more details. 38 | 39 | You should have received a copy of the GNU General Public License 40 | along with XMM. If not, see . 41 | 42 | ### Citing this work 43 | 44 | If you use this code for research purposes, please cite one of the following publications: 45 | 46 | - J. Francoise, N. Schnell, R. Borghesi, and F. Bevilacqua, Probabilistic Models for Designing Motion and Sound Relationships. In Proceedings of the 2014 International Conference on New Interfaces for Musical Expression, NIME’14, London, UK, 2014. 47 | - J. Francoise, N. Schnell, and F. Bevilacqua, A Multimodal Probabilistic Model for Gesture-based Control of Sound Synthesis. In Proceedings of the 21st ACM international conference on Multimedia (MM’13), Barcelona, Spain, 2013. 48 | 49 | ### Dependencies 50 | 51 | The library depends on jsoncpp for JSON file I/O. The library is distributed with this softare. The units tests rely on the Catch testing framework 52 | 53 | ## Documentation 54 | 55 | The full documentation is available on Github Pages: http://ircam-ismm.github.io/xmm/ 56 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) 2 | 3 | # Project declaration 4 | project(xmm) 5 | 6 | include(CheckCXXCompilerFlag) 7 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 8 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 9 | if(COMPILER_SUPPORTS_CXX11) 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 11 | elseif(COMPILER_SUPPORTS_CXX0X) 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 13 | else() 14 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 15 | endif() 16 | 17 | # The version number. 18 | set (xmm_VERSION_MAJOR 0) 19 | set (xmm_VERSION_MINOR 1) 20 | 21 | # Compiler Flags 22 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fPIC") 23 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -DJSON_DEBUG -fPIC") 24 | if (NOT CMAKE_BUILD_TYPE) 25 | message(STATUS "No build type selected, default to Release") 26 | set(CMAKE_BUILD_TYPE "Release") 27 | endif() 28 | 29 | # Include JSON 30 | include_directories(./dependencies/jsoncpp/include) 31 | include_directories(./dependencies/jsoncpp/src) 32 | 33 | # Declare library 34 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) 35 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/core/common) 36 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/core/distributions) 37 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/core/model) 38 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/core/trainingset) 39 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/models/gmm) 40 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/models/hmm) 41 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/models/kmeans) 42 | 43 | set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}) 44 | add_definitions(-DUSE_PTHREAD) 45 | 46 | file( 47 | GLOB_RECURSE 48 | xmm_source_files 49 | src/* 50 | ) 51 | 52 | file( 53 | GLOB_RECURSE 54 | jsoncpp_source_files 55 | dependencies/jsoncpp/src/* 56 | ) 57 | 58 | add_library( 59 | xmm 60 | STATIC 61 | ${xmm_source_files} ${jsoncpp_source_files} 62 | ) 63 | 64 | # Declare Unit tests 65 | set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE}) 66 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dependencies/catch) 67 | 68 | # message(${LINK_DIRECTORIES}) 69 | 70 | file( 71 | GLOB_RECURSE 72 | xmm_test_files 73 | test/* 74 | ) 75 | 76 | add_executable( 77 | tests 78 | EXCLUDE_FROM_ALL 79 | ${xmm_test_files} 80 | ) 81 | 82 | # linking configuration 83 | target_link_libraries( 84 | tests 85 | xmm 86 | ) 87 | 88 | set_target_properties(tests PROPERTIES OUTPUT_NAME xmm_testing) 89 | add_custom_command(TARGET tests POST_BUILD COMMAND ${EXECUTABLE_OUTPUT_PATH}/xmm_testing) 90 | 91 | # add a target to generate API documentation with Doxygen 92 | find_package(Doxygen) 93 | 94 | find_program(DOTPATH dot) 95 | if(${DOTPATH} STREQUAL "DOTPATH-NOTFOUND") 96 | set(HAS_DOT "") 97 | else(${DOTPATH} STREQUAL "DOTPATH-NOTFOUND") 98 | set(HAS_DOT "-dot") 99 | endif(${DOTPATH} STREQUAL "DOTPATH-NOTFOUND") 100 | 101 | if(DOXYGEN_FOUND) 102 | add_custom_target(doc 103 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile${HAS_DOT} 104 | DEPENDS ${tracking_source_files} 105 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ 106 | COMMENT "Generating API documentation with Doxygen" VERBATIM) 107 | else(DOXYGEN_FOUND) 108 | message(STATUS "Doxygen not found, doc will not be included in the Makefile") 109 | endif(DOXYGEN_FOUND) 110 | 111 | set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/doc/html") 112 | -------------------------------------------------------------------------------- /src/core/common/xmmEvents.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmEvents.hpp 3 | * 4 | * Template classes for Event generators 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmEvents_h 34 | #define xmmEvents_h 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | namespace xmm { 41 | /** 42 | @ingroup Common 43 | @brief Generator class for a specific type of events 44 | @tparam EventType Type of Events that can be sent 45 | */ 46 | template 47 | class EventGenerator { 48 | public: 49 | typedef std::function EventCallBack; 50 | 51 | /** 52 | @brief Default constructor 53 | */ 54 | EventGenerator() {} 55 | 56 | /** 57 | @brief Destructor 58 | @details Also notifies all listeners that this generators is deleted 59 | */ 60 | virtual ~EventGenerator() {} 61 | 62 | /** 63 | @brief Adds a listener object to be notified when events are sent 64 | @param owner Pointer to the listener object 65 | @param listenerMethod Method to be called in the target class 66 | @tparam U type of the target object 67 | @tparam args callback arguments 68 | @tparam ListenerClass Listener Class 69 | */ 70 | template 71 | void addListener(U* owner, void (ListenerClass::*listenerMethod)(args)) { 72 | callbacks_.insert(std::pair( 73 | static_cast(owner), 74 | std::bind(listenerMethod, owner, std::placeholders::_1))); 75 | } 76 | 77 | /** 78 | @brief Removes a listener object 79 | @param owner Pointer to the listener object 80 | @param listenerMethod Method to be called in the target class 81 | @tparam U type of the target object 82 | @tparam args callback arguments 83 | @tparam ListenerClass Listener Class 84 | */ 85 | template 86 | void removeListener(U* owner, void (ListenerClass::*listenerMethod)(args)) { 87 | callbacks_.erase(static_cast(owner)); 88 | } 89 | 90 | /** 91 | @brief Removes all listeners 92 | */ 93 | void removeListeners() { callbacks_.clear(); } 94 | 95 | /** 96 | @brief Propagates the event to all listeners 97 | @param e event 98 | */ 99 | void notifyListeners(EventType& e) const { 100 | for (auto& callback : callbacks_) { 101 | callback.second(e); 102 | } 103 | } 104 | 105 | private: 106 | /** 107 | @brief Set of listener objects 108 | */ 109 | std::map callbacks_; 110 | }; 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/models/kmeans/xmmKMeansParameters.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmKMeansParameters.hpp 3 | * 4 | * Parameters of the K-Means clustering Algorithm 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmKMeansParameters_hpp 34 | #define xmmKMeansParameters_hpp 35 | 36 | #include "../../core/model/xmmModelParameters.hpp" 37 | 38 | namespace xmm { 39 | /** 40 | @defgroup KMeans [Models] K-Means Algorithm 41 | */ 42 | 43 | /** 44 | Dummy structure for template specialization 45 | */ 46 | class KMeans; 47 | 48 | /** 49 | @ingroup KMeans 50 | @brief Parameters specific to each class of a K-Means Algorithm 51 | */ 52 | template <> 53 | class ClassParameters : public Writable { 54 | public: 55 | /** 56 | @brief Default Constructor 57 | */ 58 | ClassParameters(); 59 | 60 | /** 61 | @brief Copy Constructor 62 | @param src Source Object 63 | */ 64 | ClassParameters(ClassParameters const& src); 65 | 66 | /** 67 | @brief Constructor from Json Structure 68 | @param root Json Value 69 | */ 70 | explicit ClassParameters(Json::Value const& root); 71 | 72 | /** 73 | @brief Assignment 74 | @param src Source Object 75 | */ 76 | ClassParameters& operator=(ClassParameters const& src); 77 | 78 | virtual ~ClassParameters() {} 79 | 80 | /** @name Json I/O */ 81 | ///@{ 82 | 83 | /** 84 | @brief Write the object to a JSON Structure 85 | @return Json value containing the object's information 86 | */ 87 | Json::Value toJson() const; 88 | 89 | /** 90 | @brief Read the object from a JSON Structure 91 | @param root JSON value containing the object's information 92 | @throws JsonException if the JSON value has a wrong format 93 | */ 94 | virtual void fromJson(Json::Value const& root); 95 | 96 | ///@} 97 | 98 | /** 99 | @brief specifies if parameters have changed (model is invalid) 100 | */ 101 | bool changed = false; 102 | 103 | /** 104 | @brief Number of Gaussian Mixture Components 105 | */ 106 | Attribute clusters; 107 | 108 | /** 109 | @brief Maximum number of iterations of the training update 110 | */ 111 | Attribute max_iterations; 112 | 113 | /** 114 | @brief threshold (as relative distance between cluster) required to define 115 | convergence 116 | */ 117 | Attribute relative_distance_threshold; 118 | 119 | protected: 120 | /** 121 | @brief notification function called when a member attribute is changed 122 | */ 123 | virtual void onAttributeChange(AttributeBase* attr_pointer); 124 | }; 125 | } 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /src/models/gmm/xmmGmmParameters.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmGmmParameters.hpp 3 | * 4 | * Parameters of Gaussian Mixture Models 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmGMMParameters_hpp 34 | #define xmmGMMParameters_hpp 35 | 36 | #include "../../core/distributions/xmmGaussianDistribution.hpp" 37 | #include "../../core/model/xmmModelParameters.hpp" 38 | 39 | namespace xmm { 40 | /** 41 | @defgroup GMM [Models] Gaussian Mixture Models 42 | */ 43 | 44 | /** 45 | Dummy structure for template specialization 46 | */ 47 | class GMM; 48 | 49 | /** 50 | @ingroup GMM 51 | @brief Parameters specific to each class of a Gaussian Mixture Model 52 | */ 53 | template <> 54 | class ClassParameters : public Writable { 55 | public: 56 | /** 57 | @brief Default Constructor 58 | */ 59 | ClassParameters(); 60 | 61 | /** 62 | @brief Copy Constructor 63 | @param src Source Object 64 | */ 65 | ClassParameters(ClassParameters const& src); 66 | 67 | /** 68 | @brief Constructor from Json Structure 69 | @param root Json Value 70 | */ 71 | explicit ClassParameters(Json::Value const& root); 72 | 73 | /** 74 | @brief Assignment 75 | @param src Source Object 76 | */ 77 | ClassParameters& operator=(ClassParameters const& src); 78 | 79 | /** @name Json I/O */ 80 | ///@{ 81 | 82 | /** 83 | @brief Write the object to a JSON Structure 84 | @return Json value containing the object's information 85 | */ 86 | Json::Value toJson() const; 87 | 88 | /** 89 | @brief Read the object from a JSON Structure 90 | @param root JSON value containing the object's information 91 | @throws JsonException if the JSON value has a wrong format 92 | */ 93 | virtual void fromJson(Json::Value const& root); 94 | 95 | ///@} 96 | 97 | /** 98 | @brief specifies if parameters have changed (model is invalid) 99 | */ 100 | bool changed = false; 101 | 102 | /** 103 | @brief Number of Gaussian Mixture Components 104 | */ 105 | Attribute gaussians; 106 | 107 | /** 108 | @brief Offset Added to the diagonal of covariance matrices for convergence 109 | (Relative to Data Variance) 110 | */ 111 | Attribute relative_regularization; 112 | 113 | /** 114 | @brief Offset Added to the diagonal of covariance matrices for convergence 115 | (minimum value) 116 | */ 117 | Attribute absolute_regularization; 118 | 119 | /** 120 | @brief Covariance Mode 121 | */ 122 | Attribute covariance_mode; 123 | 124 | protected: 125 | /** 126 | @brief notification function called when a member attribute is changed 127 | */ 128 | virtual void onAttributeChange(AttributeBase* attr_pointer); 129 | }; 130 | } 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /src/core/model/xmmModelResults.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelResults.hpp 3 | * 4 | * Results structures for probabilistic models 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmModelResults_h 34 | #define xmmModelResults_h 35 | 36 | #include 37 | #include 38 | 39 | namespace xmm { 40 | /** 41 | @ingroup Model 42 | @brief Class-specific Results of the filtering/inference process. 43 | @details The default results contain both likelihoods for recognition 44 | and vectors for the results of a regression 45 | */ 46 | template 47 | struct ClassResults { 48 | /** 49 | @brief Instantaneous likelihood 50 | */ 51 | double instant_likelihood; 52 | 53 | /** 54 | @brief Cumulative log-likelihood computed on a sliding window 55 | */ 56 | double log_likelihood; 57 | 58 | /** 59 | @brief Predicted Output parameter vector (only used in regression mode) 60 | @warning this variable is not allocated if the model is not bimodal 61 | */ 62 | std::vector output_values; 63 | 64 | /** 65 | @brief Predicted Output variance associated with the generated parameter 66 | vector (only used in regression mode) 67 | @warning this variable is not allocated if the model is not bimodal 68 | */ 69 | std::vector output_covariance; 70 | }; 71 | 72 | /** 73 | @ingroup Model 74 | @brief Results of the filtering/inference process (for a Model with multiple 75 | classes). 76 | @details The default results contain both likelihoods for recognition 77 | and vectors for the results of a regression 78 | */ 79 | template 80 | struct Results { 81 | /** 82 | @brief Instantaneous likelihood of each class 83 | */ 84 | std::vector instant_likelihoods; 85 | 86 | /** 87 | @brief Normalized instantaneous likelihood of each class 88 | */ 89 | std::vector instant_normalized_likelihoods; 90 | 91 | /** 92 | @brief Smoothed likelihood of each class 93 | */ 94 | std::vector smoothed_likelihoods; 95 | 96 | /** 97 | @brief Normalized smoothed likelihood of each class 98 | */ 99 | std::vector smoothed_normalized_likelihoods; 100 | 101 | /** 102 | @brief Cumulative smoothed log-likelihood of each class 103 | */ 104 | std::vector smoothed_log_likelihoods; 105 | 106 | /** 107 | @brief Label of the likeliest class 108 | */ 109 | std::string likeliest; 110 | 111 | /** 112 | @brief Output values estimated by regression 113 | @warning this variable is not allocated if the Model is not bimodal 114 | */ 115 | std::vector output_values; 116 | 117 | /** 118 | @brief Output variance over the values estimated by regression 119 | @warning this variable is not allocated if the Model is not bimodal 120 | */ 121 | std::vector output_covariance; 122 | }; 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/models/kmeans/xmmKMeansParameters.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmKMeansParameters.hpp 3 | * 4 | * Parameters of the K-Means clustering Algorithm 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmKMeansParameters.hpp" 34 | 35 | xmm::ClassParameters::ClassParameters() 36 | : changed(true), 37 | clusters(1, 1), 38 | max_iterations(50, 1), 39 | relative_distance_threshold(1e-20, 0) { 40 | clusters.onAttributeChange( 41 | this, &xmm::ClassParameters::onAttributeChange); 42 | max_iterations.onAttributeChange( 43 | this, &xmm::ClassParameters::onAttributeChange); 44 | relative_distance_threshold.onAttributeChange( 45 | this, &xmm::ClassParameters::onAttributeChange); 46 | } 47 | 48 | xmm::ClassParameters::ClassParameters( 49 | ClassParameters const& src) 50 | : changed(true), 51 | clusters(src.clusters), 52 | max_iterations(src.max_iterations), 53 | relative_distance_threshold(src.relative_distance_threshold) { 54 | clusters.onAttributeChange( 55 | this, &xmm::ClassParameters::onAttributeChange); 56 | max_iterations.onAttributeChange( 57 | this, &xmm::ClassParameters::onAttributeChange); 58 | relative_distance_threshold.onAttributeChange( 59 | this, &xmm::ClassParameters::onAttributeChange); 60 | } 61 | 62 | xmm::ClassParameters::ClassParameters(Json::Value const& root) 63 | : ClassParameters() { 64 | clusters.set(root["clusters"].asInt()); 65 | max_iterations.set(root["max_iterations"].asInt()); 66 | relative_distance_threshold.set( 67 | root["relative_distance_threshold"].asFloat()); 68 | } 69 | 70 | xmm::ClassParameters& xmm::ClassParameters::operator=( 71 | ClassParameters const& src) { 72 | if (this != &src) { 73 | changed = true; 74 | clusters = src.clusters; 75 | max_iterations = src.max_iterations; 76 | relative_distance_threshold = src.relative_distance_threshold; 77 | clusters.onAttributeChange( 78 | this, &xmm::ClassParameters::onAttributeChange); 79 | max_iterations.onAttributeChange( 80 | this, &xmm::ClassParameters::onAttributeChange); 81 | relative_distance_threshold.onAttributeChange( 82 | this, &xmm::ClassParameters::onAttributeChange); 83 | } 84 | return *this; 85 | } 86 | 87 | Json::Value xmm::ClassParameters::toJson() const { 88 | Json::Value root; 89 | root["clusters"] = static_cast(clusters.get()); 90 | root["max_iterations"] = static_cast(max_iterations.get()); 91 | root["relative_distance_threshold"] = relative_distance_threshold.get(); 92 | return root; 93 | } 94 | 95 | void xmm::ClassParameters::fromJson(Json::Value const& root) { 96 | try { 97 | ClassParameters tmp(root); 98 | *this = tmp; 99 | } catch (JsonException& e) { 100 | throw e; 101 | } 102 | } 103 | 104 | void xmm::ClassParameters::onAttributeChange( 105 | AttributeBase* attr_pointer) { 106 | changed = true; 107 | attr_pointer->changed = false; 108 | } 109 | -------------------------------------------------------------------------------- /src/core/common/xmmAttribute.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmAttribute.hpp 3 | * 4 | * Generic Attributes 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmAttribute.hpp" 34 | #include 35 | 36 | template <> 37 | void xmm::checkLimits(bool const& value, bool const& limit_min, 38 | bool const& limit_max) {} 39 | 40 | template <> 41 | void xmm::checkLimits(unsigned char const& value, 42 | unsigned char const& limit_min, 43 | unsigned char const& limit_max) { 44 | if (value < limit_min || value > limit_max) 45 | throw std::domain_error("Attribute value out of range. Range: [" + 46 | std::to_string(limit_min) + " ; " + 47 | std::to_string(limit_max) + "]"); 48 | } 49 | 50 | template <> 51 | void xmm::checkLimits(char const& value, char const& limit_min, 52 | char const& limit_max) { 53 | if (value < limit_min || value > limit_max) 54 | throw std::domain_error("Attribute value out of range. Range: [" + 55 | std::to_string(limit_min) + " ; " + 56 | std::to_string(limit_max) + "]"); 57 | } 58 | 59 | template <> 60 | void xmm::checkLimits(unsigned int const& value, 61 | unsigned int const& limit_min, 62 | unsigned int const& limit_max) { 63 | if (value < limit_min || value > limit_max) 64 | throw std::domain_error("Attribute value out of range. Range: [" + 65 | std::to_string(limit_min) + " ; " + 66 | std::to_string(limit_max) + "]"); 67 | } 68 | 69 | template <> 70 | void xmm::checkLimits(int const& value, int const& limit_min, 71 | int const& limit_max) { 72 | if (value < limit_min || value > limit_max) 73 | throw std::domain_error("Attribute value out of range. Range: [" + 74 | std::to_string(limit_min) + " ; " + 75 | std::to_string(limit_max) + "]"); 76 | } 77 | 78 | template <> 79 | void xmm::checkLimits(long const& value, long const& limit_min, 80 | long const& limit_max) { 81 | if (value < limit_min || value > limit_max) 82 | throw std::domain_error("Attribute value out of range. Range: [" + 83 | std::to_string(limit_min) + " ; " + 84 | std::to_string(limit_max) + "]"); 85 | } 86 | 87 | template <> 88 | void xmm::checkLimits(float const& value, float const& limit_min, 89 | float const& limit_max) { 90 | if (value < limit_min || value > limit_max) 91 | throw std::domain_error("Attribute value out of range. Range: [" + 92 | std::to_string(limit_min) + " ; " + 93 | std::to_string(limit_max) + "]"); 94 | } 95 | 96 | template <> 97 | void xmm::checkLimits(double const& value, double const& limit_min, 98 | double const& limit_max) { 99 | if (value < limit_min || value > limit_max) 100 | throw std::domain_error("Attribute value out of range. Range: [" + 101 | std::to_string(limit_min) + " ; " + 102 | std::to_string(limit_max) + "]"); 103 | } 104 | 105 | template <> 106 | void xmm::checkLimits(std::string const& value, 107 | std::string const& limit_min, 108 | std::string const& limit_max) {} 109 | -------------------------------------------------------------------------------- /src/core/common/xmmJson.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmJson.cpp 3 | * 4 | * Set of utility functions for JSON I/O 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmJson.hpp" 34 | 35 | template <> 36 | void xmm::json2array(Json::Value const& root, float* a, unsigned int n) { 37 | if (!root.isArray()) 38 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 39 | if (root.size() != n) 40 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 41 | unsigned int i = 0; 42 | for (auto it : root) { 43 | a[i++] = it.asFloat(); 44 | } 45 | } 46 | 47 | template <> 48 | void xmm::json2array(Json::Value const& root, double* a, unsigned int n) { 49 | if (!root.isArray()) 50 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 51 | if (root.size() != n) 52 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 53 | unsigned int i = 0; 54 | for (auto it : root) { 55 | a[i++] = it.asDouble(); 56 | } 57 | } 58 | 59 | template <> 60 | void xmm::json2array(Json::Value const& root, bool* a, unsigned int n) { 61 | if (!root.isArray()) 62 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 63 | if (root.size() != n) 64 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 65 | unsigned int i = 0; 66 | for (auto it : root) { 67 | a[i++] = it.asBool(); 68 | } 69 | } 70 | 71 | template <> 72 | void xmm::json2array(Json::Value const& root, std::string* a, unsigned int n) { 73 | if (!root.isArray()) 74 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 75 | if (root.size() != n) 76 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 77 | unsigned int i = 0; 78 | for (auto it : root) { 79 | a[i++] = it.asString(); 80 | } 81 | } 82 | 83 | template <> 84 | void xmm::json2vector(Json::Value const& root, std::vector& a, 85 | unsigned int n) { 86 | if (n == 0) return; 87 | if (!root.isArray()) 88 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 89 | if (root.size() != n) 90 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 91 | unsigned int i = 0; 92 | for (auto it : root) { 93 | a[i++] = it.asFloat(); 94 | } 95 | } 96 | 97 | template <> 98 | void xmm::json2vector(Json::Value const& root, std::vector& a, 99 | unsigned int n) { 100 | if (n == 0) return; 101 | if (!root.isArray()) 102 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 103 | if (root.size() != n) 104 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 105 | unsigned int i = 0; 106 | for (auto it : root) { 107 | a[i++] = it.asDouble(); 108 | } 109 | } 110 | 111 | template <> 112 | void xmm::json2vector(Json::Value const& root, std::vector& a, 113 | unsigned int n) { 114 | if (n == 0) return; 115 | if (!root.isArray()) 116 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 117 | if (root.size() != n) 118 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 119 | unsigned int i = 0; 120 | for (auto it : root) { 121 | a[i++] = it.asBool(); 122 | } 123 | } 124 | 125 | template <> 126 | void xmm::json2vector(Json::Value const& root, std::vector& a, 127 | unsigned int n) { 128 | if (n == 0) return; 129 | if (!root.isArray()) 130 | throw JsonException(JsonException::JsonErrorType::JsonTypeError); 131 | if (root.size() != n) 132 | throw JsonException(JsonException::JsonErrorType::JsonValueError); 133 | unsigned int i = 0; 134 | for (auto it : root) { 135 | a[i++] = it.asString(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/include/config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_CONFIG_H_INCLUDED 7 | #define JSON_CONFIG_H_INCLUDED 8 | 9 | /// If defined, indicates that json library is embedded in CppTL library. 10 | //# define JSON_IN_CPPTL 1 11 | 12 | /// If defined, indicates that json may leverage CppTL library 13 | //# define JSON_USE_CPPTL 1 14 | /// If defined, indicates that cpptl vector based map should be used instead of 15 | /// std::map 16 | /// as Value container. 17 | //# define JSON_USE_CPPTL_SMALLMAP 1 18 | 19 | // If non-zero, the library uses exceptions to report bad input instead of C 20 | // assertion macros. The default is to use exceptions. 21 | #ifndef JSON_USE_EXCEPTION 22 | #define JSON_USE_EXCEPTION 1 23 | #endif 24 | 25 | /// If defined, indicates that the source file is amalgated 26 | /// to prevent private header inclusion. 27 | /// Remarks: it is automatically defined in the generated amalgated header. 28 | // #define JSON_IS_AMALGAMATION 29 | 30 | #ifdef JSON_IN_CPPTL 31 | #include 32 | #ifndef JSON_USE_CPPTL 33 | #define JSON_USE_CPPTL 1 34 | #endif 35 | #endif 36 | 37 | #ifdef JSON_IN_CPPTL 38 | #define JSON_API CPPTL_API 39 | #elif defined(JSON_DLL_BUILD) 40 | #if defined(_MSC_VER) 41 | #define JSON_API __declspec(dllexport) 42 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 43 | #endif // if defined(_MSC_VER) 44 | #elif defined(JSON_DLL) 45 | #if defined(_MSC_VER) 46 | #define JSON_API __declspec(dllimport) 47 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 48 | #endif // if defined(_MSC_VER) 49 | #endif // ifdef JSON_IN_CPPTL 50 | #if !defined(JSON_API) 51 | #define JSON_API 52 | #endif 53 | 54 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 55 | // integer 56 | // Storages, and 64 bits integer support is disabled. 57 | // #define JSON_NO_INT64 1 58 | 59 | #if defined(_MSC_VER) // MSVC 60 | # if _MSC_VER <= 1200 // MSVC 6 61 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 62 | // (no conversion from unsigned __int64). 63 | # define JSON_USE_INT64_DOUBLE_CONVERSION 1 64 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 65 | // characters in the debug information) 66 | // All projects I've ever seen with VS6 were using this globally (not bothering 67 | // with pragma push/pop). 68 | # pragma warning(disable : 4786) 69 | # endif // MSVC 6 70 | 71 | # if _MSC_VER >= 1500 // MSVC 2008 72 | /// Indicates that the following function is deprecated. 73 | # define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 74 | # endif 75 | 76 | #endif // defined(_MSC_VER) 77 | 78 | 79 | #ifndef JSON_HAS_RVALUE_REFERENCES 80 | 81 | #if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 82 | #define JSON_HAS_RVALUE_REFERENCES 1 83 | #endif // MSVC >= 2010 84 | 85 | #ifdef __clang__ 86 | #if __has_feature(cxx_rvalue_references) 87 | #define JSON_HAS_RVALUE_REFERENCES 1 88 | #endif // has_feature 89 | 90 | #elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) 91 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) 92 | #define JSON_HAS_RVALUE_REFERENCES 1 93 | #endif // GXX_EXPERIMENTAL 94 | 95 | #endif // __clang__ || __GNUC__ 96 | 97 | #endif // not defined JSON_HAS_RVALUE_REFERENCES 98 | 99 | #ifndef JSON_HAS_RVALUE_REFERENCES 100 | #define JSON_HAS_RVALUE_REFERENCES 0 101 | #endif 102 | 103 | #ifdef __clang__ 104 | #elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) 105 | # if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 106 | # define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) 107 | # elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 108 | # define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 109 | # endif // GNUC version 110 | #endif // __clang__ || __GNUC__ 111 | 112 | #if !defined(JSONCPP_DEPRECATED) 113 | #define JSONCPP_DEPRECATED(message) 114 | #endif // if !defined(JSONCPP_DEPRECATED) 115 | 116 | namespace Json { 117 | typedef int Int; 118 | typedef unsigned int UInt; 119 | #if defined(JSON_NO_INT64) 120 | typedef int LargestInt; 121 | typedef unsigned int LargestUInt; 122 | #undef JSON_HAS_INT64 123 | #else // if defined(JSON_NO_INT64) 124 | // For Microsoft Visual use specific types as long long is not supported 125 | #if defined(_MSC_VER) // Microsoft Visual Studio 126 | typedef __int64 Int64; 127 | typedef unsigned __int64 UInt64; 128 | #else // if defined(_MSC_VER) // Other platforms, use long long 129 | typedef long long int Int64; 130 | typedef unsigned long long int UInt64; 131 | #endif // if defined(_MSC_VER) 132 | typedef Int64 LargestInt; 133 | typedef UInt64 LargestUInt; 134 | #define JSON_HAS_INT64 135 | #endif // if defined(JSON_NO_INT64) 136 | } // end namespace Json 137 | 138 | #endif // JSON_CONFIG_H_INCLUDED 139 | -------------------------------------------------------------------------------- /src/core/model/xmmModelSharedParameters.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelSharedParameters.hpp 3 | * 4 | * Shared Parameters class 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmModelSharedParameters_h 34 | #define xmmModelSharedParameters_h 35 | 36 | #include "../common/xmmEvents.hpp" 37 | #include "../trainingset/xmmTrainingSet.hpp" 38 | #include 39 | 40 | namespace xmm { 41 | /** 42 | @defgroup Model [Core] Probabilistic Models 43 | */ 44 | 45 | /** 46 | @ingroup Model 47 | @brief Shared Parameters for models with multiple classes. 48 | @details This structure is shared by pointer between the class-specific models 49 | to avoid 50 | data duplication and ensures that all class-specific models share the same 51 | common attributes. 52 | */ 53 | class SharedParameters : public Writable { 54 | public: 55 | template 56 | friend class Model; 57 | friend class SingleClassProbabilisticModel; 58 | friend class SingleClassGMM; 59 | friend class SingleClassHMM; 60 | friend class HierarchicalHMM; 61 | friend class GMM; 62 | 63 | /** 64 | @brief Default Constructor 65 | */ 66 | SharedParameters(); 67 | 68 | /** 69 | @brief Copy Constructor 70 | @param src Source Object 71 | */ 72 | SharedParameters(SharedParameters const& src); 73 | 74 | /** 75 | @brief Constructor from Json Structure 76 | @param root Json Value 77 | */ 78 | explicit SharedParameters(Json::Value const& root); 79 | 80 | /** 81 | @brief Assignment 82 | @param src Source Object 83 | */ 84 | SharedParameters& operator=(SharedParameters const& src); 85 | 86 | /** @name Json I/O */ 87 | ///@{ 88 | 89 | /** 90 | @brief Write the object to a JSON Structure 91 | @return Json value containing the object's information 92 | */ 93 | virtual Json::Value toJson() const; 94 | 95 | /** 96 | @brief Read the object from a JSON Structure 97 | @param root JSON value containing the object's information 98 | @throws JsonException if the JSON value has a wrong format 99 | */ 100 | virtual void fromJson(Json::Value const& root); 101 | 102 | ///@} 103 | 104 | /** 105 | @brief defines if the phrase is bimodal (true) or unimodal (false) 106 | */ 107 | Attribute bimodal; 108 | 109 | /** 110 | @brief total dimension of the training data 111 | */ 112 | Attribute dimension; 113 | 114 | /** 115 | @brief Dimension of the input modality 116 | */ 117 | Attribute dimension_input; 118 | 119 | /** 120 | @brief labels of the columns of input/output data (e.g. descriptor names) 121 | */ 122 | Attribute> column_names; 123 | 124 | /** 125 | @brief Minimum number of iterations of the EM algorithm 126 | */ 127 | Attribute em_algorithm_min_iterations; 128 | 129 | /** 130 | @brief Maximum number of iterations of the EM algorithm. 131 | @details If this value is superior to 132 | minSteps, this criterion is used. Otherwise, only the 133 | em_algorithm_percent_chg criterion applies. 134 | */ 135 | Attribute em_algorithm_max_iterations; 136 | 137 | /** 138 | @brief log-likelihood difference threshold necessary to stop the EM 139 | algorithm. 140 | @details When the percent-change in likelihood of the training data given 141 | the 142 | estimated parameters gets under this threshold, the EM algorithm is 143 | stopped. 144 | */ 145 | Attribute em_algorithm_percent_chg; 146 | 147 | /** 148 | @brief Size of the window (in samples) used to compute the likelihoods 149 | */ 150 | Attribute likelihood_window; 151 | 152 | protected: 153 | /** 154 | @brief notification function called when a member attribute is changed 155 | */ 156 | virtual void onAttributeChange(AttributeBase* attr_pointer); 157 | }; 158 | } 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /python/examples/data/hhmm_test_data1.txt: -------------------------------------------------------------------------------- 1 | -0.00229573 -0.0161034 0.00273422 2 | -0.00209583 -0.0138385 0.00237611 3 | -0.00188896 -0.0131124 0.00241048 4 | -0.00190232 -0.0126487 0.00255336 5 | -0.00230856 -0.0128130 0.00272066 6 | -0.00263037 -0.0127942 0.00274633 7 | -0.00291448 -0.0126319 0.00294704 8 | -0.00323296 -0.0130865 0.00324436 9 | -0.00356229 -0.0136605 0.00352499 10 | -0.00477578 -0.0136923 0.00423113 11 | -0.00673026 -0.0136688 0.00538045 12 | -0.00986695 -0.0133379 0.00709194 13 | -0.0140573 -0.0130442 0.00873355 14 | -0.0198976 -0.0126503 0.0101524 15 | -0.0257379 -0.0122564 0.0115713 16 | -0.0344662 -0.0140648 0.0122861 17 | -0.0433411 -0.0159131 0.0129581 18 | -0.0571211 -0.0195968 0.0124505 19 | -0.0735968 -0.0228563 0.0113518 20 | -0.0926917 -0.0259496 0.0103498 21 | -0.111430 -0.0288262 0.00941716 22 | -0.132856 -0.0302379 0.00953173 23 | -0.157717 -0.0319985 0.0104882 24 | -0.182489 -0.0331298 0.0113894 25 | -0.213138 -0.0317954 0.0125260 26 | -0.244391 -0.0289650 0.0146853 27 | -0.274913 -0.0265495 0.0163701 28 | -0.305198 -0.0227768 0.0187433 29 | -0.330191 -0.0186065 0.0226028 30 | -0.353176 -0.0122608 0.0287881 31 | -0.372503 -0.00416417 0.0340082 32 | -0.391644 0.00916755 0.0387263 33 | -0.410786 0.0224993 0.0434445 34 | -0.430884 0.0414529 0.0477572 35 | -0.450467 0.0633359 0.0464063 36 | -0.471611 0.0881113 0.0409210 37 | -0.498378 0.117261 0.0296078 38 | -0.527157 0.149312 0.0128186 39 | -0.552531 0.181345 -0.00490144 40 | -0.578285 0.219732 -0.0235427 41 | -0.591999 0.256563 -0.0451901 42 | -0.597120 0.294503 -0.0665158 43 | -0.597378 0.336212 -0.0856132 44 | -0.591253 0.378440 -0.104139 45 | -0.589375 0.420348 -0.124047 46 | -0.585625 0.465973 -0.145070 47 | -0.585632 0.515632 -0.170047 48 | -0.576988 0.559073 -0.192454 49 | -0.562852 0.603323 -0.210681 50 | -0.539111 0.643393 -0.225786 51 | -0.513298 0.680706 -0.234801 52 | -0.478651 0.716917 -0.238556 53 | -0.433218 0.749664 -0.234285 54 | -0.379708 0.781149 -0.223065 55 | -0.324799 0.813146 -0.213148 56 | -0.267692 0.835939 -0.205293 57 | -0.211392 0.860327 -0.193176 58 | -0.162225 0.881931 -0.182787 59 | -0.110593 0.896715 -0.173410 60 | -0.0629640 0.908543 -0.165607 61 | -0.0111522 0.917694 -0.157785 62 | 0.0423216 0.914433 -0.152050 63 | 0.100682 0.902987 -0.141632 64 | 0.153248 0.894266 -0.132802 65 | 0.203855 0.884031 -0.126645 66 | 0.253416 0.872324 -0.119304 67 | 0.306251 0.855339 -0.112759 68 | 0.354584 0.836072 -0.107397 69 | 0.399900 0.811497 -0.100756 70 | 0.442917 0.782584 -0.0939125 71 | 0.485156 0.747291 -0.0859814 72 | 0.526108 0.714115 -0.0728846 73 | 0.562772 0.674981 -0.0599182 74 | 0.599461 0.633478 -0.0458970 75 | 0.631969 0.594357 -0.0346670 76 | 0.663042 0.556008 -0.0236861 77 | 0.690220 0.514329 -0.0131663 78 | 0.710764 0.474565 -0.00204923 79 | 0.727291 0.429089 0.00617950 80 | 0.743818 0.383613 0.0144082 81 | 0.754134 0.328864 0.0204626 82 | 0.759115 0.268914 0.0254464 83 | 0.763393 0.211472 0.0332799 84 | 0.769087 0.148515 0.0408030 85 | 0.771055 0.0906074 0.0461758 86 | 0.770032 0.0346582 0.0493415 87 | 0.768390 -0.0154230 0.0527214 88 | 0.763564 -0.0645964 0.0554613 89 | 0.753886 -0.113136 0.0573975 90 | 0.741360 -0.162675 0.0588695 91 | 0.722636 -0.215505 0.0622911 92 | 0.701912 -0.267783 0.0671811 93 | 0.678301 -0.314156 0.0721804 94 | 0.657421 -0.355563 0.0776811 95 | 0.631489 -0.390651 0.0863570 96 | 0.603029 -0.428927 0.0947544 97 | 0.574689 -0.459019 0.103232 98 | 0.546541 -0.484255 0.110001 99 | 0.512890 -0.507761 0.114163 100 | 0.477822 -0.525753 0.118635 101 | 0.441048 -0.545753 0.120994 102 | 0.403660 -0.568066 0.123063 103 | 0.364852 -0.591288 0.124809 104 | 0.328696 -0.614685 0.125012 105 | 0.293485 -0.635982 0.124727 106 | 0.261096 -0.653910 0.123851 107 | 0.225830 -0.667130 0.121827 108 | 0.189557 -0.681207 0.118185 109 | 0.153887 -0.695532 0.115074 110 | 0.116624 -0.708528 0.111788 111 | 0.0836440 -0.719727 0.108451 112 | 0.0510510 -0.727032 0.105507 113 | 0.0191004 -0.731689 0.103402 114 | -0.0123679 -0.733302 0.101442 115 | -0.0426651 -0.732235 0.0997344 116 | -0.0729624 -0.731169 0.0980272 117 | -0.101079 -0.727441 0.0967458 118 | -0.127696 -0.720660 0.0949118 119 | -0.154295 -0.711404 0.0928282 120 | -0.182247 -0.700477 0.0906246 121 | -0.207920 -0.686718 0.0880353 122 | -0.234342 -0.670744 0.0850482 123 | -0.254835 -0.655520 0.0828358 124 | -0.273055 -0.637654 0.0803419 125 | -0.289639 -0.617389 0.0776318 126 | -0.304360 -0.595879 0.0746915 127 | -0.318530 -0.571770 0.0714322 128 | -0.330559 -0.548368 0.0680594 129 | -0.339885 -0.523210 0.0642993 130 | -0.346646 -0.496481 0.0604616 131 | -0.351646 -0.471391 0.0569232 132 | -0.354742 -0.441806 0.0525215 133 | -0.355242 -0.411798 0.0483002 134 | -0.353379 -0.382036 0.0438687 135 | -0.350117 -0.353841 0.0400107 136 | -0.345500 -0.327316 0.0362727 137 | -0.338650 -0.299431 0.0316349 138 | -0.329788 -0.271214 0.0271837 139 | -0.320926 -0.242997 0.0227326 140 | -0.311107 -0.216996 0.0184197 141 | -0.297569 -0.189330 0.0142475 142 | -0.284299 -0.164238 0.0104802 143 | -0.270231 -0.140440 0.00733799 144 | -0.254958 -0.115757 0.00439778 145 | -0.239556 -0.0930162 0.00169878 146 | -0.223882 -0.0725396 -0.000779465 147 | -0.208208 -0.0520630 -0.00325771 148 | -0.193625 -0.0357059 -0.00480983 149 | -0.179833 -0.0208569 -0.00624597 150 | -0.166790 -0.00726443 -0.00693205 151 | -0.153202 0.00655957 -0.00757805 152 | -0.139614 0.0203836 -0.00822404 153 | -0.127400 0.0310135 -0.00745938 154 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | # Compiler Flags 4 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fPIC") 5 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -DJSON_DEBUG -fPIC") 6 | if (NOT CMAKE_BUILD_TYPE) 7 | message(STATUS "No build type selected, default to Release") 8 | set(CMAKE_BUILD_TYPE "Release") 9 | endif() 10 | 11 | # C++11 Support 12 | include(CheckCXXCompilerFlag) 13 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 14 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 15 | if(COMPILER_SUPPORTS_CXX11) 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 17 | elseif(COMPILER_SUPPORTS_CXX0X) 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 19 | else() 20 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 21 | endif() 22 | 23 | # Require global XMM project 24 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/_build_tmp) 25 | 26 | # PYTHON STUFF 27 | find_package(SWIG REQUIRED) 28 | include(${SWIG_USE_FILE}) 29 | 30 | execute_process(COMMAND python -c "import sysconfig, os; print(os.path.join(sysconfig.get_config_var('LIBPL'), sysconfig.get_config_var('LIBRARY')))" OUTPUT_VARIABLE PYTHON_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE) 31 | execute_process(COMMAND python -c "import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'))" OUTPUT_VARIABLE PYTHON_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) 32 | find_package(PythonLibs REQUIRED) 33 | message(STATUS "PYTHON_LIBRARY: ${PYTHON_LIBRARY}") 34 | message(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}") 35 | message(STATUS "PYTHON_INCLUDE_PATH: ${PYTHON_INCLUDE_PATH}") 36 | message(STATUS "PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}") 37 | message(STATUS "PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}") 38 | 39 | ## Try to determine the directory of numpy headers 40 | execute_process( COMMAND python -c "from numpy import distutils; path=distutils.misc_util.get_numpy_include_dirs(); print(path[0])" OUTPUT_VARIABLE NUMPY_INCLUDEDIR OUTPUT_STRIP_TRAILING_WHITESPACE ) 41 | if (NOT NUMPY_INCLUDE) 42 | SET(NUMPY_INCLUDE ${NUMPY_INCLUDEDIR} CACHE PATH "Directory for the numpy headers. If it is not set automatically it is determined by python distutils." ) 43 | endif( NOT NUMPY_INCLUDE) 44 | include_directories( ${NUMPY_INCLUDE} ) 45 | if( NOT EXISTS ${NUMPY_INCLUDE}/numpy/arrayobject.h ) 46 | message( FATAL_ERROR "${NUMPY_INCLUDE}/numpy/arrayobject.h header is not found. If it is installed, than check the python flags and numpy header directories") 47 | endif( NOT EXISTS ${NUMPY_INCLUDE}/numpy/arrayobject.h ) 48 | 49 | # Include python and XMM header directories 50 | include_directories(${PYTHON_INCLUDE_PATH}) 51 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/jsoncpp/include) 52 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/jsoncpp/src) 53 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 54 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core/common) 55 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core/distributions) 56 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core/model) 57 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core/trainingset) 58 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/models/gmm) 59 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/models/hmm) 60 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/models/kmeans) 61 | 62 | # Doxygen XML documentation 63 | find_package(Doxygen) 64 | 65 | if(DOXYGEN_FOUND) 66 | set(XML_DOC_INDEX ${CMAKE_CURRENT_SOURCE_DIR}/_build_tmp/xml/index.xml) 67 | add_custom_command(OUTPUT ${XML_DOC_INDEX} 68 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/Doxyfile-Python 69 | DEPENDS ${tracking_source_files} 70 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/ 71 | COMMENT "Generating API documentation with Doxygen" VERBATIM 72 | ) 73 | add_custom_target(docpy DEPENDS ${XML_DOC_INDEX}) 74 | endif(DOXYGEN_FOUND) 75 | 76 | # Add target for python documentation from doxygen 77 | file( 78 | GLOB_RECURSE 79 | xmm_header_files 80 | ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.h 81 | ) 82 | add_custom_command(OUTPUT xmm_doc.i 83 | DEPENDS docpy ${xmm_header_files} 84 | COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/src/doxy2swig.py ${CMAKE_CURRENT_SOURCE_DIR}/_build_tmp/xml/index.xml ${CMAKE_CURRENT_SOURCE_DIR}/xmm_doc.i) 85 | 86 | 87 | set(CMAKE_SWIG_FLAGS "") 88 | set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/numpy.i PROPERTIES CPLUSPLUS ON) 89 | set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/xmm.i PROPERTIES CPLUSPLUS ON) 90 | set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/xmm.i PROPERTIES SWIG_FLAGS "-DUSE_PTHREAD") 91 | SET(SWIG_MODULE_xmm_EXTRA_DEPS 92 | xmm_doc.i 93 | ) 94 | set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/xmm) 95 | SWIG_ADD_LIBRARY(xmm LANGUAGE python SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/xmm.i) 96 | SWIG_LINK_LIBRARIES(xmm ${PYTHON_LIBRARIES} xmm pthread) 97 | 98 | add_custom_command(TARGET _xmm POST_BUILD COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/src/move_files.sh) 99 | 100 | set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_CURRENT_SOURCE_DIR}/bin/xmm) 101 | -------------------------------------------------------------------------------- /src/models/gmm/xmmGmm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmGmm.hpp 3 | * 4 | * Gaussian Mixture Model for Continuous Recognition and Regression 5 | * (Multi-class) 6 | * 7 | * Contact: 8 | * - Jules Francoise 9 | * 10 | * This code has been initially authored by Jules Francoise 11 | * during his PhD thesis, supervised by Frederic 12 | * Bevilacqua , in the Sound Music 13 | * Movement Interaction team of the 14 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 15 | * 16 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 17 | * 18 | * This File is part of XMM. 19 | * 20 | * XMM is free software: you can redistribute it and/or modify 21 | * it under the terms of the GNU General Public License as published by 22 | * the Free Software Foundation, either version 3 of the License, or 23 | * (at your option) any later version. 24 | * 25 | * XMM is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | * GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License 31 | * along with XMM. If not, see . 32 | */ 33 | 34 | #ifndef xmmGmm_h 35 | #define xmmGmm_h 36 | 37 | #include "../../core/distributions/xmmGaussianDistribution.hpp" 38 | #include "../../core/model/xmmModel.hpp" 39 | #include "xmmGmmSingleClass.hpp" 40 | 41 | namespace xmm { 42 | /** 43 | @ingroup GMM 44 | @brief Gaussian Mixture Model for Continuous Recognition and Regression 45 | (Multi-class) 46 | */ 47 | class GMM : public Model { 48 | public: 49 | /** 50 | @brief Constructor 51 | @param bimodal specifies if the model should be used for regression 52 | */ 53 | GMM(bool bimodal = false); 54 | 55 | /** 56 | @brief Copy Constructor 57 | @param src Source Model 58 | */ 59 | GMM(GMM const& src); 60 | 61 | /** 62 | @brief Constructor from Json Structure 63 | @param root Json Value 64 | */ 65 | explicit GMM(Json::Value const& root); 66 | 67 | /** 68 | @brief Assignment 69 | @param src Source Model 70 | */ 71 | GMM& operator=(GMM const& src); 72 | 73 | /** @name Performance */ 74 | ///@{ 75 | 76 | /** 77 | @brief Resets the fitering process (recognition or regression) 78 | */ 79 | virtual void reset(); 80 | 81 | /** 82 | @brief filters a incoming observation (performs recognition or regression) 83 | @details the results of the inference process are stored in the results 84 | attribute 85 | @param observation observation vector 86 | */ 87 | virtual void filter(std::vector const& observation); 88 | 89 | ///@} 90 | 91 | // 92 | // /** 93 | // @brief Convert to bimodal GMM in place 94 | // @param dimension_input dimension of the input modality 95 | // @throws runtime_error if the model is already bimodal 96 | // @throws out_of_range if the requested input dimension is too 97 | // large 98 | // */ 99 | // void makeBimodal(unsigned int dimension_input); 100 | // 101 | // /** 102 | // @brief Convert to unimodal GMM in place 103 | // @throws runtime_error if the model is already unimodal 104 | // */ 105 | // void makeUnimodal(); 106 | // 107 | // /** 108 | // @brief extract a submodel with the given columns 109 | // @param columns columns indices in the target order 110 | // @throws runtime_error if the model is training 111 | // @throws out_of_range if the number or indices of the requested 112 | // columns exceeds the current dimension 113 | // @return a GMM from the current model considering only the target 114 | // columns 115 | // */ 116 | // GMM extractSubmodel(std::vector& columns) const; 117 | // 118 | // /** 119 | // @brief extract the submodel of the input modality 120 | // @throws runtime_error if the model is training or if it is not 121 | // bimodal 122 | // @return a unimodal GMM of the input modality from the current 123 | // bimodal model 124 | // */ 125 | // GMM extractSubmodel_input() const; 126 | // 127 | // /** 128 | // @brief extract the submodel of the output modality 129 | // @throws runtime_error if the model is training or if it is not 130 | // bimodal 131 | // @return a unimodal GMM of the output modality from the current 132 | // bimodal model 133 | // */ 134 | // GMM extractSubmodel_output() const; 135 | // 136 | // /** 137 | // @brief extract the model with reversed input and output 138 | // modalities 139 | // @throws runtime_error if the model is training or if it is not 140 | // bimodal 141 | // @return a bimodal GMM that swaps the input and output modalities 142 | // */ 143 | // GMM extract_inverse_model() const; 144 | 145 | /** 146 | @brief Results of the Filtering Process (Recognition + Regression) 147 | */ 148 | Results results; 149 | 150 | protected: 151 | /** 152 | @brief Update the results (Likelihoods) 153 | */ 154 | virtual void updateResults(); 155 | }; 156 | } 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /src/models/kmeans/xmmKMeans.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmKMeans.hpp 3 | * 4 | * K-Means clustering 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmKMeans_h 34 | #define xmmKMeans_h 35 | 36 | #include "../../core/model/xmmModelConfiguration.hpp" 37 | #include "../../core/model/xmmModelSingleClass.hpp" 38 | #include "xmmKMeansParameters.hpp" 39 | #include "xmmKMeansResults.hpp" 40 | 41 | namespace xmm { 42 | /** 43 | @ingroup KMeans 44 | @brief K-Means Clustering algorithm 45 | */ 46 | class KMeans : public Writable { 47 | public: 48 | static const unsigned int DEFAULT_MAX_ITERATIONS = 50; 49 | static const float DEFAULT_RELATIVE_VARIATION_THRESHOLD() { return 1e-20; } 50 | 51 | /** 52 | @brief Type of initizalization of the K-Means algorithm 53 | */ 54 | enum class InitializationMode { 55 | /** 56 | @brief random initialization (scaled using training set variance) 57 | */ 58 | Random, 59 | 60 | /** 61 | @brief biased initialization: initialiazed with the first phrase 62 | */ 63 | Biased 64 | }; 65 | 66 | /** 67 | @brief Default Constructor 68 | @param clusters number of clusters 69 | */ 70 | KMeans(unsigned int clusters = 1); 71 | 72 | /** 73 | @brief Copy Constructor 74 | @param src Source Model 75 | */ 76 | KMeans(KMeans const& src); 77 | 78 | /** 79 | @brief Assignment 80 | @param src Source Model 81 | */ 82 | KMeans& operator=(KMeans const& src); 83 | 84 | /** 85 | @brief Train the K-Means clutering from the given training set 86 | @param trainingSet Training Set 87 | */ 88 | void train(TrainingSet* trainingSet); 89 | 90 | /** 91 | @brief Resets the fitering process (cluster association) 92 | */ 93 | void reset(); 94 | 95 | /** 96 | @brief filters a incoming observation (performs cluster association) 97 | @details the results of the inference process are stored in the results 98 | attribute 99 | @param observation observation vector 100 | */ 101 | void filter(std::vector const& observation); 102 | 103 | /** @name Json I/O */ 104 | ///@{ 105 | 106 | /** 107 | @brief Write the object to a JSON Structure 108 | @return Json value containing the object's information 109 | */ 110 | Json::Value toJson() const; 111 | 112 | /** 113 | @brief Read the object from a JSON Structure 114 | @param root JSON value containing the object's information 115 | @throws JsonException if the JSON value has a wrong format 116 | */ 117 | void fromJson(Json::Value const& root); 118 | 119 | ///@} 120 | 121 | /** 122 | @brief Set of Parameters shared among classes 123 | */ 124 | std::shared_ptr shared_parameters; 125 | 126 | /** 127 | @brief Configuration (default and class-specific parameters) 128 | */ 129 | Configuration configuration; 130 | 131 | /** 132 | @brief Results of the cluster association after update with an observation 133 | */ 134 | Results results; 135 | 136 | /** 137 | @brief Clusters centers 138 | */ 139 | std::vector centers; 140 | 141 | /** 142 | @brief Type of initialization for the K-Means Algorithm 143 | */ 144 | KMeans::InitializationMode initialization_mode; 145 | 146 | protected: 147 | /** 148 | @brief randomzie Cluster Centers (normalized width data variance) 149 | of the first phrase of the training set 150 | */ 151 | void randomizeClusters(std::vector const& trainingSetVariance); 152 | 153 | /** 154 | @brief Initialize the clusters using a regular segmentation 155 | of the first phrase of the training set 156 | */ 157 | void initClustersWithFirstPhrase(std::shared_ptr phrase); 158 | 159 | /** 160 | @brief Update method for training 161 | @details computes the cluster associated with each data points, and update 162 | Cluster centers 163 | */ 164 | void updateCenters(std::vector& previous_centers, 165 | TrainingSet* trainingSet); 166 | }; 167 | 168 | /** 169 | @brief Simple Euclidian distance measure 170 | @param vector1 first data point 171 | @param vector2 first data point 172 | @param dimension dimension of the data space 173 | @return euclidian distance between the 2 points 174 | */ 175 | template 176 | T euclidean_distance(const T* vector1, const T* vector2, unsigned int dimension); 177 | } 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /src/models/gmm/xmmGmmParameters.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmGmmParameters.cpp 3 | * 4 | * Parameters of Gaussian Mixture Models 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmGmmParameters.hpp" 34 | 35 | xmm::ClassParameters::ClassParameters() 36 | : changed(true), 37 | gaussians(10, 1), 38 | relative_regularization(1.0e-2, 1e-20), 39 | absolute_regularization(1.0e-3, 1e-20), 40 | covariance_mode(GaussianDistribution::CovarianceMode::Full) { 41 | gaussians.onAttributeChange( 42 | this, &xmm::ClassParameters::onAttributeChange); 43 | relative_regularization.onAttributeChange( 44 | this, &xmm::ClassParameters::onAttributeChange); 45 | absolute_regularization.onAttributeChange( 46 | this, &xmm::ClassParameters::onAttributeChange); 47 | covariance_mode.onAttributeChange( 48 | this, &xmm::ClassParameters::onAttributeChange); 49 | } 50 | 51 | xmm::ClassParameters::ClassParameters(ClassParameters const& src) 52 | : changed(true), 53 | gaussians(src.gaussians), 54 | relative_regularization(src.relative_regularization), 55 | absolute_regularization(src.absolute_regularization), 56 | covariance_mode(src.covariance_mode) { 57 | gaussians.onAttributeChange( 58 | this, &xmm::ClassParameters::onAttributeChange); 59 | relative_regularization.onAttributeChange( 60 | this, &xmm::ClassParameters::onAttributeChange); 61 | absolute_regularization.onAttributeChange( 62 | this, &xmm::ClassParameters::onAttributeChange); 63 | covariance_mode.onAttributeChange( 64 | this, &xmm::ClassParameters::onAttributeChange); 65 | } 66 | 67 | xmm::ClassParameters::ClassParameters(Json::Value const& root) 68 | : changed(true), 69 | gaussians(10, 1), 70 | relative_regularization(1.0e-2, 1e-20), 71 | absolute_regularization(1.0e-3, 1e-20), 72 | covariance_mode(GaussianDistribution::CovarianceMode::Full) { 73 | gaussians.onAttributeChange( 74 | this, &xmm::ClassParameters::onAttributeChange); 75 | relative_regularization.onAttributeChange( 76 | this, &xmm::ClassParameters::onAttributeChange); 77 | absolute_regularization.onAttributeChange( 78 | this, &xmm::ClassParameters::onAttributeChange); 79 | covariance_mode.onAttributeChange( 80 | this, &xmm::ClassParameters::onAttributeChange); 81 | 82 | gaussians.set(root["gaussians"].asInt()); 83 | relative_regularization.set(root["relative_regularization"].asFloat()); 84 | absolute_regularization.set(root["absolute_regularization"].asFloat()); 85 | covariance_mode.set(static_cast( 86 | root["covariance_mode"].asInt())); 87 | } 88 | 89 | xmm::ClassParameters& xmm::ClassParameters::operator=( 90 | ClassParameters const& src) { 91 | if (this != &src) { 92 | changed = true; 93 | gaussians = src.gaussians; 94 | relative_regularization = src.relative_regularization; 95 | absolute_regularization = src.absolute_regularization; 96 | covariance_mode = src.covariance_mode; 97 | 98 | gaussians.onAttributeChange( 99 | this, &xmm::ClassParameters::onAttributeChange); 100 | relative_regularization.onAttributeChange( 101 | this, &xmm::ClassParameters::onAttributeChange); 102 | absolute_regularization.onAttributeChange( 103 | this, &xmm::ClassParameters::onAttributeChange); 104 | covariance_mode.onAttributeChange( 105 | this, &xmm::ClassParameters::onAttributeChange); 106 | } 107 | return *this; 108 | } 109 | 110 | Json::Value xmm::ClassParameters::toJson() const { 111 | Json::Value root; 112 | root["gaussians"] = static_cast(gaussians.get()); 113 | root["relative_regularization"] = relative_regularization.get(); 114 | root["absolute_regularization"] = absolute_regularization.get(); 115 | root["covariance_mode"] = static_cast(covariance_mode.get()); 116 | return root; 117 | } 118 | 119 | void xmm::ClassParameters::fromJson(Json::Value const& root) { 120 | try { 121 | ClassParameters tmp(root); 122 | *this = tmp; 123 | } catch (JsonException& e) { 124 | throw e; 125 | } 126 | } 127 | 128 | void xmm::ClassParameters::onAttributeChange( 129 | AttributeBase* attr_pointer) { 130 | changed = true; 131 | attr_pointer->changed = false; 132 | } 133 | -------------------------------------------------------------------------------- /dependencies/jsoncpp/src/json_valueiterator.inl: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | // included by json_value.cpp 7 | 8 | namespace Json { 9 | 10 | // ////////////////////////////////////////////////////////////////// 11 | // ////////////////////////////////////////////////////////////////// 12 | // ////////////////////////////////////////////////////////////////// 13 | // class ValueIteratorBase 14 | // ////////////////////////////////////////////////////////////////// 15 | // ////////////////////////////////////////////////////////////////// 16 | // ////////////////////////////////////////////////////////////////// 17 | 18 | ValueIteratorBase::ValueIteratorBase() 19 | : current_(), isNull_(true) { 20 | } 21 | 22 | ValueIteratorBase::ValueIteratorBase( 23 | const Value::ObjectValues::iterator& current) 24 | : current_(current), isNull_(false) {} 25 | 26 | Value& ValueIteratorBase::deref() const { 27 | return current_->second; 28 | } 29 | 30 | void ValueIteratorBase::increment() { 31 | ++current_; 32 | } 33 | 34 | void ValueIteratorBase::decrement() { 35 | --current_; 36 | } 37 | 38 | ValueIteratorBase::difference_type 39 | ValueIteratorBase::computeDistance(const SelfType& other) const { 40 | #ifdef JSON_USE_CPPTL_SMALLMAP 41 | return other.current_ - current_; 42 | #else 43 | // Iterator for null value are initialized using the default 44 | // constructor, which initialize current_ to the default 45 | // std::map::iterator. As begin() and end() are two instance 46 | // of the default std::map::iterator, they can not be compared. 47 | // To allow this, we handle this comparison specifically. 48 | if (isNull_ && other.isNull_) { 49 | return 0; 50 | } 51 | 52 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 53 | // RogueWave STL, 54 | // which is the one used by default). 55 | // Using a portable hand-made version for non random iterator instead: 56 | // return difference_type( std::distance( current_, other.current_ ) ); 57 | difference_type myDistance = 0; 58 | for (Value::ObjectValues::iterator it = current_; it != other.current_; 59 | ++it) { 60 | ++myDistance; 61 | } 62 | return myDistance; 63 | #endif 64 | } 65 | 66 | bool ValueIteratorBase::isEqual(const SelfType& other) const { 67 | if (isNull_) { 68 | return other.isNull_; 69 | } 70 | return current_ == other.current_; 71 | } 72 | 73 | void ValueIteratorBase::copy(const SelfType& other) { 74 | current_ = other.current_; 75 | isNull_ = other.isNull_; 76 | } 77 | 78 | Value ValueIteratorBase::key() const { 79 | const Value::CZString czstring = (*current_).first; 80 | if (czstring.data()) { 81 | if (czstring.isStaticString()) 82 | return Value(StaticString(czstring.data())); 83 | return Value(czstring.data(), czstring.data() + czstring.length()); 84 | } 85 | return Value(czstring.index()); 86 | } 87 | 88 | UInt ValueIteratorBase::index() const { 89 | const Value::CZString czstring = (*current_).first; 90 | if (!czstring.data()) 91 | return czstring.index(); 92 | return Value::UInt(-1); 93 | } 94 | 95 | std::string ValueIteratorBase::name() const { 96 | char const* keey; 97 | char const* end; 98 | keey = memberName(&end); 99 | if (!keey) return std::string(); 100 | return std::string(keey, end); 101 | } 102 | 103 | char const* ValueIteratorBase::memberName() const { 104 | const char* cname = (*current_).first.data(); 105 | return cname ? cname : ""; 106 | } 107 | 108 | char const* ValueIteratorBase::memberName(char const** end) const { 109 | const char* cname = (*current_).first.data(); 110 | if (!cname) { 111 | *end = NULL; 112 | return NULL; 113 | } 114 | *end = cname + (*current_).first.length(); 115 | return cname; 116 | } 117 | 118 | // ////////////////////////////////////////////////////////////////// 119 | // ////////////////////////////////////////////////////////////////// 120 | // ////////////////////////////////////////////////////////////////// 121 | // class ValueConstIterator 122 | // ////////////////////////////////////////////////////////////////// 123 | // ////////////////////////////////////////////////////////////////// 124 | // ////////////////////////////////////////////////////////////////// 125 | 126 | ValueConstIterator::ValueConstIterator() {} 127 | 128 | ValueConstIterator::ValueConstIterator( 129 | const Value::ObjectValues::iterator& current) 130 | : ValueIteratorBase(current) {} 131 | 132 | ValueConstIterator::ValueConstIterator(ValueIterator const& other) 133 | : ValueIteratorBase(other) {} 134 | 135 | ValueConstIterator& ValueConstIterator:: 136 | operator=(const ValueIteratorBase& other) { 137 | copy(other); 138 | return *this; 139 | } 140 | 141 | // ////////////////////////////////////////////////////////////////// 142 | // ////////////////////////////////////////////////////////////////// 143 | // ////////////////////////////////////////////////////////////////// 144 | // class ValueIterator 145 | // ////////////////////////////////////////////////////////////////// 146 | // ////////////////////////////////////////////////////////////////// 147 | // ////////////////////////////////////////////////////////////////// 148 | 149 | ValueIterator::ValueIterator() {} 150 | 151 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 152 | : ValueIteratorBase(current) {} 153 | 154 | ValueIterator::ValueIterator(const ValueConstIterator& other) 155 | : ValueIteratorBase(other) { 156 | throwRuntimeError("ConstIterator to Iterator should never be allowed."); 157 | } 158 | 159 | ValueIterator::ValueIterator(const ValueIterator& other) 160 | : ValueIteratorBase(other) {} 161 | 162 | ValueIterator& ValueIterator::operator=(const SelfType& other) { 163 | copy(other); 164 | return *this; 165 | } 166 | 167 | } // namespace Json 168 | -------------------------------------------------------------------------------- /src/core/common/xmmCircularbuffer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmCircularBuffer.hpp 3 | * 4 | * Simple Circular Buffer Utility 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmCircularbuffer_h 34 | #define xmmCircularbuffer_h 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | namespace xmm { 41 | /** 42 | @ingroup Common 43 | @brief Simple CircularBuffer Class 44 | @details Multichannel Circular Buffer 45 | @tparam T Data type 46 | @tparam channels number of channels 47 | */ 48 | template 49 | class CircularBuffer { 50 | public: 51 | /** 52 | @brief Constructor 53 | @param length length of the CircularBuffer 54 | */ 55 | CircularBuffer(unsigned int length = 1) { 56 | length_ = length; 57 | for (int c = 0; c < channels; c++) { 58 | data_[c].resize(length_); 59 | } 60 | current_index_ = 0; 61 | full_ = false; 62 | } 63 | 64 | /** 65 | @brief Access data by index & channel 66 | @return value at the given index and channel 67 | */ 68 | T operator()(unsigned int channel, unsigned int index) const { 69 | if (channel >= channels) 70 | throw std::out_of_range("CircularBuffer: channel out of bounds"); 71 | unsigned int m = full_ ? length_ : current_index_; 72 | if (index >= m) 73 | throw std::out_of_range("CircularBuffer: index out of bounds"); 74 | return data_[channel][index]; 75 | } 76 | 77 | /** 78 | @brief Clear the content of the buffer 79 | */ 80 | void clear() { 81 | current_index_ = 0; 82 | full_ = false; 83 | } 84 | 85 | /** 86 | @brief Add an element to the buffer (single-channel method) 87 | @param value element to add to the buffer 88 | @throws invalid_argument if the buffer is multi-channel 89 | */ 90 | void push(T const value) { 91 | if (channels > 1) 92 | throw std::invalid_argument("You must pass a vector or array"); 93 | data_[0][current_index_] = value; 94 | current_index_++; 95 | if (current_index_ == length_) full_ = true; 96 | current_index_ %= length_; 97 | } 98 | 99 | /** 100 | @brief Add an element to the buffer (multi-channel method) 101 | @param value element to add to the buffer 102 | */ 103 | void push(T const *value) { 104 | for (int c = 0; c < channels; c++) { 105 | data_[c][current_index_] = value[c]; 106 | } 107 | current_index_++; 108 | if (current_index_ == length_) full_ = true; 109 | current_index_ %= length_; 110 | } 111 | 112 | /** 113 | @brief Add an element to the buffer (multi-channel method) 114 | @param value element to add to the buffer 115 | */ 116 | void push(std::vector const &value) { 117 | for (int c = 0; c < channels; c++) { 118 | data_[c][current_index_] = value[c]; 119 | } 120 | current_index_++; 121 | if (current_index_ == length_) full_ = true; 122 | current_index_ %= length_; 123 | } 124 | 125 | /** 126 | @brief Get the size of the CircularBuffer 127 | @return size of the CircularBuffer (length) 128 | */ 129 | unsigned int size() const { return length_; } 130 | 131 | /** 132 | @brief Get the actual size of the CircularBuffer (< size() if the buffer is 133 | not full) 134 | @return actual size of the CircularBuffer (length) 135 | */ 136 | unsigned int size_t() const { return (full_ ? length_ : current_index_); } 137 | 138 | /** 139 | @brief Resize the buffer to a specific length 140 | @param length target length of the CircularBuffer 141 | */ 142 | void resize(unsigned int length) { 143 | if (length == length_) return; 144 | if (length > length_) { 145 | full_ = false; 146 | } else if (current_index_ >= length) { 147 | full_ = true; 148 | current_index_ = 0; 149 | } 150 | length_ = length; 151 | for (int c = 0; c < channels; c++) { 152 | data_[c].resize(length_); 153 | } 154 | } 155 | 156 | /** 157 | @brief Compute the mean of the buffer 158 | @return vector containing the mean of the buffer 159 | */ 160 | std::vector mean() const { 161 | std::vector _mean(channels, 0.0); 162 | int size = full_ ? length_ : current_index_; 163 | for (int c = 0; c < channels; c++) { 164 | for (int i = 0; i < size; i++) { 165 | _mean[c] += data_[c][i]; 166 | } 167 | _mean[c] /= T(size); 168 | } 169 | return _mean; 170 | } 171 | 172 | protected: 173 | /** 174 | @brief buffer data 175 | */ 176 | std::vector data_[channels]; 177 | 178 | /** 179 | @brief length of the buffer 180 | */ 181 | unsigned int length_; 182 | 183 | /** 184 | @brief current index in the buffer 185 | */ 186 | unsigned int current_index_; 187 | 188 | /** 189 | @brief Defines if the CircularBuffer is already full 190 | */ 191 | bool full_; 192 | }; 193 | } 194 | 195 | #endif -------------------------------------------------------------------------------- /src/models/hmm/xmmHmmParameters.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmHmmParameters.hpp 3 | * 4 | * Parameters of Hidden Markov Models 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmHmmParameters_hpp 34 | #define xmmHmmParameters_hpp 35 | 36 | #include "../../core/distributions/xmmGaussianDistribution.hpp" 37 | #include "../../core/model/xmmModelParameters.hpp" 38 | 39 | namespace xmm { 40 | /** 41 | @defgroup HMM [Models] Hidden Markov Models 42 | */ 43 | class HMM { 44 | public: 45 | /** 46 | @brief Type of Transition Matrix 47 | */ 48 | enum class TransitionMode { 49 | /** 50 | @brief Ergodic Transition Matrix 51 | */ 52 | Ergodic = 0, 53 | 54 | /** 55 | @brief Left-Right Transition model 56 | @details The only authorized transitions are: auto-transition and 57 | transition to the next state 58 | */ 59 | LeftRight = 1 60 | }; 61 | 62 | /** 63 | @enum RegressionEstimator 64 | @brief Estimator for the regression with HMMs 65 | */ 66 | enum class RegressionEstimator { 67 | /** 68 | @brief The output is estimated by a weighted regression over all states 69 | */ 70 | Full = 0, 71 | 72 | /** 73 | @brief The output is estimated by a weighted regression over a window 74 | centered around 75 | the likeliest state 76 | */ 77 | Windowed = 1, 78 | 79 | /** 80 | @brief The output is estimated by a regression using the likeliest 81 | state only. 82 | */ 83 | Likeliest = 2 84 | }; 85 | }; 86 | 87 | /** 88 | @ingroup HMM 89 | @brief Parameters specific to each class of a Hidden Markov Model 90 | */ 91 | template <> 92 | class ClassParameters { 93 | public: 94 | /** 95 | @brief Default Constructor 96 | */ 97 | ClassParameters(); 98 | 99 | /** 100 | @brief Copy Constructor 101 | @param src Source Object 102 | */ 103 | ClassParameters(ClassParameters const& src); 104 | 105 | /** 106 | @brief Constructor from Json Structure 107 | @param root Json Value 108 | */ 109 | explicit ClassParameters(Json::Value const& root); 110 | 111 | /** 112 | @brief Assignment 113 | @param src Source Object 114 | */ 115 | ClassParameters& operator=(ClassParameters const& src); 116 | 117 | /** @name Json I/O */ 118 | ///@{ 119 | 120 | /** 121 | @brief Write the object to a JSON Structure 122 | @return Json value containing the object's information 123 | */ 124 | Json::Value toJson() const; 125 | 126 | /** 127 | @brief Read the object from a JSON Structure 128 | @param root JSON value containing the object's information 129 | @throws JsonException if the JSON value has a wrong format 130 | */ 131 | virtual void fromJson(Json::Value const& root); 132 | 133 | ///@} 134 | 135 | /** 136 | @brief specifies if parameters have changed (model is invalid) 137 | */ 138 | bool changed = false; 139 | 140 | /** 141 | @brief Number of hidden states 142 | */ 143 | Attribute states; 144 | 145 | /** 146 | @brief Number of Gaussian Mixture Components 147 | */ 148 | Attribute gaussians; 149 | 150 | /** 151 | @brief Offset Added to the diagonal of covariance matrices for convergence 152 | (Relative to Data Variance) 153 | */ 154 | Attribute relative_regularization; 155 | 156 | /** 157 | @brief Offset Added to the diagonal of covariance matrices for convergence 158 | (minimum value) 159 | */ 160 | Attribute absolute_regularization; 161 | 162 | /** 163 | @brief Covariance Mode 164 | */ 165 | Attribute covariance_mode; 166 | 167 | /** 168 | @brief Transition matrix of the model (left-right vs ergodic) 169 | */ 170 | Attribute transition_mode; 171 | 172 | /** 173 | @brief Type of regression estimator 174 | */ 175 | Attribute regression_estimator; 176 | 177 | /** 178 | @brief specifies if the decoding algorithm is hierarchical or 179 | class-conditional 180 | */ 181 | Attribute hierarchical; 182 | 183 | protected: 184 | /** 185 | @brief notification function called when a member attribute is changed 186 | */ 187 | virtual void onAttributeChange(AttributeBase* attr_pointer); 188 | }; 189 | 190 | template <> 191 | void checkLimits(HMM::TransitionMode const& value, 192 | HMM::TransitionMode const& limit_min, 193 | HMM::TransitionMode const& limit_max); 194 | 195 | template <> 196 | HMM::TransitionMode Attribute::defaultLimitMax(); 197 | 198 | template <> 199 | void checkLimits( 200 | HMM::RegressionEstimator const& value, 201 | HMM::RegressionEstimator const& limit_min, 202 | HMM::RegressionEstimator const& limit_max); 203 | 204 | template <> 205 | HMM::RegressionEstimator Attribute::defaultLimitMax(); 206 | } 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /doc/doc-misc/XmmDoxygenLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /python/examples/data/hhmm_test_data2.txt: -------------------------------------------------------------------------------- 1 | -0.00880614 0.00732435 0.00565518 2 | -0.00928310 0.00684498 0.00606584 3 | -0.00967540 0.00596859 0.00625829 4 | -0.0100912 0.00467277 0.00657782 5 | -0.0102588 0.00349957 0.00675149 6 | -0.0101302 0.00219718 0.00688223 7 | -0.00965544 0.000913042 0.00685498 8 | -0.00907896 -0.000303052 0.00669500 9 | -0.00845574 -0.00134457 0.00645387 10 | -0.00776900 -0.00248294 0.00610784 11 | -0.00715657 -0.00331580 0.00577062 12 | -0.00662397 -0.00390247 0.00546031 13 | -0.00600769 -0.00461088 0.00516760 14 | -0.00506570 -0.00643449 0.00485982 15 | -0.00410575 -0.00867734 0.00454124 16 | -0.00330928 -0.0102832 0.00419222 17 | -0.00238831 -0.0120096 0.00367055 18 | -0.00146733 -0.0137361 0.00314889 19 | -0.00109360 -0.0172496 0.00234312 20 | -0.00160769 -0.0207134 0.000777393 21 | -0.00291108 -0.0246872 -0.00117275 22 | -0.00544242 -0.0270268 -0.00330152 23 | -0.0101054 -0.0292060 -0.00585092 24 | -0.0149451 -0.0313700 -0.00824579 25 | -0.0224186 -0.0341879 -0.0118038 26 | -0.0321796 -0.0345023 -0.0168008 27 | -0.0445700 -0.0327600 -0.0235859 28 | -0.0597514 -0.0287514 -0.0318725 29 | -0.0750452 -0.0246430 -0.0401656 30 | -0.0936977 -0.0165951 -0.0490126 31 | -0.116150 -0.00465981 -0.0589204 32 | -0.141789 0.0100854 -0.0700368 33 | -0.170439 0.0288273 -0.0828573 34 | -0.202667 0.0525676 -0.0982388 35 | -0.237013 0.0838079 -0.117254 36 | -0.273502 0.122223 -0.138260 37 | -0.309202 0.161148 -0.158882 38 | -0.345440 0.204142 -0.181734 39 | -0.381392 0.252637 -0.204814 40 | -0.417897 0.305638 -0.228634 41 | -0.452610 0.363682 -0.250105 42 | -0.485100 0.419320 -0.270032 43 | -0.516415 0.477714 -0.285688 44 | -0.545705 0.537240 -0.296899 45 | -0.575703 0.599185 -0.304940 46 | -0.601785 0.657273 -0.311225 47 | -0.623580 0.712354 -0.312129 48 | -0.641396 0.762691 -0.310046 49 | -0.656211 0.809292 -0.306183 50 | -0.667520 0.848973 -0.296273 51 | -0.675039 0.880886 -0.280578 52 | -0.677365 0.901934 -0.260364 53 | -0.676409 0.918575 -0.240385 54 | -0.673784 0.929737 -0.218004 55 | -0.667154 0.930537 -0.194851 56 | -0.658276 0.922776 -0.172063 57 | -0.645440 0.907006 -0.148679 58 | -0.627115 0.884288 -0.125147 59 | -0.603700 0.848069 -0.103057 60 | -0.577142 0.806416 -0.0817823 61 | -0.549875 0.762345 -0.0636788 62 | -0.521128 0.715381 -0.0491443 63 | -0.490950 0.665987 -0.0406915 64 | -0.458704 0.615920 -0.0365414 65 | -0.424546 0.566875 -0.0319729 66 | -0.390316 0.519752 -0.0308909 67 | -0.353538 0.471162 -0.0302312 68 | -0.314884 0.427486 -0.0302169 69 | -0.274830 0.387391 -0.0296786 70 | -0.229676 0.344210 -0.0281840 71 | -0.182541 0.300900 -0.0284607 72 | -0.136205 0.258293 -0.0325226 73 | -0.0930488 0.219174 -0.0382685 74 | -0.0539447 0.190588 -0.0479171 75 | -0.0184891 0.170482 -0.0585822 76 | 0.0264302 0.155261 -0.0709969 77 | 0.0756341 0.135998 -0.0822552 78 | 0.126507 0.117492 -0.0880867 79 | 0.175416 0.101180 -0.0921382 80 | 0.230537 0.0910276 -0.0891163 81 | 0.288081 0.0931727 -0.0855357 82 | 0.337297 0.0957888 -0.0815079 83 | 0.400226 0.104138 -0.0826218 84 | 0.464759 0.112692 -0.0865326 85 | 0.524610 0.122072 -0.0907330 86 | 0.589656 0.135697 -0.0965085 87 | 0.657264 0.153223 -0.102267 88 | 0.727416 0.181713 -0.103497 89 | 0.800467 0.208906 -0.102131 90 | 0.872081 0.232513 -0.0970107 91 | 0.943562 0.250083 -0.0889104 92 | 0.999568 0.256581 -0.0812139 93 | 1.04782 0.261268 -0.0771931 94 | 1.08927 0.263084 -0.0785819 95 | 1.12852 0.265310 -0.0771117 96 | 1.15938 0.272239 -0.0764716 97 | 1.18591 0.265849 -0.0768087 98 | 1.21746 0.258216 -0.0742424 99 | 1.23164 0.248255 -0.0679635 100 | 1.23401 0.237715 -0.0522589 101 | 1.23306 0.232040 -0.0273860 102 | 1.21758 0.225620 0.00843052 103 | 1.19508 0.220186 0.0460379 104 | 1.16443 0.211190 0.0864563 105 | 1.12531 0.202152 0.116895 106 | 1.07757 0.186194 0.141003 107 | 1.02673 0.174984 0.159947 108 | 0.975168 0.170652 0.176489 109 | 0.927073 0.172173 0.195550 110 | 0.877246 0.177265 0.213658 111 | 0.829617 0.181947 0.228906 112 | 0.779704 0.175608 0.241032 113 | 0.727566 0.165829 0.250638 114 | 0.672603 0.153452 0.256961 115 | 0.617640 0.141076 0.263284 116 | 0.564248 0.127244 0.260557 117 | 0.511285 0.105573 0.248332 118 | 0.459648 0.0804873 0.227259 119 | 0.405318 0.0518667 0.203275 120 | 0.355709 0.0191973 0.176841 121 | 0.308155 -0.0140027 0.155142 122 | 0.268318 -0.0442818 0.138902 123 | 0.231704 -0.0732725 0.124845 124 | 0.198568 -0.103022 0.112040 125 | 0.165432 -0.132771 0.0992340 126 | 0.132269 -0.166230 0.0869424 127 | 0.0991059 -0.199688 0.0746508 128 | 0.0660677 -0.233355 0.0606963 129 | 0.0352546 -0.263582 0.0492612 130 | 0.000238362 -0.299342 0.0368452 131 | -0.0391311 -0.340472 0.0228507 132 | -0.0784661 -0.385323 0.00993428 133 | -0.114925 -0.427200 -0.00265261 134 | -0.153071 -0.469378 -0.0155174 135 | -0.188525 -0.508022 -0.0254710 136 | -0.232308 -0.553823 -0.0324881 137 | -0.276167 -0.601748 -0.0346257 138 | -0.319108 -0.645673 -0.0358909 139 | -0.365842 -0.694133 -0.0349049 140 | -0.414096 -0.743581 -0.0314646 141 | -0.463524 -0.794359 -0.0270731 142 | -0.509374 -0.841013 -0.0191445 143 | -0.555023 -0.887423 -0.00991230 144 | -0.599043 -0.931498 0.000417001 145 | -0.642247 -0.974242 0.0124685 146 | -0.673421 -1.00589 0.0269993 147 | -0.700242 -1.03216 0.0431087 148 | -0.717192 -1.04648 0.0609973 149 | -0.730742 -1.05655 0.0788025 150 | -0.739688 -1.06331 0.0954085 151 | -0.744912 -1.06548 0.111684 152 | -0.737644 -1.05583 0.124681 153 | -0.722583 -1.03729 0.134174 154 | -0.703316 -1.01435 0.142547 155 | -0.676511 -0.983304 0.146995 156 | -0.643683 -0.945629 0.148959 157 | -0.609681 -0.906624 0.149971 158 | -0.571425 -0.861925 0.148800 159 | -0.533372 -0.817470 0.146325 160 | -0.490648 -0.767768 0.142361 161 | -0.448740 -0.719396 0.136674 162 | -0.406188 -0.669762 0.126780 163 | -0.363636 -0.620128 0.116886 164 | -0.324436 -0.573423 0.105204 165 | -0.287007 -0.527185 0.0936899 166 | -0.248370 -0.477879 0.0824720 167 | -0.212623 -0.430598 0.0716557 168 | -0.179752 -0.384825 0.0611491 169 | -0.151094 -0.343949 0.0519175 170 | -0.125767 -0.305335 0.0438136 171 | -0.104184 -0.270288 0.0373832 172 | -0.0856690 -0.237506 0.0321383 173 | -0.0664307 -0.203106 0.0270419 174 | -0.0501802 -0.172105 0.0233302 175 | -0.0335938 -0.140609 0.0197748 176 | -0.0216771 -0.114360 0.0177086 177 | -0.00936389 -0.0877211 0.0157763 178 | 0.000722727 -0.0642152 0.0165973 179 | 0.0111505 -0.0400946 0.0173213 180 | 0.0199255 -0.0200808 0.0177924 181 | 0.0270715 -0.00385683 0.0181785 182 | 0.0329600 0.00946002 0.0184142 183 | 0.0380173 0.0202108 0.0185792 184 | 0.0419077 0.0283709 0.0187536 185 | 0.0455385 0.0362544 0.0187943 186 | 0.0482939 0.0419948 0.0188261 187 | -------------------------------------------------------------------------------- /python/examples/test_gmm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | test_gmm.py 5 | 6 | Simple Test File for GMMs 7 | 8 | Contact: 9 | - Jules Francoise 10 | 11 | This code has been initially authored by Jules Francoise 12 | during his PhD thesis, supervised by Frederic 13 | Bevilacqua , in the Sound Music 14 | Movement Interaction team of the 15 | STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 16 | 17 | Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 18 | 19 | This File is part of XMM. 20 | 21 | XMM is free software: you can redistribute it and/or modify 22 | it under the terms of the GNU General Public License as published by 23 | the Free Software Foundation, either version 3 of the License, or 24 | (at your option) any later version. 25 | 26 | XMM is distributed in the hope that it will be useful, 27 | but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | GNU General Public License for more details. 30 | 31 | You should have received a copy of the GNU General Public License 32 | along with XMM. If not, see . 33 | """ 34 | 35 | import numpy as np 36 | import matplotlib.pyplot as plt 37 | import xmm 38 | 39 | 40 | def create_training_set(): 41 | """ Create the training set for building a simple GMM recognizer 42 | 43 | The training data originates from the help patch: "mubu.gmm.maxhelp". 44 | 45 | Returns: 46 | training_set -- Unimodal Training Set 47 | """ 48 | # Create the training set 49 | training_set = xmm.TrainingSet() 50 | training_set.dimension.set(6) # dimension of data in this example 51 | # Record data phrases 52 | for i in range(3): 53 | phrase = np.genfromtxt('data/gmm_training_data{}.txt'.format(i+1)) 54 | training_set.addPhrase(i, str(i+1)) 55 | for frame in phrase: 56 | # Append data frame to the phrase i 57 | training_set.getPhrase(i).record(frame) 58 | return training_set 59 | 60 | 61 | def gmm_train(training_set, num_gaussians=1, varianceoffset=[1., 0.01]): 62 | """ Create and Traing a GMM from the given training set 63 | 64 | Args: 65 | training_set -- Unimodal Training Set 66 | num_gaussians -- Number of Gaussian Components 67 | varianceoffset -- rel/abs variance offset 68 | 69 | Returns: 70 | gmm -- Trained GMM group 71 | """ 72 | # Create a GMM Group (handles multiples labels for recognition) 73 | gmm = xmm.GMM() 74 | # Set parameters 75 | gmm.configuration.gaussians.set(num_gaussians) 76 | gmm.configuration.relative_regularization.set(varianceoffset[0]) 77 | gmm.configuration.absolute_regularization.set(varianceoffset[1]) 78 | # Train all models 79 | gmm.train(training_set) 80 | return gmm 81 | 82 | 83 | def gmm_test_recognition(gmm, likelihood_window=20): 84 | """ Simple Test Function for Gaussian Mixture Models. 85 | The data originates from the help patch: "mubu.gmm.maxhelp". 86 | 87 | Args: 88 | gmm -- trained GMM Group 89 | likelihood_window -- size of the smoothing window for recognition 90 | """ 91 | # read test data (concatenation of 3 test examples labeled 1, 2, 3) 92 | test_data = np.genfromtxt('data/gmm_test_data1.txt') 93 | test_data = np.vstack((test_data, 94 | np.genfromtxt('data/gmm_test_data2.txt'))) 95 | test_data = np.vstack((test_data, 96 | np.genfromtxt('data/gmm_test_data3.txt'))) 97 | # Set Size of the likelihood Window (samples) 98 | gmm.shared_parameters.likelihood_window.set(likelihood_window) 99 | # Initialize performance phase 100 | gmm.reset() 101 | # Create likelihood arrays for recognition 102 | instantaneous_likelihoods = np.zeros((test_data.shape[0], gmm.size())) 103 | normalized_likelihoods = np.zeros((test_data.shape[0], gmm.size())) 104 | log_likelihoods = np.zeros((test_data.shape[0], gmm.size())) 105 | # Performance: Play test data and record the likelihoods of the modes 106 | for i in range(test_data.shape[0]): 107 | gmm.filter(test_data[i, :]) 108 | instantaneous_likelihoods[i, :] = np.array(gmm.results.instant_likelihoods) 109 | normalized_likelihoods[i, :] = np.array(gmm.results.smoothed_normalized_likelihoods) 110 | log_likelihoods[i, :] = np.array(gmm.results.smoothed_log_likelihoods) 111 | # Plot the likelihoods over time for the test phase 112 | plt.figure() 113 | plt.subplot(311) 114 | plt.plot(instantaneous_likelihoods) 115 | plt.title("Instantaneous Likelihood of Each Model Over time") 116 | plt.xlabel("Time (Samples)") 117 | plt.ylabel("Likelihood") 118 | plt.legend(("model 1", "model 2", "model 3")) 119 | plt.subplot(312) 120 | plt.plot(normalized_likelihoods) 121 | plt.title("Normalized Smoothed Likelihood of Each Model Over time") 122 | plt.xlabel("Time (Samples)") 123 | plt.ylabel("Normalized Likelihood") 124 | plt.legend(("model 1", "model 2", "model 3")) 125 | plt.subplot(313) 126 | plt.plot(log_likelihoods) 127 | plt.title("Smoothed Log-Likelihood of Each Model Over time") 128 | plt.xlabel("Time (Samples)") 129 | plt.ylabel("Log-Likelihood") 130 | plt.legend(("model 1", "model 2", "model 3")) 131 | # plt.show() 132 | return log_likelihoods 133 | 134 | 135 | if __name__ == '__main__': 136 | TRAINING_SET = create_training_set() 137 | GMM_MODEL = gmm_train(TRAINING_SET) 138 | LIKELIHOOD_WINDOW = 1 # 50 139 | LOG_LIKELIHOODS1 = gmm_test_recognition(GMM_MODEL, LIKELIHOOD_WINDOW) 140 | LIKELIHOOD_WINDOW = 40 # 50 141 | LOG_LIKELIHOODS2 = gmm_test_recognition(GMM_MODEL, LIKELIHOOD_WINDOW) 142 | plt.figure() 143 | ax1 = plt.subplot(211) 144 | plt.plot(LOG_LIKELIHOODS1) 145 | plt.title("Smoothed Log-Likelihood of Each Model Over time ($L_W = 1$)") 146 | # plt.xlabel("Time (Samples)") 147 | plt.ylabel("Log-likelihood") 148 | plt.legend(("model 1", "model 2", "model 3"), loc='best') 149 | ax2 = plt.subplot(212) 150 | plt.plot(LOG_LIKELIHOODS2) 151 | plt.title("Smoothed Log-Likelihood of Each Model Over time ($L_W = 30$)") 152 | plt.xlabel("Time (Samples)") 153 | plt.ylabel("Log-likelihood") 154 | plt.legend(("model 1", "model 2", "model 3"), loc='best') 155 | plt.show() 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /python/src/xmm.i: -------------------------------------------------------------------------------- 1 | /* 2 | * xmm.i 3 | * 4 | * Contact: 5 | * - Jules Francoise 6 | * 7 | * This code has been initially authored by Jules Francoise 8 | * during his PhD thesis, supervised by Frederic 9 | * Bevilacqua , in the Sound Music 10 | * Movement Interaction team of the 11 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 12 | * 13 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 14 | * 15 | * This File is part of XMM. 16 | * 17 | * XMM is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * XMM is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with XMM. If not, see . 29 | */ 30 | 31 | %module(docstring="XMM - Probabilistic Models for Motion Recognition and Mapping") xmm 32 | 33 | #pragma SWIG nowarn=362,503 34 | 35 | %{ 36 | #define SWIG_FILE_WITH_INIT 37 | #include 38 | #include 39 | #include "xmmMatrix.hpp" 40 | #include "xmmCircularbuffer.hpp" 41 | #include "xmmJson.hpp" 42 | #include "xmmAttribute.hpp" 43 | #include "xmmEvents.hpp" 44 | #include "xmmGaussianDistribution.hpp" 45 | #include "xmmPhrase.hpp" 46 | #include "xmmTrainingSet.hpp" 47 | #include "xmmModelSharedParameters.hpp" 48 | #include "xmmModelParameters.hpp" 49 | #include "xmmModelResults.hpp" 50 | #include "xmmModelConfiguration.hpp" 51 | #include "xmmModelSingleClass.hpp" 52 | #include "xmmModel.hpp" 53 | #include "xmmKMeansParameters.hpp" 54 | #include "xmmKMeansResults.hpp" 55 | #include "xmmKMeans.hpp" 56 | #include "xmmGmmParameters.hpp" 57 | #include "xmmGmmSingleClass.hpp" 58 | #include "xmmGmm.hpp" 59 | #include "xmmHmmParameters.hpp" 60 | #include "xmmHmmResults.hpp" 61 | #include "xmmHmmSingleClass.hpp" 62 | #include "xmmHierarchicalHmm.hpp" 63 | %} 64 | 65 | %init %{ 66 | import_array(); 67 | %} 68 | 69 | %exception { 70 | try { 71 | $action 72 | } 73 | catch (std::exception const& e) { 74 | PyErr_SetString(PyExc_IndexError,e.what()); 75 | SWIG_fail; 76 | } 77 | } 78 | 79 | %include std_vector.i 80 | %include numpy.i 81 | %include std_string.i 82 | %include std_map.i 83 | %include std_set.i 84 | %include std_shared_ptr.i 85 | 86 | //%apply (int DIM1, double* IN_ARRAY1) { (int dimension, double *observation) }; 87 | //%apply (int DIM1, double* ARGOUT_ARRAY1) { (double *modelLikelihoods, int dimension) }; 88 | 89 | namespace std { 90 | %template(vectord) vector; 91 | %template(vectorf) vector; 92 | %template(vectors) vector; 93 | %template(sets) set; 94 | %template(vectorgauss) vector; 95 | %template(vectorgmm) vector; 96 | %template(vectorhmm) vector; 97 | %template(mapgmm) map; 98 | %template(maphmm) map; 99 | }; 100 | 101 | %include ../xmm_doc.i 102 | 103 | %include "xmmMatrix.hpp" 104 | %include "xmmCircularbuffer.hpp" 105 | %include "xmmJson.hpp" 106 | %include "xmmAttribute.hpp" 107 | 108 | %template(Attribute_bool) xmm::Attribute; 109 | %template(Attribute_size_t) xmm::Attribute; 110 | %template(Attribute_int) xmm::Attribute; 111 | %template(Attribute_double) xmm::Attribute; 112 | %template(Attribute_float) xmm::Attribute; 113 | %template(Attribute_string) xmm::Attribute; 114 | %template(Attribute_vectorString) xmm::Attribute>; 115 | 116 | %include "xmmEvents.hpp" 117 | 118 | %include "xmmGaussianDistribution.hpp" 119 | 120 | %template(Attribute_CovarianceMode) xmm::Attribute; 121 | 122 | %shared_ptr(xmm::Phrase) 123 | %include "xmmPhrase.hpp" 124 | %include "xmmTrainingSet.hpp" 125 | 126 | %shared_ptr(xmm::Writable) 127 | %shared_ptr(xmm::SharedParameters) 128 | %include "xmmModelSharedParameters.hpp" 129 | 130 | %include "xmmModelParameters.hpp" 131 | %include "xmmModelResults.hpp" 132 | %include "xmmModelConfiguration.hpp" 133 | 134 | %include "xmmModelSingleClass.hpp" 135 | 136 | %template(TrainingEventGenerator) xmm::EventGenerator< xmm::TrainingEvent >; 137 | 138 | %include "xmmModel.hpp" 139 | 140 | %include "xmmKMeansParameters.hpp" 141 | 142 | %template(ClassParametersKMeans) xmm::ClassParameters< xmm::KMeans >; 143 | 144 | %include "xmmKMeansResults.hpp" 145 | 146 | %template(ResultsKMeans) xmm::Results< xmm::KMeans >; 147 | 148 | %include "xmmKMeans.hpp" 149 | 150 | %include "xmmGmmParameters.hpp" 151 | %template(ClassParametersGMM) xmm::ClassParameters< xmm::GMM >; 152 | %template(ClassResultsGMM) xmm::ClassResults< xmm::GMM >; 153 | %template(ResultsGMM) xmm::Results< xmm::GMM >; 154 | %template(ConfigurationGMM) xmm::Configuration< xmm::GMM >; 155 | 156 | %include "xmmGmmSingleClass.hpp" 157 | 158 | %template(Model_SingleClassGMM_GMM_) xmm::Model< xmm::SingleClassGMM, xmm::GMM >; 159 | 160 | %include "xmmGmm.hpp" 161 | 162 | %include "xmmHmmParameters.hpp" 163 | %template(Attribute_TransitionMode) xmm::Attribute; 164 | %template(Attribute_RegressionEstimator) xmm::Attribute; 165 | 166 | %include "xmmHmmResults.hpp" 167 | %template(ClassParametersHMM) xmm::ClassParameters< xmm::HMM >; 168 | %template(ClassResultsHMM) xmm::ClassResults< xmm::HMM >; 169 | %template(ResultsHMM) xmm::Results< xmm::HMM >; 170 | %template(ConfigurationHMM) xmm::Configuration< xmm::HMM >; 171 | %include "xmmHmmSingleClass.hpp" 172 | 173 | %template(Model_SingleClassHMM_HMM_) xmm::Model< xmm::SingleClassHMM, xmm::HMM >; 174 | 175 | %include "xmmHierarchicalHmm.hpp" 176 | 177 | %extend xmm::Configuration { 178 | xmm::ClassParameters& __getitem__(std::string label) { 179 | return (*($self))[label]; 180 | } 181 | } 182 | %extend xmm::Configuration { 183 | xmm::ClassParameters& __getitem__(std::string label) { 184 | return (*($self))[label]; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/core/model/xmmModelSharedParameters.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelSharedParameters.cpp 3 | * 4 | * Shared Parameters class 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmModelSharedParameters.hpp" 34 | 35 | xmm::SharedParameters::SharedParameters() 36 | : bimodal(false), 37 | dimension((bimodal.get()) ? 2 : 1, (bimodal.get()) ? 2 : 1), 38 | dimension_input((bimodal.get()) ? 1 : 0, 0, 39 | (bimodal.get()) ? dimension.get() : 0), 40 | em_algorithm_min_iterations(10, 1), 41 | em_algorithm_max_iterations(0), 42 | em_algorithm_percent_chg(0.01, 0.), 43 | likelihood_window(1, 1) { 44 | bimodal.onAttributeChange(this, &xmm::SharedParameters::onAttributeChange); 45 | dimension.onAttributeChange(this, 46 | &xmm::SharedParameters::onAttributeChange); 47 | dimension_input.onAttributeChange( 48 | this, &xmm::SharedParameters::onAttributeChange); 49 | em_algorithm_min_iterations.onAttributeChange( 50 | this, &xmm::SharedParameters::onAttributeChange); 51 | em_algorithm_max_iterations.onAttributeChange( 52 | this, &xmm::SharedParameters::onAttributeChange); 53 | em_algorithm_percent_chg.onAttributeChange( 54 | this, &xmm::SharedParameters::onAttributeChange); 55 | likelihood_window.onAttributeChange( 56 | this, &xmm::SharedParameters::onAttributeChange); 57 | column_names.onAttributeChange(this, 58 | &xmm::SharedParameters::onAttributeChange); 59 | } 60 | 61 | xmm::SharedParameters::SharedParameters(SharedParameters const& src) 62 | : bimodal(src.bimodal), 63 | dimension(src.dimension), 64 | dimension_input(src.dimension_input), 65 | column_names(src.column_names), 66 | em_algorithm_min_iterations(src.em_algorithm_min_iterations), 67 | em_algorithm_max_iterations(src.em_algorithm_max_iterations), 68 | em_algorithm_percent_chg(src.em_algorithm_percent_chg), 69 | likelihood_window(src.likelihood_window) { 70 | bimodal.onAttributeChange(this, &xmm::SharedParameters::onAttributeChange); 71 | dimension.onAttributeChange(this, 72 | &xmm::SharedParameters::onAttributeChange); 73 | dimension_input.onAttributeChange( 74 | this, &xmm::SharedParameters::onAttributeChange); 75 | em_algorithm_min_iterations.onAttributeChange( 76 | this, &xmm::SharedParameters::onAttributeChange); 77 | em_algorithm_max_iterations.onAttributeChange( 78 | this, &xmm::SharedParameters::onAttributeChange); 79 | em_algorithm_percent_chg.onAttributeChange( 80 | this, &xmm::SharedParameters::onAttributeChange); 81 | likelihood_window.onAttributeChange( 82 | this, &xmm::SharedParameters::onAttributeChange); 83 | column_names.onAttributeChange(this, 84 | &xmm::SharedParameters::onAttributeChange); 85 | } 86 | 87 | xmm::SharedParameters::SharedParameters(Json::Value const& root) 88 | : SharedParameters() { 89 | bimodal.set(root.get("bimodal", false).asBool()); 90 | dimension.set(root.get("dimension", bimodal.get() ? 2 : 1).asInt()); 91 | dimension_input.set( 92 | root.get("dimension_input", bimodal.get() ? 1 : 0).asInt()); 93 | em_algorithm_min_iterations.set( 94 | root.get("em_algorithm_min_iterations", 10).asInt()); 95 | em_algorithm_max_iterations.set( 96 | root.get("em_algorithm_max_iterations", 0).asInt()); 97 | em_algorithm_percent_chg.set( 98 | root.get("em_algorithm_percent_chg", 0.01).asFloat()); 99 | likelihood_window.set(root.get("likelihood_window", 1).asInt()); 100 | std::vector tmpColNames(dimension.get()); 101 | for (int i = 0; i < tmpColNames.size(); i++) 102 | tmpColNames[i] = root["column_names"].get(i, "").asString(); 103 | column_names.set(tmpColNames); 104 | } 105 | 106 | xmm::SharedParameters& xmm::SharedParameters::operator=( 107 | SharedParameters const& src) { 108 | if (this != &src) { 109 | bimodal = src.bimodal; 110 | dimension = src.dimension; 111 | dimension_input = src.dimension_input; 112 | column_names = src.column_names; 113 | em_algorithm_min_iterations = src.em_algorithm_min_iterations; 114 | em_algorithm_max_iterations = src.em_algorithm_max_iterations; 115 | em_algorithm_percent_chg = src.em_algorithm_percent_chg; 116 | likelihood_window = src.likelihood_window; 117 | } 118 | return *this; 119 | } 120 | 121 | Json::Value xmm::SharedParameters::toJson() const { 122 | Json::Value root; 123 | root["bimodal"] = bimodal.get(); 124 | root["dimension"] = static_cast(dimension.get()); 125 | root["dimension_input"] = static_cast(dimension_input.get()); 126 | for (int i = 0; i < column_names.size(); i++) 127 | root["column_names"][i] = column_names.at(i); 128 | root["em_algorithm_min_iterations"] = em_algorithm_min_iterations.get(); 129 | root["em_algorithm_max_iterations"] = em_algorithm_max_iterations.get(); 130 | root["em_algorithm_percent_chg"] = em_algorithm_percent_chg.get(); 131 | root["likelihood_window"] = static_cast(likelihood_window.get()); 132 | return root; 133 | } 134 | 135 | void xmm::SharedParameters::fromJson(Json::Value const& root) { 136 | try { 137 | SharedParameters tmp(root); 138 | *this = tmp; 139 | } catch (JsonException& e) { 140 | throw e; 141 | } 142 | } 143 | 144 | void xmm::SharedParameters::onAttributeChange(AttributeBase* attr_pointer) { 145 | if (attr_pointer == &bimodal) { 146 | if (bimodal.get()) { 147 | dimension.setLimitMin(2); 148 | if (dimension.get() < 2) dimension.set(2); 149 | dimension_input.setLimitMin(1); 150 | if (dimension_input.get() < 1) dimension_input.set(1); 151 | } else { 152 | dimension.setLimitMin(1); 153 | if (dimension.get() < 1) dimension.set(1); 154 | dimension_input.setLimitMax(0); 155 | dimension_input.set(0); 156 | } 157 | } else if (attr_pointer == &dimension) { 158 | dimension_input.setLimitMax(dimension.get() - 1); 159 | column_names.resize(dimension.get()); 160 | } 161 | attr_pointer->changed = false; 162 | } 163 | -------------------------------------------------------------------------------- /src/core/model/xmmModelConfiguration.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelConfiguration.hpp 3 | * 4 | * Configuration for probabilistic models with multiple classes 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #ifndef xmmModelConfiguration_h 34 | #define xmmModelConfiguration_h 35 | 36 | #include "xmmModelParameters.hpp" 37 | #include 38 | #include 39 | 40 | namespace xmm { 41 | /** 42 | @brief Regression estimator for multiclass models 43 | */ 44 | enum class MultiClassRegressionEstimator { 45 | /** 46 | @brief the output is estimated as the output values of the likeliest class 47 | */ 48 | Likeliest = 0, 49 | 50 | /** 51 | @brief the output is estimated as a weight sum of the output values of each 52 | class 53 | */ 54 | Mixture = 1 55 | }; 56 | 57 | /** 58 | @brief Multithreading mode for multiple-class training 59 | */ 60 | enum class MultithreadingMode { 61 | /** 62 | @brief No multithreading: all classes are trained sequentially 63 | */ 64 | Sequential, 65 | 66 | /** 67 | @brief Multithreading: all classes are trained in parallel in different 68 | threads. the train 69 | function returns after all classes have finished training. 70 | */ 71 | Parallel, 72 | 73 | /** 74 | @brief Multithreading in Background: all classes are trained in parallel in 75 | different threads. the train 76 | function returns after the training has started 77 | @warning when the train function return, models are still training in 78 | background. 79 | */ 80 | Background 81 | }; 82 | 83 | /** 84 | @ingroup Model 85 | @brief Model configuration 86 | @details The object contains both default parameters and class-specific 87 | parameters 88 | */ 89 | template 90 | class Configuration : public ClassParameters { 91 | public: 92 | template 93 | friend class Model; 94 | 95 | /** 96 | @brief Default Constructor 97 | */ 98 | Configuration() 99 | : multithreading(MultithreadingMode::Parallel), 100 | multiClass_regression_estimator(MultiClassRegressionEstimator::Likeliest) {} 101 | 102 | /** 103 | @brief Copy Constructor 104 | @param src Source Object 105 | */ 106 | Configuration(Configuration const& src) 107 | : ClassParameters(src), 108 | multithreading(src.multithreading), 109 | multiClass_regression_estimator(src.multiClass_regression_estimator), 110 | class_parameters_(src.class_parameters_) {} 111 | 112 | /** 113 | @brief Constructor from Json Structure 114 | @param root Json Value 115 | */ 116 | explicit Configuration(Json::Value const& root) { 117 | ClassParameters::fromJson(root["default_parameters"]); 118 | multithreading = static_cast( 119 | root.get("multithreading", 0).asInt()); 120 | multiClass_regression_estimator = 121 | static_cast( 122 | root.get("multiClass_regression_estimator", 0).asInt()); 123 | class_parameters_.clear(); 124 | std::vector members = root["class_parameters"].getMemberNames(); 125 | for (auto label : members) { 126 | class_parameters_[label].fromJson(root["class_parameters"][label]); 127 | } 128 | } 129 | 130 | /** 131 | @brief Assignment 132 | @param src Source Object 133 | */ 134 | Configuration& operator=(Configuration const& src) { 135 | if (this != &src) { 136 | ClassParameters::operator=(src); 137 | class_parameters_ = src.class_parameters_; 138 | multithreading = src.multithreading; 139 | multiClass_regression_estimator = 140 | src.multiClass_regression_estimator; 141 | } 142 | return *this; 143 | } 144 | 145 | /** 146 | @brief access the parameters of a given class by label 147 | @details If the parameters have not been edited for this class yet, they 148 | are set to the default parameters. 149 | @param label class label 150 | @return a reference to the parameters of the given class 151 | */ 152 | ClassParameters& operator[](std::string label) { 153 | if (class_parameters_.count(label) == 0) { 154 | class_parameters_[label] = *this; 155 | } 156 | return class_parameters_[label]; 157 | } 158 | 159 | /** 160 | @brief check if there exist an overloaded configuration for a given label 161 | default parameters. 162 | @param label class label 163 | @return true if there exist an overloaded configuration for the given label 164 | */ 165 | bool includes(std::string label) { 166 | return class_parameters_.count(label) > 0; 167 | } 168 | 169 | /** 170 | @brief Reset the parameters of all classes to default 171 | */ 172 | void reset() { class_parameters_.clear(); } 173 | 174 | /** 175 | @brief Reset the parameters of a given classes to default 176 | @param label class label 177 | */ 178 | void reset(std::string label) { 179 | if (class_parameters_.count(label) > 0) { 180 | class_parameters_.erase(label); 181 | } 182 | } 183 | 184 | /** 185 | @brief Write the object to a JSON Structure 186 | @return Json value containing the object's information 187 | */ 188 | virtual Json::Value toJson() const { 189 | Json::Value root; 190 | root["multithreading"] = static_cast(multithreading); 191 | root["multiClass_regression_estimator"] = 192 | static_cast(multiClass_regression_estimator); 193 | root["default_parameters"] = ClassParameters::toJson(); 194 | for (auto p : class_parameters_) { 195 | root["class_parameters"][p.first] = p.second.toJson(); 196 | } 197 | return root; 198 | } 199 | 200 | /** 201 | @brief Read the object from a JSON Structure 202 | @param root JSON value containing the object's information 203 | @throws JsonException if the JSON value has a wrong format 204 | */ 205 | virtual void fromJson(Json::Value const& root) { 206 | try { 207 | Configuration tmp(root); 208 | *this = tmp; 209 | } catch (JsonException& e) { 210 | throw e; 211 | } 212 | } 213 | 214 | /** 215 | @brief Multithreading Training Mode 216 | */ 217 | MultithreadingMode multithreading; 218 | 219 | /** 220 | @brief Regression mode for multiple class (prediction from likeliest class 221 | vs interpolation) 222 | */ 223 | MultiClassRegressionEstimator multiClass_regression_estimator; 224 | 225 | protected: 226 | /** 227 | @brief Parameters for each class 228 | */ 229 | std::map> class_parameters_; 230 | }; 231 | } 232 | 233 | #endif 234 | -------------------------------------------------------------------------------- /test/xmmTestsJsonIO.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsJsonIO.cpp 3 | * 4 | * Test suite for Json I/O 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "catch.hpp" 34 | #include "xmmTestsUtilities.hpp" 35 | #define XMM_TESTING 36 | #include "xmm.h" 37 | #include 38 | 39 | TEST_CASE("Phrase: Json IO", "[JSON I/O]") { 40 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 41 | xmm::Multimodality::Unimodal); 42 | ts.dimension.set(3); 43 | std::vector observation(3); 44 | std::string label_a(static_cast("a")); 45 | std::string label_b(static_cast("b")); 46 | ts.addPhrase(0, label_a); 47 | ts.addPhrase(1, label_b); 48 | for (unsigned int i = 0; i < 100; i++) { 49 | observation[0] = float(i) / 100.; 50 | observation[1] = pow(float(i) / 100., 2.); 51 | observation[2] = pow(float(i) / 100., 3.); 52 | ts.getPhrase(0)->record(observation); 53 | observation[0] -= 1.; 54 | observation[1] -= 1.; 55 | observation[2] -= 1.; 56 | ts.getPhrase(1)->record(observation); 57 | } 58 | CHECK(ts.getPhrase(0)->toJson() != ts.getPhrase(1)->toJson()); 59 | // std::cout << ts.getPhrase(0)->toJson() << std::endl; 60 | // std::cout << ts.getPhrase(1)->toJson() << std::endl; 61 | ts.getPhrase(1)->fromJson(ts.getPhrase(0)->toJson()); 62 | CHECK(ts.getPhrase(0)->toJson() == ts.getPhrase(1)->toJson()); 63 | // std::cout << ts.getPhrase(1)->toJson() << std::endl; 64 | 65 | xmm::TrainingSet ts2(xmm::MemoryMode::OwnMemory, 66 | xmm::Multimodality::Unimodal); 67 | ts2.dimension.set(2); 68 | std::string label_c(static_cast("c")); 69 | ts2.addPhrase(0, label_c); 70 | CHECK_NOTHROW(ts2.getPhrase(0)->fromJson(ts.getPhrase(0)->toJson())); 71 | CHECK(ts2.getPhrase(0)->toJson() == ts.getPhrase(0)->toJson()); 72 | // std::cout << ts2.getPhrase(0)->toJson() << std::endl; 73 | 74 | xmm::TrainingSet ts3(xmm::MemoryMode::OwnMemory, 75 | xmm::Multimodality::Bimodal); 76 | ts3.dimension.set(3); 77 | ts3.dimension_input.set(2); 78 | std::vector observation_input(2); 79 | std::vector observation_output(1); 80 | ts3.addPhrase(0, label_a); 81 | for (unsigned int i = 0; i < 100; i++) { 82 | observation_input[0] = float(i) / 100.; 83 | observation_input[1] = pow(float(i) / 100., 2.); 84 | observation_output[0] = pow(float(i) / 100., 3.); 85 | ts3.getPhrase(0)->record_input(observation_input); 86 | ts3.getPhrase(0)->record_output(observation_output); 87 | } 88 | ts3.addPhrase(1243, label_c); 89 | CHECK_NOTHROW(ts3.getPhrase(1243)->fromJson(ts3.getPhrase(0)->toJson())); 90 | for (int i = 0; i < ts3.getPhrase(0)->size(); i++) { 91 | CHECK(ts3.getPhrase(0)->getValue(i, 0) == 92 | ts3.getPhrase(1243)->getValue(i, 0)); 93 | } 94 | CHECK_NOTHROW(ts3.getPhrase(1243)->fromJson(ts.getPhrase(0)->toJson())); 95 | } 96 | 97 | TEST_CASE("Training Set: Json IO", "[JSON I/O]") { 98 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 99 | xmm::Multimodality::Unimodal); 100 | ts.dimension.set(3); 101 | std::vector observation(3); 102 | std::string label_a(static_cast("a")); 103 | std::string label_b(static_cast("b")); 104 | ts.addPhrase(12, label_a); 105 | ts.addPhrase(18, label_b); 106 | for (unsigned int i = 0; i < 100; i++) { 107 | observation[0] = float(i) / 100.; 108 | observation[1] = pow(float(i) / 100., 2.); 109 | observation[2] = pow(float(i) / 100., 3.); 110 | ts.getPhrase(12)->record(observation); 111 | observation[0] -= 1.; 112 | observation[1] -= 1.; 113 | observation[2] -= 1.; 114 | ts.getPhrase(18)->record(observation); 115 | } 116 | // std::cout << ts.toJson() << std::endl; 117 | 118 | xmm::TrainingSet ts2(xmm::MemoryMode::OwnMemory, 119 | xmm::Multimodality::Bimodal); 120 | ts2.dimension.set(2); 121 | std::string label_c(static_cast("c")); 122 | CHECK_NOTHROW(ts2.fromJson(ts.toJson())); 123 | CHECK(ts.toJson() == ts2.toJson()); 124 | } 125 | 126 | TEST_CASE("GaussianDistribution: Json IO", "[JSON I/O]") { 127 | xmm::GaussianDistribution a; 128 | a.dimension.set(3); 129 | a.mean = {1, 2, 3}; 130 | a.covariance = {1, 0, 0, 0, 2, 0, 0, 0, 3}; 131 | 132 | // std::cout << a.toJson() << std::endl; 133 | xmm::GaussianDistribution b(a.toJson()); 134 | CHECK(a.toJson() == b.toJson()); 135 | 136 | xmm::GaussianDistribution c; 137 | CHECK_NOTHROW(c.fromJson(a.toJson())); 138 | } 139 | 140 | TEST_CASE("GMM: Json IO", "[JSON I/O]") { 141 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 142 | xmm::Multimodality::Unimodal); 143 | ts.dimension.set(3); 144 | std::vector observation(3); 145 | std::string label_a(static_cast("a")); 146 | std::string label_b(static_cast("b")); 147 | ts.addPhrase(0, label_a); 148 | ts.addPhrase(1, label_b); 149 | for (unsigned int i = 0; i < 100; i++) { 150 | observation[0] = float(i) / 100.; 151 | observation[1] = pow(float(i) / 100., 2.); 152 | observation[2] = pow(float(i) / 100., 3.); 153 | ts.getPhrase(0)->record(observation); 154 | ts.getPhrase(1)->record(observation); 155 | } 156 | xmm::GMM a; 157 | a.configuration.gaussians.set(3); 158 | a.configuration.absolute_regularization.set(1.); 159 | a.configuration.relative_regularization.set(1.); 160 | a.shared_parameters->em_algorithm_percent_chg.set(0.); 161 | a.train(&ts); 162 | 163 | xmm::GMM b(a.toJson()); 164 | CHECK(b.toJson() == a.toJson()); 165 | 166 | xmm::GMM c; 167 | c.fromJson(a.toJson()); 168 | CHECK(c.toJson() == a.toJson()); 169 | } 170 | 171 | TEST_CASE("HierarchicalHMM: Json IO", "[JSON I/O]") { 172 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 173 | xmm::Multimodality::Unimodal); 174 | ts.dimension.set(3); 175 | ts.column_names.set({"x", "y", "z"}); 176 | std::vector observation(3); 177 | std::string label_a(static_cast("a")); 178 | std::string label_b(static_cast("b")); 179 | ts.addPhrase(0, label_a); 180 | ts.addPhrase(1, label_b); 181 | for (unsigned int i = 0; i < 100; i++) { 182 | observation[0] = float(i) / 100.; 183 | observation[1] = pow(float(i) / 100., 2.); 184 | observation[2] = pow(float(i) / 100., 3.); 185 | ts.getPhrase(0)->record(observation); 186 | ts.getPhrase(1)->record(observation); 187 | } 188 | xmm::HierarchicalHMM a; 189 | a.configuration.states.set(3); 190 | a.configuration.absolute_regularization.set(1.); 191 | a.configuration.relative_regularization.set(1.); 192 | a.configuration[label_b].states.set(12); 193 | a.shared_parameters->em_algorithm_percent_chg.set(0.); 194 | a.train(&ts); 195 | 196 | xmm::HierarchicalHMM b(a.toJson()); 197 | CHECK(b.toJson() == a.toJson()); 198 | 199 | xmm::HierarchicalHMM c; 200 | c.fromJson(a.toJson()); 201 | CHECK(c.toJson() == a.toJson()); 202 | } 203 | -------------------------------------------------------------------------------- /src/core/model/xmmModelSingleClass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmModelSingleClass.hpp 3 | * 4 | * Abstract class for Single-class Probabilistic Machine learning models based 5 | * on the EM algorithm 6 | * 7 | * Contact: 8 | * - Jules Francoise 9 | * 10 | * This code has been initially authored by Jules Francoise 11 | * during his PhD thesis, supervised by Frederic 12 | * Bevilacqua , in the Sound Music 13 | * Movement Interaction team of the 14 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 15 | * 16 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 17 | * 18 | * This File is part of XMM. 19 | * 20 | * XMM is free software: you can redistribute it and/or modify 21 | * it under the terms of the GNU General Public License as published by 22 | * the Free Software Foundation, either version 3 of the License, or 23 | * (at your option) any later version. 24 | * 25 | * XMM is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | * GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License 31 | * along with XMM. If not, see . 32 | */ 33 | 34 | #include "xmmModelSingleClass.hpp" 35 | #include 36 | 37 | #pragma mark - 38 | #pragma mark Constructors 39 | xmm::SingleClassProbabilisticModel::SingleClassProbabilisticModel( 40 | std::shared_ptr p) 41 | : label(""), 42 | shared_parameters(p), 43 | training_status(this, label), 44 | is_training_(false), 45 | cancel_training_(false) { 46 | if (p == NULL) { 47 | throw std::runtime_error( 48 | "Cannot instantiate a probabilistic model without Shared " 49 | "parameters."); 50 | } 51 | likelihood_buffer_.resize(shared_parameters->likelihood_window.get()); 52 | } 53 | 54 | xmm::SingleClassProbabilisticModel::SingleClassProbabilisticModel( 55 | SingleClassProbabilisticModel const& src) 56 | : label(src.label), 57 | shared_parameters(src.shared_parameters), 58 | training_status(this, label), 59 | is_training_(false), 60 | cancel_training_(false) { 61 | if (is_training_) 62 | throw std::runtime_error("Cannot copy: target model is still training"); 63 | if (src.is_training_) 64 | throw std::runtime_error("Cannot copy: source model is still training"); 65 | } 66 | 67 | xmm::SingleClassProbabilisticModel::SingleClassProbabilisticModel( 68 | std::shared_ptr p, Json::Value const& root) 69 | : label(""), 70 | shared_parameters(p), 71 | training_status(this, label), 72 | is_training_(false), 73 | cancel_training_(false) { 74 | if (p == NULL) { 75 | throw std::runtime_error( 76 | "Cannot instantiate a probabilistic model without Shared " 77 | "parameters."); 78 | } 79 | label = root["label"].asString(); 80 | training_status.label = label; 81 | } 82 | 83 | xmm::SingleClassProbabilisticModel& xmm::SingleClassProbabilisticModel:: 84 | operator=(SingleClassProbabilisticModel const& src) { 85 | if (this != &src) { 86 | if (is_training_) 87 | throw std::runtime_error( 88 | "Cannot copy: target model is still training"); 89 | if (src.is_training_) 90 | throw std::runtime_error( 91 | "Cannot copy: source model is still training"); 92 | label = src.label; 93 | training_status = TrainingEvent(this, label); 94 | shared_parameters = src.shared_parameters; 95 | is_training_ = false; 96 | cancel_training_ = false; 97 | } 98 | return *this; 99 | }; 100 | 101 | xmm::SingleClassProbabilisticModel::~SingleClassProbabilisticModel() { 102 | while (this->isTraining()) { 103 | } 104 | } 105 | 106 | #pragma mark - 107 | #pragma mark Accessors 108 | bool xmm::SingleClassProbabilisticModel::isTraining() const { 109 | return is_training_; 110 | } 111 | 112 | #pragma mark - 113 | #pragma mark Training 114 | void xmm::SingleClassProbabilisticModel::train(TrainingSet* trainingSet) { 115 | training_mutex_.lock(); 116 | bool trainingError(false); 117 | 118 | training_status.status = TrainingEvent::Status::Run; 119 | 120 | if (trainingSet && !trainingSet->empty()) { 121 | this->allocate(); 122 | } else { 123 | trainingError = true; 124 | } 125 | 126 | if (cancelTrainingIfRequested()) return; 127 | if (!trainingError) { 128 | try { 129 | this->emAlgorithmInit(trainingSet); 130 | } catch (std::exception& e) { 131 | trainingError = true; 132 | } 133 | } 134 | 135 | training_status.label = label; 136 | training_status.log_likelihood = -std::numeric_limits::max(); 137 | training_status.iterations = 0; 138 | double old_log_prob = training_status.log_likelihood; 139 | 140 | while (!emAlgorithmHasConverged(training_status.iterations, 141 | training_status.log_likelihood, 142 | old_log_prob)) { 143 | if (cancelTrainingIfRequested()) return; 144 | old_log_prob = training_status.log_likelihood; 145 | if (!trainingError) { 146 | try { 147 | training_status.log_likelihood = 148 | this->emAlgorithmUpdate(trainingSet); 149 | } catch (std::exception& e) { 150 | trainingError = true; 151 | } 152 | } 153 | 154 | if (std::isnan(100. * 155 | fabs((training_status.log_likelihood - old_log_prob) / 156 | old_log_prob)) && 157 | (training_status.iterations > 1)) 158 | trainingError = true; 159 | 160 | if (trainingError) { 161 | is_training_ = false; 162 | training_mutex_.unlock(); 163 | training_status.status = TrainingEvent::Status::Error; 164 | training_events.notifyListeners(training_status); 165 | return; 166 | } 167 | 168 | ++training_status.iterations; 169 | 170 | if (shared_parameters->em_algorithm_max_iterations.get() > 171 | shared_parameters->em_algorithm_min_iterations.get()) 172 | training_status.progression = 173 | float(training_status.iterations) / 174 | float(shared_parameters->em_algorithm_max_iterations.get()); 175 | else 176 | training_status.progression = 177 | float(training_status.iterations) / 178 | float(shared_parameters->em_algorithm_min_iterations.get()); 179 | 180 | training_events.notifyListeners(training_status); 181 | } 182 | 183 | if (cancelTrainingIfRequested()) return; 184 | this->emAlgorithmTerminate(); 185 | 186 | training_mutex_.unlock(); 187 | } 188 | 189 | bool xmm::SingleClassProbabilisticModel::emAlgorithmHasConverged( 190 | int step, double log_prob, double old_log_prob) const { 191 | if (step >= 1000) return true; 192 | if (shared_parameters->em_algorithm_max_iterations.get() >= 193 | shared_parameters->em_algorithm_min_iterations.get()) 194 | return (step >= shared_parameters->em_algorithm_max_iterations.get()); 195 | else 196 | return (step >= shared_parameters->em_algorithm_min_iterations.get()) && 197 | (100. * fabs((log_prob - old_log_prob) / log_prob) <= 198 | shared_parameters->em_algorithm_percent_chg.get()); 199 | } 200 | 201 | void xmm::SingleClassProbabilisticModel::emAlgorithmTerminate() { 202 | training_status.status = TrainingEvent::Status::Done; 203 | training_events.notifyListeners(training_status); 204 | this->is_training_ = false; 205 | } 206 | 207 | void xmm::SingleClassProbabilisticModel::cancelTraining() { 208 | if (isTraining()) { 209 | cancel_training_ = true; 210 | } 211 | } 212 | 213 | bool xmm::SingleClassProbabilisticModel::cancelTrainingIfRequested() { 214 | if (!cancel_training_) return false; 215 | training_mutex_.unlock(); 216 | training_status.label = label; 217 | training_status.status = TrainingEvent::Status::Cancel; 218 | training_events.notifyListeners(training_status); 219 | is_training_ = false; 220 | return true; 221 | } 222 | 223 | #pragma mark - 224 | #pragma mark Performance 225 | void xmm::SingleClassProbabilisticModel::reset() { 226 | check_training(); 227 | likelihood_buffer_.resize(shared_parameters->likelihood_window.get()); 228 | likelihood_buffer_.clear(); 229 | } 230 | 231 | #pragma mark - 232 | #pragma mark File IO 233 | Json::Value xmm::SingleClassProbabilisticModel::toJson() const { 234 | check_training(); 235 | Json::Value root; 236 | root["label"] = label; 237 | return root; 238 | } 239 | -------------------------------------------------------------------------------- /test/xmmTestsGaussianCovarianceMode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsGaussianCovarianceMode.cpp 3 | * 4 | * Test suite for Diagonal vs Full covariance Gaussian Distributions 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "catch.hpp" 34 | #include "xmmTestsUtilities.hpp" 35 | #define XMM_TESTING 36 | #include "xmm.h" 37 | #include 38 | 39 | TEST_CASE("Diagonal covariance (unimodal)", "[GaussianDistribution]") { 40 | xmm::GaussianDistribution a(false, 3, 0); 41 | a.mean[0] = 0.2; 42 | a.mean[1] = 0.3; 43 | a.mean[2] = 0.1; 44 | a.covariance[0] = 1.3; 45 | a.covariance[1] = 0.0; 46 | a.covariance[2] = 0.2; 47 | a.covariance[3] = 0.0; 48 | a.covariance[4] = 1.4; 49 | a.covariance[5] = 0.7; 50 | a.covariance[6] = 0.2; 51 | a.covariance[7] = 0.7; 52 | a.covariance[8] = 1.5; 53 | a.updateInverseCovariance(); 54 | float *observation = new float[3]; 55 | observation[0] = 0.7; 56 | observation[1] = 0.; 57 | observation[2] = -0.3; 58 | xmm::GaussianDistribution b(a); 59 | CHECK_NOTHROW(b.covariance_mode.set( 60 | xmm::GaussianDistribution::CovarianceMode::Diagonal)); 61 | CHECK(a.mean == b.mean); 62 | CHECK(a.covariance[0] == b.covariance[0]); 63 | CHECK(a.covariance[4] == b.covariance[1]); 64 | CHECK(a.covariance[8] == b.covariance[2]); 65 | double likelihood_b = b.likelihood(observation); 66 | xmm::GaussianDistribution c(b); 67 | CHECK_NOTHROW( 68 | c.covariance_mode.set(xmm::GaussianDistribution::CovarianceMode::Full)); 69 | CHECK(a.mean == c.mean); 70 | CHECK_FALSE(a.covariance == c.covariance); 71 | CHECK(c.covariance[0] == b.covariance[0]); 72 | CHECK(c.covariance[4] == b.covariance[1]); 73 | CHECK(c.covariance[8] == b.covariance[2]); 74 | double likelihood_c = c.likelihood(observation); 75 | CHECK(likelihood_b == likelihood_c); 76 | delete[] observation; 77 | } 78 | 79 | TEST_CASE("Diagonal covariance (bimodal)", "[GaussianDistribution]") { 80 | xmm::GaussianDistribution a(true, 3, 2); 81 | a.mean[0] = 0.2; 82 | a.mean[1] = 0.3; 83 | a.mean[2] = 0.1; 84 | a.covariance[0] = 1.3; 85 | a.covariance[1] = 0.8; 86 | a.covariance[2] = 0.2; 87 | a.covariance[3] = 0.8; 88 | a.covariance[4] = 1.4; 89 | a.covariance[5] = 0.7; 90 | a.covariance[6] = 0.2; 91 | a.covariance[7] = 0.7; 92 | a.covariance[8] = 1.5; 93 | a.updateInverseCovariance(); 94 | float *observation = new float[3]; 95 | observation[0] = 0.7; 96 | observation[1] = 0.; 97 | observation[2] = -0.3; 98 | xmm::GaussianDistribution b(a); 99 | CHECK_NOTHROW(b.covariance_mode.set( 100 | xmm::GaussianDistribution::CovarianceMode::Diagonal)); 101 | CHECK(a.mean == b.mean); 102 | CHECK(a.covariance[0] == b.covariance[0]); 103 | CHECK(a.covariance[4] == b.covariance[1]); 104 | CHECK(a.covariance[8] == b.covariance[2]); 105 | xmm::GaussianDistribution c(b); 106 | CHECK_NOTHROW( 107 | c.covariance_mode.set(xmm::GaussianDistribution::CovarianceMode::Full)); 108 | CHECK(a.mean == c.mean); 109 | CHECK_FALSE(a.covariance == c.covariance); 110 | CHECK(c.covariance[0] == b.covariance[0]); 111 | CHECK(c.covariance[4] == b.covariance[1]); 112 | CHECK(c.covariance[8] == b.covariance[2]); 113 | CHECK(b.likelihood_input(observation) == c.likelihood_input(observation)); 114 | CHECK_FALSE(b.likelihood_input(observation) == 115 | a.likelihood_input(observation)); 116 | delete[] observation; 117 | } 118 | 119 | TEST_CASE("GMM with Diagonal covariance (unimodal)", "[GMM]") { 120 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 121 | xmm::Multimodality::Unimodal); 122 | ts.dimension.set(3); 123 | std::vector observation(3); 124 | ts.addPhrase(0); 125 | ts.addPhrase(1); 126 | for (unsigned int i = 0; i < 100; i++) { 127 | observation[0] = float(i) / 100.; 128 | observation[1] = pow(float(i) / 100., 2.); 129 | observation[2] = pow(float(i) / 100., 3.); 130 | ts.getPhrase(0)->record(observation); 131 | ts.getPhrase(1)->record(observation); 132 | } 133 | std::string label_a(static_cast("a")); 134 | std::string label_b(static_cast("b")); 135 | ts.getPhrase(0)->label.set(label_a); 136 | ts.getPhrase(1)->label.set(label_b); 137 | xmm::GMM a; 138 | a.configuration.gaussians.set(3); 139 | a.train(&ts); 140 | CHECK_NOTHROW(a.configuration.covariance_mode.set( 141 | xmm::GaussianDistribution::CovarianceMode::Diagonal)); 142 | a.reset(); 143 | std::vector log_likelihood(100, 0.0); 144 | for (unsigned int i = 0; i < 100; i++) { 145 | observation[0] = float(i) / 100.; 146 | observation[1] = pow(float(i) / 100., 2.); 147 | observation[2] = pow(float(i) / 100., 3.); 148 | a.filter(observation); 149 | log_likelihood[i] = a.results.smoothed_log_likelihoods[0]; 150 | } 151 | CHECK_NOTHROW(a.configuration.covariance_mode.set( 152 | xmm::GaussianDistribution::CovarianceMode::Full)); 153 | a.reset(); 154 | std::vector log_likelihood2(100, 0.0); 155 | for (unsigned int i = 0; i < 100; i++) { 156 | observation[0] = float(i) / 100.; 157 | observation[1] = pow(float(i) / 100., 2.); 158 | observation[2] = pow(float(i) / 100., 3.); 159 | a.filter(observation); 160 | log_likelihood2[i] = a.results.smoothed_log_likelihoods[0]; 161 | } 162 | CHECK_VECTOR_APPROX(log_likelihood, log_likelihood2); 163 | } 164 | 165 | TEST_CASE("HierarchicalHMM with Diagonal covariance (unimodal)", 166 | "[HierarchicalHMM]") { 167 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 168 | xmm::Multimodality::Unimodal); 169 | ts.dimension.set(3); 170 | std::vector observation(3); 171 | ts.addPhrase(0); 172 | ts.addPhrase(1); 173 | for (unsigned int i = 0; i < 100; i++) { 174 | observation[0] = float(i) / 100.; 175 | observation[1] = pow(float(i) / 100., 2.); 176 | observation[2] = pow(float(i) / 100., 3.); 177 | ts.getPhrase(0)->record(observation); 178 | ts.getPhrase(1)->record(observation); 179 | } 180 | std::string label_a(static_cast("a")); 181 | std::string label_b(static_cast("b")); 182 | ts.getPhrase(0)->label.set(label_a); 183 | ts.getPhrase(1)->label.set(label_b); 184 | xmm::HierarchicalHMM a; 185 | a.configuration.states.set(3); 186 | a.train(&ts); 187 | a.configuration.covariance_mode.set( 188 | xmm::GaussianDistribution::CovarianceMode::Diagonal); 189 | a.reset(); 190 | std::vector log_likelihood(100, 0.0); 191 | for (unsigned int i = 0; i < 100; i++) { 192 | observation[0] = float(i) / 100.; 193 | observation[1] = pow(float(i) / 100., 2.); 194 | observation[2] = pow(float(i) / 100., 3.); 195 | a.filter(observation); 196 | log_likelihood[i] = a.results.smoothed_log_likelihoods[0]; 197 | } 198 | a.configuration.covariance_mode.set( 199 | xmm::GaussianDistribution::CovarianceMode::Full); 200 | a.reset(); 201 | std::vector log_likelihood2(100, 0.0); 202 | for (unsigned int i = 0; i < 100; i++) { 203 | observation[0] = float(i) / 100.; 204 | observation[1] = pow(float(i) / 100., 2.); 205 | observation[2] = pow(float(i) / 100., 3.); 206 | a.filter(observation); 207 | log_likelihood2[i] = a.results.smoothed_log_likelihoods[0]; 208 | } 209 | CHECK_VECTOR_APPROX(log_likelihood, log_likelihood2); 210 | CHECK_NOTHROW(a.configuration.covariance_mode.set( 211 | xmm::GaussianDistribution::CovarianceMode::Diagonal);); 212 | // JSONNode a_json = a.toJson(); 213 | // xmm::HierarchicalHMM b; 214 | // b.fromJson(a_json); 215 | } 216 | -------------------------------------------------------------------------------- /src/models/hmm/xmmHmmParameters.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmHmmParameters.cpp 3 | * 4 | * Parameters of Hidden Markov Models 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "xmmHmmParameters.hpp" 34 | 35 | xmm::ClassParameters::ClassParameters() 36 | : changed(true), 37 | states(10, 1), 38 | gaussians(1, 1), 39 | relative_regularization(1.0e-2, 1e-20), 40 | absolute_regularization(1.0e-3, 1e-20), 41 | covariance_mode(GaussianDistribution::CovarianceMode::Full), 42 | transition_mode(HMM::TransitionMode::LeftRight), 43 | regression_estimator(HMM::RegressionEstimator::Full), 44 | hierarchical(true) { 45 | states.onAttributeChange( 46 | this, &xmm::ClassParameters::onAttributeChange); 47 | gaussians.onAttributeChange( 48 | this, &xmm::ClassParameters::onAttributeChange); 49 | relative_regularization.onAttributeChange( 50 | this, &xmm::ClassParameters::onAttributeChange); 51 | absolute_regularization.onAttributeChange( 52 | this, &xmm::ClassParameters::onAttributeChange); 53 | covariance_mode.onAttributeChange( 54 | this, &xmm::ClassParameters::onAttributeChange); 55 | transition_mode.onAttributeChange( 56 | this, &xmm::ClassParameters::onAttributeChange); 57 | regression_estimator.onAttributeChange( 58 | this, &xmm::ClassParameters::onAttributeChange); 59 | hierarchical.onAttributeChange( 60 | this, &xmm::ClassParameters::onAttributeChange); 61 | } 62 | 63 | xmm::ClassParameters::ClassParameters(ClassParameters const& src) 64 | : changed(true), 65 | states(src.states), 66 | gaussians(src.gaussians), 67 | relative_regularization(src.relative_regularization), 68 | absolute_regularization(src.absolute_regularization), 69 | covariance_mode(src.covariance_mode), 70 | transition_mode(src.transition_mode), 71 | regression_estimator(src.regression_estimator), 72 | hierarchical(src.hierarchical) { 73 | states.onAttributeChange( 74 | this, &xmm::ClassParameters::onAttributeChange); 75 | gaussians.onAttributeChange( 76 | this, &xmm::ClassParameters::onAttributeChange); 77 | relative_regularization.onAttributeChange( 78 | this, &xmm::ClassParameters::onAttributeChange); 79 | absolute_regularization.onAttributeChange( 80 | this, &xmm::ClassParameters::onAttributeChange); 81 | covariance_mode.onAttributeChange( 82 | this, &xmm::ClassParameters::onAttributeChange); 83 | transition_mode.onAttributeChange( 84 | this, &xmm::ClassParameters::onAttributeChange); 85 | regression_estimator.onAttributeChange( 86 | this, &xmm::ClassParameters::onAttributeChange); 87 | hierarchical.onAttributeChange( 88 | this, &xmm::ClassParameters::onAttributeChange); 89 | } 90 | 91 | xmm::ClassParameters::ClassParameters(Json::Value const& root) 92 | : ClassParameters() { 93 | states.set(root["states"].asInt()); 94 | gaussians.set(root["gaussians"].asInt()); 95 | relative_regularization.set(root["relative_regularization"].asFloat()); 96 | absolute_regularization.set(root["absolute_regularization"].asFloat()); 97 | covariance_mode.set(static_cast( 98 | root["covariance_mode"].asInt())); 99 | transition_mode.set( 100 | static_cast(root["transition_mode"].asInt())); 101 | regression_estimator.set(static_cast( 102 | root["regression_estimator"].asInt())); 103 | hierarchical.set(root["hierarchical"].asBool()); 104 | } 105 | 106 | xmm::ClassParameters& xmm::ClassParameters::operator=( 107 | ClassParameters const& src) { 108 | if (this != &src) { 109 | changed = true; 110 | states = src.states; 111 | gaussians = src.gaussians; 112 | relative_regularization = src.relative_regularization; 113 | absolute_regularization = src.absolute_regularization; 114 | covariance_mode = src.covariance_mode; 115 | transition_mode = src.transition_mode; 116 | regression_estimator = src.regression_estimator; 117 | states.onAttributeChange( 118 | this, &xmm::ClassParameters::onAttributeChange); 119 | gaussians.onAttributeChange( 120 | this, &xmm::ClassParameters::onAttributeChange); 121 | relative_regularization.onAttributeChange( 122 | this, &xmm::ClassParameters::onAttributeChange); 123 | absolute_regularization.onAttributeChange( 124 | this, &xmm::ClassParameters::onAttributeChange); 125 | covariance_mode.onAttributeChange( 126 | this, &xmm::ClassParameters::onAttributeChange); 127 | transition_mode.onAttributeChange( 128 | this, &xmm::ClassParameters::onAttributeChange); 129 | regression_estimator.onAttributeChange( 130 | this, &xmm::ClassParameters::onAttributeChange); 131 | hierarchical.onAttributeChange( 132 | this, &xmm::ClassParameters::onAttributeChange); 133 | } 134 | return *this; 135 | } 136 | 137 | Json::Value xmm::ClassParameters::toJson() const { 138 | Json::Value root; 139 | root["states"] = static_cast(states.get()); 140 | root["gaussians"] = static_cast(gaussians.get()); 141 | root["relative_regularization"] = relative_regularization.get(); 142 | root["absolute_regularization"] = absolute_regularization.get(); 143 | root["covariance_mode"] = static_cast(covariance_mode.get()); 144 | root["transition_mode"] = static_cast(transition_mode.get()); 145 | root["regression_estimator"] = static_cast(regression_estimator.get()); 146 | root["hierarchical"] = hierarchical.get(); 147 | return root; 148 | } 149 | 150 | void xmm::ClassParameters::fromJson(Json::Value const& root) { 151 | try { 152 | ClassParameters tmp(root); 153 | *this = tmp; 154 | } catch (JsonException& e) { 155 | throw e; 156 | } 157 | } 158 | 159 | void xmm::ClassParameters::onAttributeChange( 160 | AttributeBase* attr_pointer) { 161 | changed = true; 162 | attr_pointer->changed = false; 163 | } 164 | 165 | template <> 166 | void xmm::checkLimits( 167 | xmm::HMM::TransitionMode const& value, 168 | xmm::HMM::TransitionMode const& limit_min, 169 | xmm::HMM::TransitionMode const& limit_max) { 170 | if (value < limit_min || value > limit_max) 171 | throw std::domain_error( 172 | "Attribute value out of range. Range: [" + 173 | std::to_string(static_cast(limit_min)) + " ; " + 174 | std::to_string(static_cast(limit_max)) + "]"); 175 | } 176 | 177 | template <> 178 | xmm::HMM::TransitionMode 179 | xmm::Attribute::defaultLimitMax() { 180 | return xmm::HMM::TransitionMode::LeftRight; 181 | } 182 | 183 | template <> 184 | void xmm::checkLimits( 185 | xmm::HMM::RegressionEstimator const& value, 186 | xmm::HMM::RegressionEstimator const& limit_min, 187 | xmm::HMM::RegressionEstimator const& limit_max) { 188 | if (value < limit_min || value > limit_max) 189 | throw std::domain_error( 190 | "Attribute value out of range. Range: [" + 191 | std::to_string(static_cast(limit_min)) + " ; " + 192 | std::to_string(static_cast(limit_max)) + "]"); 193 | } 194 | 195 | template <> 196 | xmm::HMM::RegressionEstimator 197 | xmm::Attribute::defaultLimitMax() { 198 | return xmm::HMM::RegressionEstimator::Likeliest; 199 | } 200 | -------------------------------------------------------------------------------- /python/examples/data/hhmm_test_data3.txt: -------------------------------------------------------------------------------- 1 | -0.000570692 -0.00622956 0.00149215 2 | -0.000288264 -0.00661619 0.00158801 3 | -2.13865e-05 -0.00700467 0.00169089 4 | 0.000228700 -0.00742931 0.00179842 5 | 0.000436098 -0.00777401 0.00187085 6 | 0.000615549 -0.00807370 0.00192480 7 | 0.000822189 -0.00840182 0.00199079 8 | 0.00101794 -0.00870835 0.00205511 9 | 0.00116592 -0.00910740 0.00213479 10 | 0.00133486 -0.00957325 0.00221943 11 | 0.00150178 -0.0100335 0.00230741 12 | 0.00168197 -0.0104397 0.00237797 13 | 0.00189616 -0.0107851 0.00244704 14 | 0.00217165 -0.0112263 0.00253675 15 | 0.00251068 -0.0116938 0.00262004 16 | 0.00295267 -0.0126572 0.00270461 17 | 0.00332523 -0.0133075 0.00265795 18 | 0.00365202 -0.0138460 0.00256704 19 | 0.00394784 -0.0142168 0.00243298 20 | 0.00446016 -0.0146339 0.00228618 21 | 0.00515327 -0.0152224 0.00213787 22 | 0.00595497 -0.0158443 0.00199905 23 | 0.00671708 -0.0164343 0.00185688 24 | 0.00747633 -0.0169498 0.00170218 25 | 0.00825763 -0.0174546 0.00155141 26 | 0.00901797 -0.0178926 0.00139568 27 | 0.00960866 -0.0183424 0.00127820 28 | 0.0100578 -0.0190423 0.00116290 29 | 0.0104627 -0.0197978 0.00105560 30 | 0.0106718 -0.0206671 0.000888532 31 | 0.0106912 -0.0215046 0.000705203 32 | 0.0104692 -0.0220046 0.000512929 33 | 0.00998963 -0.0228193 0.000339050 34 | 0.00910980 -0.0237939 0.000161771 35 | 0.00767208 -0.0249349 -2.69665e-05 36 | 0.00601786 -0.0260297 -0.000202964 37 | 0.00288346 -0.0274495 -0.000837435 38 | -0.00195195 -0.0293517 -0.00224478 39 | -0.00916913 -0.0320656 -0.00420024 40 | -0.0197008 -0.0356778 -0.00675848 41 | -0.0302217 -0.0392353 -0.00932552 42 | -0.0443351 -0.0437239 -0.0130055 43 | -0.0637565 -0.0504855 -0.0221066 44 | -0.0891282 -0.0584260 -0.0306369 45 | -0.119905 -0.0662953 -0.0387574 46 | -0.155788 -0.0743564 -0.0454307 47 | -0.196676 -0.0824901 -0.0510124 48 | -0.237430 -0.0904744 -0.0565841 49 | -0.277977 -0.0981020 -0.0621169 50 | -0.324537 -0.102818 -0.0620642 51 | -0.374582 -0.113579 -0.0662588 52 | -0.427657 -0.122411 -0.0682242 53 | -0.479405 -0.130817 -0.0697145 54 | -0.529548 -0.138755 -0.0704307 55 | -0.577425 -0.138407 -0.0657481 56 | -0.621992 -0.137279 -0.0604373 57 | -0.661680 -0.129361 -0.0525584 58 | -0.693847 -0.120115 -0.0436425 59 | -0.716512 -0.110497 -0.0309060 60 | -0.733099 -0.0995047 -0.0187249 61 | -0.740651 -0.0888610 -0.00855780 62 | -0.736918 -0.0777070 -0.000738645 63 | -0.728055 -0.0664858 0.00601166 64 | -0.710740 -0.0534696 0.0122546 65 | -0.693426 -0.0404534 0.0184976 66 | -0.664293 -0.0282320 0.0191192 67 | -0.627833 -0.00866454 0.0237552 68 | -0.584710 0.00789656 0.0255142 69 | -0.540055 0.0274209 0.0263188 70 | -0.493520 0.0476507 0.0242860 71 | -0.447072 0.0599789 0.0140834 72 | -0.400625 0.0723071 0.00388068 73 | -0.356257 0.0797514 -0.00970875 74 | -0.313169 0.0892696 -0.0238014 75 | -0.274106 0.100702 -0.0363320 76 | -0.235658 0.116691 -0.0494464 77 | -0.197518 0.138142 -0.0637422 78 | -0.165428 0.159478 -0.0770953 79 | -0.133574 0.183777 -0.0927540 80 | -0.108831 0.215181 -0.107254 81 | -0.0836407 0.258062 -0.119695 82 | -0.0635329 0.306773 -0.131885 83 | -0.0466616 0.354183 -0.143795 84 | -0.0328714 0.412021 -0.155558 85 | -0.0206132 0.466895 -0.166366 86 | -0.00992847 0.524221 -0.173731 87 | 0.000959323 0.581975 -0.177776 88 | 0.0132545 0.649394 -0.174231 89 | 0.0221367 0.718359 -0.168934 90 | 0.0283711 0.784853 -0.163057 91 | 0.0340070 0.854438 -0.154524 92 | 0.0399842 0.920527 -0.142011 93 | 0.0418591 0.980052 -0.124482 94 | 0.0427935 1.03040 -0.107319 95 | 0.0437352 1.06322 -0.0915401 96 | 0.0433363 1.08714 -0.0764124 97 | 0.0432196 1.09493 -0.0630341 98 | 0.0407699 1.09079 -0.0506497 99 | 0.0383202 1.08665 -0.0382652 100 | 0.0340375 1.05970 -0.0259497 101 | 0.0326468 1.02072 -0.0131763 102 | 0.0307065 0.974652 -0.000786819 103 | 0.0287663 0.928584 0.0116027 104 | 0.0236303 0.873440 0.0174862 105 | 0.0199013 0.809008 0.0222752 106 | 0.0160882 0.737587 0.0256236 107 | 0.0150072 0.660590 0.0248780 108 | 0.0142007 0.582534 0.0207371 109 | 0.0175305 0.500899 0.0101682 110 | 0.0243977 0.429203 0.00136748 111 | 0.0314932 0.372076 -0.00374321 112 | 0.0399257 0.317186 -0.00214414 113 | 0.0468557 0.266666 -0.00404912 114 | 0.0557946 0.220291 -0.00517144 115 | 0.0689151 0.173949 -0.00787261 116 | 0.0870497 0.141839 -0.00894954 117 | 0.106025 0.116233 -0.0123381 118 | 0.128584 0.0958103 -0.0160152 119 | 0.154813 0.0709664 -0.0203144 120 | 0.182829 0.0455334 -0.0256982 121 | 0.211339 0.0229239 -0.0342595 122 | 0.242493 0.00661557 -0.0426295 123 | 0.271514 -0.00721035 -0.0495625 124 | 0.306150 -0.00263384 -0.0571482 125 | 0.337432 0.00689923 -0.0605366 126 | 0.370857 0.00852946 -0.0653145 127 | 0.407453 0.00332376 -0.0683644 128 | 0.446924 7.94055e-05 -0.0785385 129 | 0.491047 -0.000339966 -0.0860693 130 | 0.540706 0.00163794 -0.0918566 131 | 0.591672 0.0185872 -0.0953932 132 | 0.638904 0.0347653 -0.0999844 133 | 0.686254 0.0595759 -0.105167 134 | 0.724660 0.0702549 -0.110999 135 | 0.759397 0.0853554 -0.116208 136 | 0.790118 0.0951670 -0.119615 137 | 0.818102 0.101026 -0.114627 138 | 0.843526 0.107573 -0.108389 139 | 0.867632 0.111225 -0.0987908 140 | 0.886846 0.0912559 -0.0876099 141 | 0.901943 0.0691634 -0.0732273 142 | 0.909945 0.0579668 -0.0591780 143 | 0.909952 0.0593779 -0.0444391 144 | 0.903112 0.0634628 -0.0293408 145 | 0.892394 0.0650032 -0.0136916 146 | 0.876139 0.0641462 0.000214245 147 | 0.852355 0.0578174 0.0136677 148 | 0.822991 0.0480150 0.0291339 149 | 0.783481 0.0325434 0.0487280 150 | 0.749574 0.0299491 0.0690362 151 | 0.709462 0.0231344 0.0903128 152 | 0.667926 0.0189330 0.110202 153 | 0.626747 0.0231198 0.124583 154 | 0.582428 0.0248259 0.138899 155 | 0.540205 0.0264632 0.149897 156 | 0.497256 0.0333195 0.159965 157 | 0.453835 0.0406800 0.165809 158 | 0.410141 0.0470284 0.168159 159 | 0.371269 0.0476049 0.168092 160 | 0.333760 0.0370523 0.163381 161 | 0.295319 0.0212440 0.159626 162 | 0.256878 0.00543563 0.155871 163 | 0.222852 -0.0202984 0.150382 164 | 0.193534 -0.0399139 0.141665 165 | 0.169891 -0.0599534 0.129268 166 | 0.144512 -0.0856820 0.118298 167 | 0.124956 -0.111985 0.107890 168 | 0.110709 -0.136671 0.0945467 169 | 0.0975557 -0.162779 0.0816545 170 | 0.0886955 -0.187641 0.0675743 171 | 0.0790591 -0.209538 0.0534515 172 | 0.0679657 -0.244490 0.0411323 173 | 0.0616390 -0.281888 0.0309110 174 | 0.0557709 -0.327972 0.0242845 175 | 0.0499029 -0.374056 0.0176579 176 | 0.0431672 -0.419727 0.0147499 177 | 0.0374393 -0.463498 0.00885782 178 | 0.0322065 -0.514072 0.00416236 179 | 0.0246897 -0.568044 0.00202454 180 | 0.0180457 -0.624661 0.00110249 181 | 0.0113718 -0.681401 0.00474163 182 | 0.00549952 -0.735481 0.00902167 183 | 9.59006e-06 -0.784767 0.0117717 184 | -0.00480809 -0.836314 0.0170792 185 | -0.00962578 -0.887861 0.0223868 186 | -0.0151944 -0.935516 0.0319194 187 | -0.0207629 -0.983171 0.0414520 188 | -0.0238008 -1.01485 0.0498195 189 | -0.0265260 -1.03844 0.0577964 190 | -0.0265153 -1.05127 0.0662709 191 | -0.0257328 -1.05788 0.0744459 192 | -0.0228084 -1.06065 0.0836008 193 | -0.0198260 -1.05446 0.0941241 194 | -0.0170641 -1.03582 0.103273 195 | -0.0143925 -1.01339 0.111378 196 | -0.0126175 -0.981646 0.119555 197 | -0.0101929 -0.946790 0.125169 198 | -0.00767369 -0.899800 0.126223 199 | -0.00515443 -0.852811 0.127278 200 | -0.00282209 -0.797796 0.127524 201 | -0.000924733 -0.738780 0.126736 202 | 2.67967e-05 -0.678982 0.121970 203 | 0.000448365 -0.616479 0.116620 204 | -0.000111553 -0.554655 0.109916 205 | -0.00116122 -0.496856 0.102527 206 | -0.00325523 -0.441966 0.0943410 207 | -0.00612119 -0.393284 0.0864548 208 | -0.0109318 -0.342576 0.0773075 209 | -0.0166892 -0.296579 0.0691251 210 | -0.0227211 -0.256230 0.0611204 211 | -0.0307582 -0.215232 0.0527328 212 | -0.0398377 -0.183281 0.0434944 213 | -0.0511301 -0.150426 0.0330947 214 | -0.0636101 -0.127003 0.0249061 215 | -0.0781956 -0.103891 0.0171112 216 | -0.0956060 -0.0856100 0.00914005 217 | -0.112581 -0.0713296 0.00220268 218 | -0.129014 -0.0604895 -0.00372819 219 | -0.148322 -0.0522957 -0.00865100 220 | -0.176167 -0.0469325 -0.0121785 221 | -0.207955 -0.0424288 -0.0141127 222 | -0.239265 -0.0398411 -0.0155282 223 | -0.270576 -0.0372535 -0.0169438 224 | -0.306866 -0.0352273 -0.0115108 225 | -0.344409 -0.0337729 -0.00588757 226 | -0.383452 -0.0322697 -8.50046e-05 227 | -0.420491 -0.0314153 0.00610057 228 | -0.456218 -0.0312251 0.0132704 229 | -0.489223 -0.0316358 0.0208436 230 | -0.520200 -0.0317186 0.0286973 231 | -0.547269 -0.0310444 0.0353729 232 | -0.566323 -0.0287533 0.0413073 233 | -0.585377 -0.0264621 0.0472418 234 | -0.601349 -0.0233182 0.0524008 235 | -0.610927 -0.0196855 0.0565450 236 | -0.608753 -0.0149968 0.0589682 237 | -0.600236 -0.00974187 0.0589999 238 | -0.589158 -0.00562588 0.0584064 239 | -0.575377 -0.00169759 0.0568909 240 | -0.551452 0.000413220 0.0492898 241 | -0.525462 0.00219979 0.0411936 242 | -0.494711 0.00362562 0.0329955 243 | -0.463961 0.00505145 0.0247973 244 | -0.428660 0.00627491 0.0160012 245 | -0.392245 0.00691418 0.00774071 246 | -0.355831 0.00755345 -0.000519809 247 | -0.319703 0.00788739 -0.00782083 248 | -0.287886 0.00658608 -0.0134988 249 | -0.255159 0.00499778 -0.0191063 250 | -0.224640 0.00261189 -0.0236405 251 | -0.197109 -0.000321528 -0.0275840 252 | -0.171498 -0.00342559 -0.0298074 253 | -0.148288 -0.00623631 -0.0312325 254 | -0.127344 -0.00782629 -0.0322917 255 | -0.109102 -0.00922857 -0.0324289 256 | -0.0934610 -0.0100923 -0.0317013 257 | -0.0776301 -0.0110501 -0.0307644 258 | -0.0650585 -0.0116961 -0.0299049 259 | -0.0523244 -0.0123735 -0.0288478 260 | -0.0433985 -0.0123967 -0.0272212 261 | -0.0359939 -0.0121981 -0.0252262 262 | -0.0285134 -0.0120102 -0.0230895 263 | -0.0225479 -0.0119627 -0.0211279 264 | -0.0177616 -0.0117304 -0.0189760 265 | -0.0138009 -0.0112240 -0.0167580 266 | -0.0105736 -0.0108576 -0.0147691 267 | -0.00734630 -0.0104913 -0.0127801 268 | -0.00533452 -0.0104311 -0.0112716 269 | -0.00327563 -0.0102839 -0.00970721 270 | -0.00151242 -0.0102187 -0.00788352 271 | 0.000250785 -0.0101534 -0.00605983 272 | 0.00141258 -0.0100809 -0.00452510 273 | 0.00236182 -0.00983230 -0.00317889 274 | 0.00336154 -0.00967760 -0.00181212 275 | 0.00419882 -0.00949146 -0.000642997 276 | 0.00496665 -0.00920999 0.000207805 277 | 0.00561201 -0.00872745 0.000921911 278 | 0.00619340 -0.00816707 0.00149054 279 | 0.00677479 -0.00760670 0.00205918 280 | -------------------------------------------------------------------------------- /test/xmmTestsMultithreading.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * xmmTestsMultithreading.cpp 3 | * 4 | * Test suite for Multithreading modes of the training algorithms 5 | * 6 | * Contact: 7 | * - Jules Francoise 8 | * 9 | * This code has been initially authored by Jules Francoise 10 | * during his PhD thesis, supervised by Frederic 11 | * Bevilacqua , in the Sound Music 12 | * Movement Interaction team of the 13 | * STMS Lab - IRCAM, CNRS, UPMC (2011-2015). 14 | * 15 | * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou. 16 | * 17 | * This File is part of XMM. 18 | * 19 | * XMM is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 3 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * XMM is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with XMM. If not, see . 31 | */ 32 | 33 | #include "catch.hpp" 34 | #include "xmmTestsUtilities.hpp" 35 | #define XMM_TESTING 36 | #include "xmm.h" 37 | #include 38 | #include 39 | 40 | class MyTrainingListener { 41 | public: 42 | void onEvent(xmm::TrainingEvent const &e) { 43 | m.lock(); 44 | std::string status; 45 | if (e.status == xmm::TrainingEvent::Status::Run) 46 | status = "Run"; 47 | else if (e.status == xmm::TrainingEvent::Status::Done) 48 | status = "Done"; 49 | else if (e.status == xmm::TrainingEvent::Status::Cancel) 50 | status = "Cancel"; 51 | else if (e.status == xmm::TrainingEvent::Status::Error) 52 | status = "Error"; 53 | else if (e.status == xmm::TrainingEvent::Status::Alldone) 54 | status = "Alldone"; 55 | if (e.status != xmm::TrainingEvent::Status::Alldone) { 56 | // std::cout << "Class " + e.label + ": " + status + " 57 | // (iteration: " + std::to_string(e.iterations) + ", 58 | // progression: " + std::to_string(e.progression) + ", 59 | // log_likelihood: " + std::to_string(e.log_likelihood) + 60 | // ")" << std::endl; 61 | } else { 62 | // std::cout << "All models trained." << std::endl; 63 | } 64 | m.unlock(); 65 | } 66 | 67 | std::mutex m; 68 | }; 69 | 70 | TEST_CASE("Training with MultithreadingMode::Sequential", "[GMM]") { 71 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 72 | xmm::Multimodality::Unimodal); 73 | ts.dimension.set(3); 74 | std::vector observation(3); 75 | std::string label_a(static_cast("a")); 76 | std::string label_b(static_cast("b")); 77 | ts.addPhrase(0, label_a); 78 | ts.addPhrase(1, label_b); 79 | for (unsigned int i = 0; i < 100; i++) { 80 | observation[0] = float(i) / 100.; 81 | observation[1] = pow(float(i) / 100., 2.); 82 | observation[2] = pow(float(i) / 100., 3.); 83 | ts.getPhrase(0)->record(observation); 84 | ts.getPhrase(1)->record(observation); 85 | } 86 | xmm::GMM a; 87 | MyTrainingListener *listener = new MyTrainingListener(); 88 | a.training_events.addListener(listener, &MyTrainingListener::onEvent); 89 | a.configuration.multithreading = xmm::MultithreadingMode::Sequential; 90 | a.configuration.gaussians.set(3); 91 | CHECK_NOTHROW(a.train(&ts)); 92 | std::vector mixtureCoeffs(3); 93 | mixtureCoeffs[0] = 0.410568; 94 | mixtureCoeffs[1] = 0.309933; 95 | mixtureCoeffs[2] = 0.2795; 96 | CHECK_VECTOR_APPROX(a.models[label_a].mixture_coeffs, mixtureCoeffs); 97 | std::vector cov_c0(9); 98 | cov_c0[0] = 0.018729; 99 | cov_c0[1] = 0.00683308; 100 | cov_c0[2] = 0.00271096; 101 | cov_c0[3] = 0.00683308; 102 | cov_c0[4] = 0.00614827; 103 | cov_c0[5] = 0.00133768; 104 | cov_c0[6] = 0.00271096; 105 | cov_c0[7] = 0.00133768; 106 | cov_c0[8] = 0.00337321; 107 | CHECK_VECTOR_APPROX(a.models[label_a].components[0].covariance, cov_c0); 108 | } 109 | 110 | TEST_CASE("Training with MultithreadingMode::MultithreadingMode", "[GMM]") { 111 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 112 | xmm::Multimodality::Unimodal); 113 | ts.dimension.set(3); 114 | std::vector observation(3); 115 | ts.addPhrase(0); 116 | ts.addPhrase(1); 117 | for (unsigned int i = 0; i < 100; i++) { 118 | observation[0] = float(i) / 100.; 119 | observation[1] = pow(float(i) / 100., 2.); 120 | observation[2] = pow(float(i) / 100., 3.); 121 | ts.getPhrase(0)->record(observation); 122 | ts.getPhrase(1)->record(observation); 123 | } 124 | std::string label_a(static_cast("a")); 125 | std::string label_b(static_cast("b")); 126 | ts.getPhrase(0)->label.set(label_a); 127 | ts.getPhrase(1)->label.set(label_b); 128 | xmm::GMM a; 129 | MyTrainingListener *listener = new MyTrainingListener(); 130 | a.training_events.addListener(listener, &MyTrainingListener::onEvent); 131 | a.configuration.multithreading = xmm::MultithreadingMode::Parallel; 132 | a.configuration.gaussians.set(3); 133 | a.train(&ts); 134 | std::vector mixtureCoeffs(3); 135 | mixtureCoeffs[0] = 0.410568; 136 | mixtureCoeffs[1] = 0.309933; 137 | mixtureCoeffs[2] = 0.2795; 138 | CHECK_VECTOR_APPROX(a.models[label_a].mixture_coeffs, mixtureCoeffs); 139 | std::vector cov_c0(9); 140 | cov_c0[0] = 0.018729; 141 | cov_c0[1] = 0.00683308; 142 | cov_c0[2] = 0.00271096; 143 | cov_c0[3] = 0.00683308; 144 | cov_c0[4] = 0.00614827; 145 | cov_c0[5] = 0.00133768; 146 | cov_c0[6] = 0.00271096; 147 | cov_c0[7] = 0.00133768; 148 | cov_c0[8] = 0.00337321; 149 | CHECK_VECTOR_APPROX(a.models[label_a].components[0].covariance, cov_c0); 150 | } 151 | 152 | class BackgroundListener { 153 | public: 154 | bool trained() { return trained_; } 155 | 156 | void onTrainingEvent(xmm::TrainingEvent &e) { 157 | trained_ = (e.status == xmm::TrainingEvent::Status::Alldone); 158 | } 159 | 160 | protected: 161 | bool trained_ = false; 162 | }; 163 | 164 | TEST_CASE("Training with MultithreadingMode::Background", "[GMM]") { 165 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 166 | xmm::Multimodality::Unimodal); 167 | ts.dimension.set(3); 168 | std::vector observation(3); 169 | ts.addPhrase(0); 170 | ts.addPhrase(1); 171 | for (unsigned int i = 0; i < 100; i++) { 172 | observation[0] = float(i) / 100.; 173 | observation[1] = pow(float(i) / 100., 2.); 174 | observation[2] = pow(float(i) / 100., 3.); 175 | ts.getPhrase(0)->record(observation); 176 | ts.getPhrase(1)->record(observation); 177 | } 178 | std::string label_a(static_cast("a")); 179 | std::string label_b(static_cast("b")); 180 | ts.getPhrase(0)->label.set(label_a); 181 | ts.getPhrase(1)->label.set(label_b); 182 | xmm::GMM a; 183 | a.configuration.multithreading = xmm::MultithreadingMode::Background; 184 | a.configuration.gaussians.set(3); 185 | BackgroundListener listener; 186 | a.training_events.addListener(&listener, 187 | &BackgroundListener::onTrainingEvent); 188 | a.train(&ts); 189 | // std::cout << "training"; 190 | while (!listener.trained()) { 191 | std::cout << ""; 192 | } 193 | // std::cout << std::endl; 194 | std::vector mixtureCoeffs(3); 195 | mixtureCoeffs[0] = 0.410568; 196 | mixtureCoeffs[1] = 0.309933; 197 | mixtureCoeffs[2] = 0.2795; 198 | CHECK_VECTOR_APPROX(a.models[label_a].mixture_coeffs, mixtureCoeffs); 199 | std::vector cov_c0(9); 200 | cov_c0[0] = 0.018729; 201 | cov_c0[1] = 0.00683308; 202 | cov_c0[2] = 0.00271096; 203 | cov_c0[3] = 0.00683308; 204 | cov_c0[4] = 0.00614827; 205 | cov_c0[5] = 0.00133768; 206 | cov_c0[6] = 0.00271096; 207 | cov_c0[7] = 0.00133768; 208 | cov_c0[8] = 0.00337321; 209 | CHECK_VECTOR_APPROX(a.models[label_a].components[0].covariance, cov_c0); 210 | a.reset(); 211 | std::vector log_likelihood(100, 0.0); 212 | for (unsigned int i = 0; i < 100; i++) { 213 | observation[0] = float(i) / 100.; 214 | observation[1] = pow(float(i) / 100., 2.); 215 | observation[2] = pow(float(i) / 100., 3.); 216 | a.filter(observation); 217 | log_likelihood[i] = a.results.smoothed_log_likelihoods[0]; 218 | } 219 | } 220 | 221 | TEST_CASE("Cancel Training", "[GMM]") { 222 | xmm::TrainingSet ts(xmm::MemoryMode::OwnMemory, 223 | xmm::Multimodality::Unimodal); 224 | ts.dimension.set(3); 225 | std::vector observation(3); 226 | ts.addPhrase(0); 227 | ts.addPhrase(1); 228 | for (unsigned int i = 0; i < 100; i++) { 229 | observation[0] = float(i) / 100.; 230 | observation[1] = pow(float(i) / 100., 2.); 231 | observation[2] = pow(float(i) / 100., 3.); 232 | ts.getPhrase(0)->record(observation); 233 | ts.getPhrase(1)->record(observation); 234 | } 235 | std::string label_a(static_cast("a")); 236 | std::string label_b(static_cast("b")); 237 | ts.getPhrase(0)->label.set(label_a); 238 | ts.getPhrase(1)->label.set(label_b); 239 | xmm::GMM a; 240 | MyTrainingListener *listener = new MyTrainingListener(); 241 | a.training_events.addListener(listener, &MyTrainingListener::onEvent); 242 | a.configuration.gaussians.set(3); 243 | a.configuration.multithreading = xmm::MultithreadingMode::Background; 244 | a.train(&ts); 245 | a.cancelTraining(); 246 | CHECK(a.size() == 0); 247 | a.configuration.multithreading = xmm::MultithreadingMode::Parallel; 248 | a.train(&ts); 249 | a.cancelTraining(); 250 | CHECK(a.size() == 2); 251 | a.configuration.multithreading = xmm::MultithreadingMode::Sequential; 252 | a.train(&ts); 253 | a.cancelTraining(); 254 | CHECK(a.size() == 2); 255 | } 256 | --------------------------------------------------------------------------------