seriesClassification.cpp 6.5 KB
Newer Older
mzed's avatar
mzed committed
1
2
3
4
5
6
7
8
/**
 *  @file seriesClassification.cpp
 *  RapidLib
 *
 *  @author Michael Zbyszynski
 *  @date 08 Jun 2017
 *  @copyright Copyright © 2017 Goldsmiths. All rights reserved.
 */
9
10

#include <vector>
mzed's avatar
mzed committed
11
#include <cassert>
12
13
14
15
16
#include "seriesClassification.h"
#ifdef EMSCRIPTEN
#include "emscripten/seriesClassificationEmbindings.h"
#endif

17
18
#define SEARCH_RADIUS 1

mzed's avatar
mzed committed
19
20
template<typename T>
seriesClassification<T>::seriesClassification() {};
21

mzed's avatar
mzed committed
22
23
template<typename T>
seriesClassification<T>::~seriesClassification() {};
24

mzed's avatar
mzed committed
25
26
template<typename T>
bool seriesClassification<T>::train(const std::vector<trainingSeries<T> > &seriesSet) {
mzed's avatar
mzed committed
27
    assert(seriesSet.size() > 0);
mzed's avatar
mzed committed
28
29
    reset();
    bool trained = true;
mzed's avatar
mzed committed
30
    allTrainingSeries = seriesSet;
mzed's avatar
mzed committed
31
32
    minLength = maxLength = int(allTrainingSeries[0].input.size());
    for (int i = 0; i < allTrainingSeries.size(); ++i) {
mzed's avatar
mzed committed
33
34
35
36
        //Global
        int newLength = int(allTrainingSeries[i].input.size());
        if (newLength < minLength) {
            minLength = newLength;
mzed's avatar
mzed committed
37
        }
mzed's avatar
mzed committed
38
39
40
41
        if (newLength > maxLength) {
            maxLength = newLength;
        }
        //Per Label
mzed's avatar
mzed committed
42
        typename std::map<std::string, minMax<int> >::iterator it = lengthsPerLabel.find(allTrainingSeries[i].label);
mzed's avatar
mzed committed
43
44
45
46
47
48
49
50
51
        if (it != lengthsPerLabel.end()) {
            int newLength = int(allTrainingSeries[i].input.size());
            if (newLength < it->second.min) {
                it->second.min = newLength;
            }
            if (newLength > it->second.max) {
                it->second.max = newLength;
            }
        } else {
52
            minMax<int> tempLengths;
mzed's avatar
mzed committed
53
54
            tempLengths.min = tempLengths.max = int(allTrainingSeries[i].input.size());
            lengthsPerLabel[allTrainingSeries[i].label] = tempLengths;
mzed's avatar
mzed committed
55
56
        }
    }
mzed's avatar
mzed committed
57
58
59
    return trained;
};

mzed's avatar
mzed committed
60
61
template<typename T>
void seriesClassification<T>::reset() {
mzed's avatar
mzed committed
62
63
    allCosts.clear();
    allTrainingSeries.clear();
mzed's avatar
mzed committed
64
65
66
    lengthsPerLabel.clear();
    minLength = -1;
    maxLength = -1;
67
68
}

mzed's avatar
mzed committed
69
70
template<typename T>
std::string seriesClassification<T>::run(const std::vector<std::vector<T>> &inputSeries) {
71
    int closestSeries = 0;
mzed's avatar
mzed committed
72
    allCosts.clear();
mzed's avatar
mzed committed
73
    T lowestCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[0].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
74
    allCosts.push_back(lowestCost);
mzed's avatar
mzed committed
75
76
    
    for (int i = 1; i < allTrainingSeries.size(); ++i) {
mzed's avatar
mzed committed
77
        T currentCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
78
        allCosts.push_back(currentCost);
79
80
81
82
83
        if (currentCost < lowestCost) {
            lowestCost = currentCost;
            closestSeries = i;
        }
    }
mzed's avatar
mzed committed
84
    return allTrainingSeries[closestSeries].label;
mzed's avatar
mzed committed
85
86
};

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
template<typename T>
T seriesClassification<T>::run(const std::vector<std::vector<T>> &inputSeries, std::string label) {
    int closestSeries = 0;
    allCosts.clear();
    T lowestCost = std::numeric_limits<T>::max();
    for (int i = 0; i < allTrainingSeries.size(); ++i) {
        if (allTrainingSeries[i].label == label) {
            T currentCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS);
            allCosts.push_back(currentCost);
            if (currentCost < lowestCost) {
                lowestCost = currentCost;
                closestSeries = i;
            }
        }
    }
    return lowestCost;
};
mzed's avatar
mzed committed
104

mzed's avatar
mzed committed
105
template<typename T>
106
std::vector<T> seriesClassification<T>::getCosts() const{
107
108
109
    return allCosts;
}

mzed's avatar
mzed committed
110
template<typename T>
111
int seriesClassification<T>::getMinLength() const{
mzed's avatar
mzed committed
112
113
114
    return minLength;
}

mzed's avatar
mzed committed
115
template<typename T>
116
int seriesClassification<T>::getMinLength(std::string label) const {
mzed's avatar
mzed committed
117
    int labelMinLength = -1;
118
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
119
120
121
122
123
124
    if (it != lengthsPerLabel.end()) {
        labelMinLength = it->second.min;
    }
    return labelMinLength;
}

mzed's avatar
mzed committed
125
template<typename T>
126
int seriesClassification<T>::getMaxLength() const {
mzed's avatar
mzed committed
127
128
129
    return maxLength;
}

mzed's avatar
mzed committed
130
template<typename T>
131
int seriesClassification<T>::getMaxLength(std::string label) const {
mzed's avatar
mzed committed
132
    int labelMaxLength = -1;
133
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
134
135
136
137
138
139
    if (it != lengthsPerLabel.end()) {
        labelMaxLength = it->second.max;
    }
    return labelMaxLength;
}

mzed's avatar
mzed committed
140
template<typename T>
141
seriesClassification<T>::minMax<T> seriesClassification<T>::calculateCosts(std::string label) const {
mzed's avatar
mzed committed
142
    minMax<T> calculatedMinMax;
143
144
    bool foundSeries = false;
    std::vector<T> labelCosts;
145
146
    for (int i = 0; i < (allTrainingSeries.size() - 1); ++i) { //these loops are a little different than the two-label case
        if (allTrainingSeries[i].label == label) {
147
            foundSeries = true;
148
149
            for (int j = (i + 1); j < allTrainingSeries.size(); ++j) {
                if (allTrainingSeries[j].label == label) {
150
                    labelCosts.push_back(fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS));
151
152
153
154
                }
            }
        }
    }
155
156
157
158
159
    if (foundSeries) {
        auto minmax_result = std::minmax_element(std::begin(labelCosts), std::end(labelCosts));
        calculatedMinMax.min = *minmax_result.first;
        calculatedMinMax.max = *minmax_result.second;
    } else {
160
161
162
163
164
        calculatedMinMax.min = calculatedMinMax.max = 0;
    }
    return calculatedMinMax;
}

mzed's avatar
mzed committed
165
template<typename T>
166
seriesClassification<T>::minMax<T> seriesClassification<T>::calculateCosts(std::string label1, std::string label2) const {
mzed's avatar
mzed committed
167
    minMax<T> calculatedMinMax;
168
169
    bool foundSeries = false;
    std::vector<T> labelCosts;
170
171
172
173
    for (int i = 0; i < (allTrainingSeries.size()); ++i) {
        if (allTrainingSeries[i].label == label1) {
            for (int j = 0; j < allTrainingSeries.size(); ++j) {
                if (allTrainingSeries[j].label == label2) {
174
175
                    foundSeries = true;
                    labelCosts.push_back(fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS));
176
177
178
179
                }
            }
        }
    }
180
181
182
183
184
185
186
    if (foundSeries) {
        auto minmax_result = std::minmax_element(std::begin(labelCosts), std::end(labelCosts));
        calculatedMinMax.min = *minmax_result.first;
        calculatedMinMax.max = *minmax_result.second;
    } else {
        calculatedMinMax.min = calculatedMinMax.max = 0;
    }
187
188
189
    return calculatedMinMax;
}

mzed's avatar
mzed committed
190
191
192
193
//explicit instantiation
template class seriesClassification<double>;
template class seriesClassification<float>;

194

mzed's avatar
mzed committed
195
//
mzed's avatar
mzed committed
196
//std::vector<T> seriesClassification::getCosts(const std::vector<trainingExample> &trainingSet) {
mzed's avatar
mzed committed
197
198
199
//    run(trainingSet);
//    return allCosts;
//}