seriesClassification.cpp 6.44 KB
Newer Older
1
2
//
//  seriesClassification.cpp
mzed's avatar
mzed committed
3
//  RapidLib
4
//
mzed's avatar
mzed committed
5
//  Created by Michael Zbyszynski on 08/06/2017.
6
7
8
9
//  Copyright © 2017 Goldsmiths. All rights reserved.
//

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

16
17
#define SEARCH_RADIUS 1

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

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

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

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

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

mzed's avatar
mzed committed
86

mzed's avatar
mzed committed
87
88
template<typename T>
std::vector<T> seriesClassification<T>::getCosts() {
89
90
91
    return allCosts;
}

mzed's avatar
mzed committed
92
93
template<typename T>
int seriesClassification<T>::getMinLength() {
mzed's avatar
mzed committed
94
95
96
    return minLength;
}

mzed's avatar
mzed committed
97
98
template<typename T>
int seriesClassification<T>::getMinLength(std::string label) {
mzed's avatar
mzed committed
99
    int labelMinLength = -1;
mzed's avatar
mzed committed
100
    typename std::map<std::string, minMax<int> >::iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
101
102
103
104
105
106
    if (it != lengthsPerLabel.end()) {
        labelMinLength = it->second.min;
    }
    return labelMinLength;
}

mzed's avatar
mzed committed
107
108
template<typename T>
int seriesClassification<T>::getMaxLength() {
mzed's avatar
mzed committed
109
110
111
    return maxLength;
}

mzed's avatar
mzed committed
112
113
template<typename T>
int seriesClassification<T>::getMaxLength(std::string label) {
mzed's avatar
mzed committed
114
    int labelMaxLength = -1;
mzed's avatar
mzed committed
115
    typename std::map<std::string, minMax<int> >::iterator it = lengthsPerLabel.find(label);
mzed's avatar
mzed committed
116
117
118
119
120
121
    if (it != lengthsPerLabel.end()) {
        labelMaxLength = it->second.max;
    }
    return labelMaxLength;
}

mzed's avatar
mzed committed
122
123
124
125
126
template<typename T>
seriesClassification<T>::minMax<T> seriesClassification<T>::calculateCosts(std::string label) {
    minMax<T> calculatedMinMax;
    calculatedMinMax.min = std::numeric_limits<T>::max();
    calculatedMinMax.max = std::numeric_limits<T>::min();
127
128
129
130
131
132
133
    int numSeries = 0;
    
    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) {
            for (int j = (i + 1); j < allTrainingSeries.size(); ++j) {
                if (allTrainingSeries[j].label == label) {
                    numSeries++;
mzed's avatar
mzed committed
134
                    T currentCost = fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS);
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
                    if (numSeries == 1) {
                        calculatedMinMax.min = calculatedMinMax.max = currentCost; //first match is both min and max
                    } else {
                        if (currentCost < calculatedMinMax.min) {
                            calculatedMinMax.min = currentCost;
                        }
                        if (currentCost > calculatedMinMax.max) {
                            calculatedMinMax.max = currentCost;
                        }
                    }
                }
            }
        }
    }
    if (numSeries == 0) {
        calculatedMinMax.min = calculatedMinMax.max = 0;
    }
    return calculatedMinMax;
}

mzed's avatar
mzed committed
155
156
157
158
159
template<typename T>
seriesClassification<T>::minMax<T> seriesClassification<T>::calculateCosts(std::string label1, std::string label2) {
    minMax<T> calculatedMinMax;
    calculatedMinMax.min = std::numeric_limits<T>::max();
    calculatedMinMax.max = std::numeric_limits<T>::min();
160
161
162
163
164
165
166
    int numSeries = 0;
    
    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) {
                    numSeries++;
mzed's avatar
mzed committed
167
                    T currentCost = fastDTW<T>::getCost(allTrainingSeries[i].input, allTrainingSeries[j].input, SEARCH_RADIUS);
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
                    if (numSeries == 1) {
                        calculatedMinMax.min = calculatedMinMax.max = currentCost; //first match is both min and max
                    } else {
                        if (currentCost < calculatedMinMax.min) {
                            calculatedMinMax.min = currentCost;
                        }
                        if (currentCost > calculatedMinMax.max) {
                            calculatedMinMax.max = currentCost;
                        }
                    }
                }
            }
        }
    }
    return calculatedMinMax;
}

mzed's avatar
mzed committed
185
186
187
188
//explicit instantiation
template class seriesClassification<double>;
template class seriesClassification<float>;

189

mzed's avatar
mzed committed
190
//
mzed's avatar
mzed committed
191
//std::vector<T> seriesClassification::getCosts(const std::vector<trainingExample> &trainingSet) {
mzed's avatar
mzed committed
192
193
194
//    run(trainingSet);
//    return allCosts;
//}