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

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

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

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

mzed's avatar
mzed committed
117
118
119
120
121
122
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
123
        returnString = run(seriesBuffer);
mzed's avatar
mzed committed
124
125
126
127
128
129
        counter = 0;
    }
    ++counter;
    return returnString;
}

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

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

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

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

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

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

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

mzed's avatar
mzed committed
215
//explicit instantiation
mzed's avatar
mzed committed
216
217
template class seriesClassificationTemplate<double>;
template class seriesClassificationTemplate<float>;
mzed's avatar
mzed committed
218

219

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