1 | /**
|
2 | * Encoder of categorical values to integers. For k different values, encoding yields integer
|
3 | * numbers from 0 to k-1 (inclusive)
|
4 | */
|
5 | export default class LabelEncoder {
|
6 | constructor() {
|
7 | /**
|
8 | * Dictionary mapping class labels to class indices.
|
9 | *
|
10 | * @var dict[string => int]
|
11 | */
|
12 | this.labelsClassIndex = {};
|
13 |
|
14 | /**
|
15 | * Array of class labels for class indices
|
16 | *
|
17 | * @var Array[string]
|
18 | */
|
19 | this.classIndicesLabel = [];
|
20 |
|
21 | /**
|
22 | * Number of unique class labels
|
23 | *
|
24 | * @var int
|
25 | */
|
26 | this.numLabels = 0;
|
27 | }
|
28 |
|
29 | /**
|
30 | * Encode a set of labels or a single label
|
31 | *
|
32 | * @param mixed|Array[mixed] labels Single label or list of labels. Each label should support the
|
33 | * toString() method
|
34 | * @return int|Array[int] Single encoded label or list of encoded labels (i.e., integers
|
35 | * associated with the input labels)
|
36 | */
|
37 | encode(labels) {
|
38 | // In case multiple labels are passed, encode them one-by-one
|
39 | if (Array.isArray(labels)) {
|
40 | return labels.map(label => this.encode(label));
|
41 | }
|
42 |
|
43 | // In case a single label is passed, encode it
|
44 | const labelString = labels.toString();
|
45 |
|
46 | if (typeof this.labelsClassIndex[labelString] === 'undefined') {
|
47 | this.labelsClassIndex[labelString] = this.numLabels;
|
48 | this.classIndicesLabel.push(labelString);
|
49 | this.numLabels += 1;
|
50 | }
|
51 |
|
52 | return this.labelsClassIndex[labelString];
|
53 | }
|
54 |
|
55 | /**
|
56 | * Decode a set of labels or a single label
|
57 | *
|
58 | * @param int|Array[int] encodedLabels Single encoded label or list of encoded labels
|
59 | * @return int|Array[int] Single decoded label or list of decoded labels
|
60 | */
|
61 | decode(encodedLabels) {
|
62 | // In case multiple labels are passed, decode them one-by-one
|
63 | if (Array.isArray(encodedLabels)) {
|
64 | return encodedLabels.map(label => this.decode(label));
|
65 | }
|
66 |
|
67 | // In case a single label is passed, decode it
|
68 | return (typeof this.classIndicesLabel[encodedLabels] === 'undefined') ? -1 : this.classIndicesLabel[encodedLabels];
|
69 | }
|
70 | }
|