seriesClassification.cpp 7.32 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
template<typename T>
mzed's avatar
mzed committed
20
seriesClassificationTemplate<T>::seriesClassificationTemplate() : hopSize(1), counter(0) {};
21

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

mzed's avatar
mzed committed
25
template<typename T>
mzed's avatar
mzed committed
26
bool seriesClassificationTemplate<T>::train(const std::vector<trainingSeriesTemplate<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
        //for (auto trainingSeries : allTrainingSeries)
mzed's avatar
mzed committed
34
35
36
37
        //Global
        int newLength = int(allTrainingSeries[i].input.size());
        if (newLength < minLength) {
            minLength = newLength;
mzed's avatar
mzed committed
38
        }
mzed's avatar
mzed committed
39
40
41
42
        if (newLength > maxLength) {
            maxLength = newLength;
        }
        //Per Label
mzed's avatar
mzed committed
43
        typename std::map<std::string, minMax<int> >::iterator it = lengthsPerLabel.find(allTrainingSeries[i].label);
mzed's avatar
mzed committed
44
45
46
47
48
49
50
51
52
        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 {
53
            minMax<int> tempLengths;
mzed's avatar
mzed committed
54
55
            tempLengths.min = tempLengths.max = int(allTrainingSeries[i].input.size());
            lengthsPerLabel[allTrainingSeries[i].label] = tempLengths;
mzed's avatar
mzed committed
56
57
        }
    }
mzed's avatar
mzed committed
58
59
60
61
    //TODO: make this size smarter?
    for (int i = 0; i < maxLength; ++i ) {
        seriesBuffer.push_back({0}); //set size of continuous buffer
    }
mzed's avatar
mzed committed
62
63
64
    return trained;
};

mzed's avatar
mzed committed
65
template<typename T>
mzed's avatar
mzed committed
66
void seriesClassificationTemplate<T>::reset() {
mzed's avatar
mzed committed
67
68
    allCosts.clear();
    allTrainingSeries.clear();
mzed's avatar
mzed committed
69
70
71
    lengthsPerLabel.clear();
    minLength = -1;
    maxLength = -1;
72
73
}

mzed's avatar
mzed committed
74
template<typename T>
mzed's avatar
mzed committed
75
std::string seriesClassificationTemplate<T>::run(const std::vector<std::vector<T>> &inputSeries) {
mzed's avatar
mzed committed
76
    //TODO: Check to see if trained
77
    int closestSeries = 0;
mzed's avatar
mzed committed
78
    allCosts.clear();
mzed's avatar
mzed committed
79
    T lowestCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[0].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
80
    allCosts.push_back(lowestCost);
mzed's avatar
mzed committed
81
82
    
    for (int i = 1; i < allTrainingSeries.size(); ++i) {
mzed's avatar
mzed committed
83
        T currentCost = fastDTW<T>::getCost(inputSeries, allTrainingSeries[i].input, SEARCH_RADIUS);
mzed's avatar
mzed committed
84
        allCosts.push_back(currentCost);
85
86
87
88
89
        if (currentCost < lowestCost) {
            lowestCost = currentCost;
            closestSeries = i;
        }
    }
mzed's avatar
mzed committed
90
    return allTrainingSeries[closestSeries].label;
mzed's avatar
mzed committed
91
92
};

93
template<typename T>
mzed's avatar
mzed committed
94
T seriesClassificationTemplate<T>::run(const std::vector<std::vector<T>> &inputSeries, std::string label) {
mzed's avatar
mzed committed
95
    //TODO: Check to see if trained
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    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
111

mzed's avatar
mzed committed
112
113
114
115
116
117
118
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 ) {
        returnString =
        counter = 0;
    }
    ++counter;
    return returnString;
}

mzed's avatar
mzed committed
125
template<typename T>
mzed's avatar
mzed committed
126
std::vector<T> seriesClassificationTemplate<T>::getCosts() const{
127
128
129
    return allCosts;
}

mzed's avatar
mzed committed
130
template<typename T>
mzed's avatar
mzed committed
131
int seriesClassificationTemplate<T>::getMinLength() const{
mzed's avatar
mzed committed
132
133
134
    return minLength;
}

mzed's avatar
mzed committed
135
template<typename T>
mzed's avatar
mzed committed
136
int seriesClassificationTemplate<T>::getMinLength(std::string label) const {
mzed's avatar
mzed committed
137
    int labelMinLength = -1;
138
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
139
140
141
142
143
144
    if (it != lengthsPerLabel.end()) {
        labelMinLength = it->second.min;
    }
    return labelMinLength;
}

mzed's avatar
mzed committed
145
template<typename T>
mzed's avatar
mzed committed
146
int seriesClassificationTemplate<T>::getMaxLength() const {
mzed's avatar
mzed committed
147
148
149
    return maxLength;
}

mzed's avatar
mzed committed
150
template<typename T>
mzed's avatar
mzed committed
151
int seriesClassificationTemplate<T>::getMaxLength(std::string label) const {
mzed's avatar
mzed committed
152
    int labelMaxLength = -1;
153
    typename std::map<std::string, minMax<int> >::const_iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
154
155
156
157
158
159
    if (it != lengthsPerLabel.end()) {
        labelMaxLength = it->second.max;
    }
    return labelMaxLength;
}

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

mzed's avatar
mzed committed
185
template<typename T>
mzed's avatar
mzed committed
186
seriesClassificationTemplate<T>::minMax<T> seriesClassificationTemplate<T>::calculateCosts(std::string label1, std::string label2) const {
mzed's avatar
mzed committed
187
    minMax<T> calculatedMinMax;
188
189
    bool foundSeries = false;
    std::vector<T> labelCosts;
190
191
192
193
    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) {
194
195
                    foundSeries = true;
                    labelCosts.push_back(fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS));
196
197
198
199
                }
            }
        }
    }
200
201
202
203
204
205
206
    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;
    }
207
208
209
    return calculatedMinMax;
}

mzed's avatar
mzed committed
210
//explicit instantiation
mzed's avatar
mzed committed
211
212
template class seriesClassificationTemplate<double>;
template class seriesClassificationTemplate<float>;
mzed's avatar
mzed committed
213

214

mzed's avatar
mzed committed
215
//
mzed's avatar
mzed committed
216
//std::vector<T> seriesClassification::getCosts(const std::vector<trainingExample> &trainingSet) {
mzed's avatar
mzed committed
217
218
//    run(trainingSet);
//    return allCosts;
mzed's avatar
mzed committed
219
//}