seriesClassification.cpp 7.63 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>
James Frink's avatar
James Frink committed
12
13
#include <limits>
#include <algorithm>
14
15
16
17
18
#include "seriesClassification.h"
#ifdef EMSCRIPTEN
#include "emscripten/seriesClassificationEmbindings.h"
#endif

19
20
#define SEARCH_RADIUS 1

mzed's avatar
mzed committed
21
template<typename T>
mzed's avatar
mzed committed
22
seriesClassificationTemplate<T>::seriesClassificationTemplate() : hopSize(1), counter(0) {};
23

mzed's avatar
mzed committed
24
template<typename T>
mzed's avatar
mzed committed
25
seriesClassificationTemplate<T>::~seriesClassificationTemplate() {};
26

mzed's avatar
mzed committed
27
template<typename T>
mzed's avatar
mzed committed
28
bool seriesClassificationTemplate<T>::train(const std::vector<trainingSeriesTemplate<T> > &seriesSet) {
mzed's avatar
mzed committed
29
    assert(seriesSet.size() > 0);
mzed's avatar
mzed committed
30
    reset();
mzed's avatar
mzed committed
31
    vectorLength = int(seriesSet[0].input[0].size()); //TODO: check that all vectors are the same size
mzed's avatar
mzed committed
32
    bool trained = true;
mzed's avatar
mzed committed
33
    allTrainingSeries = seriesSet;
mzed's avatar
mzed committed
34
35
    minLength = maxLength = int(allTrainingSeries[0].input.size());
    for (int i = 0; i < allTrainingSeries.size(); ++i) {
mzed's avatar
mzed committed
36
        //for (auto trainingSeries : allTrainingSeries)
mzed's avatar
mzed committed
37
38
39
40
        //Global
        int newLength = int(allTrainingSeries[i].input.size());
        if (newLength < minLength) {
            minLength = newLength;
mzed's avatar
mzed committed
41
        }
mzed's avatar
mzed committed
42
43
44
45
        if (newLength > maxLength) {
            maxLength = newLength;
        }
        //Per Label
mzed's avatar
mzed committed
46
        typename std::map<std::string, minMax<int> >::iterator it = lengthsPerLabel.find(allTrainingSeries[i].label);
mzed's avatar
mzed committed
47
48
49
50
51
52
53
54
55
        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 {
56
            minMax<int> tempLengths;
mzed's avatar
mzed committed
57
58
            tempLengths.min = tempLengths.max = int(allTrainingSeries[i].input.size());
            lengthsPerLabel[allTrainingSeries[i].label] = tempLengths;
mzed's avatar
mzed committed
59
60
        }
    }
mzed's avatar
mzed committed
61
    //TODO: make this size smarter?
mzed's avatar
mzed committed
62
63
64
65
    std::vector<T> zeroVector;
    for (int i = 0; i < vectorLength; ++i) {
        zeroVector.push_back(0.0);
    }
mzed's avatar
mzed committed
66
    for (int i = 0; i < minLength; ++i ) {
mzed's avatar
mzed committed
67
        seriesBuffer.push_back(zeroVector); //set size of continuous buffer
mzed's avatar
mzed committed
68
    }
mzed's avatar
mzed committed
69
70
71
    return trained;
};

mzed's avatar
mzed committed
72
template<typename T>
mzed's avatar
mzed committed
73
void seriesClassificationTemplate<T>::reset() {
mzed's avatar
mzed committed
74
75
    allCosts.clear();
    allTrainingSeries.clear();
mzed's avatar
mzed committed
76
77
78
    lengthsPerLabel.clear();
    minLength = -1;
    maxLength = -1;
79
80
}

mzed's avatar
mzed committed
81
template<typename T>
mzed's avatar
mzed committed
82
std::string seriesClassificationTemplate<T>::run(const std::vector<std::vector<T>> &inputSeries) {
mzed's avatar
mzed committed
83
    //TODO: Check to see if trained
84
    int closestSeries = 0;
mzed's avatar
mzed committed
85
    allCosts.clear();
mzed's avatar
mzed committed
86
    T lowestCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[0].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
87
    allCosts.push_back(lowestCost);
James Frink's avatar
James Frink committed
88

mzed's avatar
mzed committed
89
    for (int i = 1; i < allTrainingSeries.size(); ++i) {
mzed's avatar
mzed committed
90
        T currentCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
91
        allCosts.push_back(currentCost);
92
93
94
95
96
        if (currentCost < lowestCost) {
            lowestCost = currentCost;
            closestSeries = i;
        }
    }
mzed's avatar
mzed committed
97
    return allTrainingSeries[closestSeries].label;
mzed's avatar
mzed committed
98
99
};

100
template<typename T>
mzed's avatar
mzed committed
101
T seriesClassificationTemplate<T>::run(const std::vector<std::vector<T>> &inputSeries, std::string label) {
mzed's avatar
mzed committed
102
    //TODO: Check to see if trained
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    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
118

mzed's avatar
mzed committed
119
120
121
122
123
124
template<typename T>
std::string seriesClassificationTemplate<T>::runContinuous(const std::vector<T> &inputVector) {
    seriesBuffer.erase(seriesBuffer.begin());
    seriesBuffer.push_back(inputVector);
    std::string returnString = "none";
    if ((counter % hopSize) == 0 ) {
mzed's avatar
mzed committed
125
        returnString = run(seriesBuffer);
mzed's avatar
mzed committed
126
127
128
129
130
131
        counter = 0;
    }
    ++counter;
    return returnString;
}

mzed's avatar
mzed committed
132
template<typename T>
mzed's avatar
mzed committed
133
std::vector<T> seriesClassificationTemplate<T>::getCosts() const{
134
135
136
    return allCosts;
}

mzed's avatar
mzed committed
137
template<typename T>
mzed's avatar
mzed committed
138
int seriesClassificationTemplate<T>::getMinLength() const{
mzed's avatar
mzed committed
139
140
141
    return minLength;
}

mzed's avatar
mzed committed
142
template<typename T>
mzed's avatar
mzed committed
143
int seriesClassificationTemplate<T>::getMinLength(std::string label) const {
mzed's avatar
mzed committed
144
    int labelMinLength = -1;
145
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
146
147
148
149
150
151
    if (it != lengthsPerLabel.end()) {
        labelMinLength = it->second.min;
    }
    return labelMinLength;
}

mzed's avatar
mzed committed
152
template<typename T>
mzed's avatar
mzed committed
153
int seriesClassificationTemplate<T>::getMaxLength() const {
mzed's avatar
mzed committed
154
155
156
    return maxLength;
}

mzed's avatar
mzed committed
157
template<typename T>
mzed's avatar
mzed committed
158
int seriesClassificationTemplate<T>::getMaxLength(std::string label) const {
mzed's avatar
mzed committed
159
    int labelMaxLength = -1;
160
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
161
162
163
164
165
166
    if (it != lengthsPerLabel.end()) {
        labelMaxLength = it->second.max;
    }
    return labelMaxLength;
}

mzed's avatar
mzed committed
167
template<typename T>
James Frink's avatar
James Frink committed
168
169
typename
seriesClassificationTemplate<T>::template minMax<T> seriesClassificationTemplate<T>::calculateCosts(std::string label) const {
mzed's avatar
mzed committed
170
    minMax<T> calculatedMinMax;
171
172
    bool foundSeries = false;
    std::vector<T> labelCosts;
173
174
    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) {
175
            foundSeries = true;
176
177
            for (int j = (i + 1); j < allTrainingSeries.size(); ++j) {
                if (allTrainingSeries[j].label == label) {
178
                    labelCosts.push_back(fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS));
179
180
181
182
                }
            }
        }
    }
183
184
185
186
187
    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 {
188
189
190
191
192
        calculatedMinMax.min = calculatedMinMax.max = 0;
    }
    return calculatedMinMax;
}

mzed's avatar
mzed committed
193
template<typename T>
James Frink's avatar
James Frink committed
194
typename seriesClassificationTemplate<T>::template minMax<T> seriesClassificationTemplate<T>::calculateCosts(std::string label1, std::string label2) const {
mzed's avatar
mzed committed
195
    minMax<T> calculatedMinMax;
196
197
    bool foundSeries = false;
    std::vector<T> labelCosts;
198
199
200
201
    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) {
202
203
                    foundSeries = true;
                    labelCosts.push_back(fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS));
204
205
206
207
                }
            }
        }
    }
208
209
210
211
212
213
214
    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;
    }
215
216
217
    return calculatedMinMax;
}

mzed's avatar
mzed committed
218
//explicit instantiation
mzed's avatar
mzed committed
219
220
template class seriesClassificationTemplate<double>;
template class seriesClassificationTemplate<float>;
mzed's avatar
mzed committed
221

222

mzed's avatar
mzed committed
223
//
mzed's avatar
mzed committed
224
//std::vector<T> seriesClassification::getCosts(const std::vector<trainingExample> &trainingSet) {
mzed's avatar
mzed committed
225
226
//    run(trainingSet);
//    return allCosts;
mzed's avatar
mzed committed
227
//}