/* * Copyright (C) 2018 Emeric Poupon * * This file is part of LMS. * * LMS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LMS. If not, see . */ #include "DataNormalizer.hpp" #include #include #include namespace SOM { template static T variance(const std::vector& vec) { std::size_t size = vec.size(); if (size == 1) return T{0.}; T mean = std::accumulate(vec.begin(), vec.end(), T{0.}) / size; return std::accumulate(vec.begin(), vec.end(), T{0.}, [mean, size] (T accumulator, const T& val) { return accumulator + ((val - mean) * (val - mean) / (size - 1)); }); } DataNormalizer::DataNormalizer(std::size_t inputDimCount) : _inputDimCount(inputDimCount) { } void DataNormalizer::computeNormalizationFactors(const std::vector& inputVectors) { if (inputVectors.empty()) throw SOMException("Empty input vectors"); // For each dimension of the input, compute the min/max _minmax.clear(); _minmax.resize(_inputDimCount); for (std::size_t dimId = 0; dimId < _inputDimCount; ++dimId) { std::vector values; for (const auto& inputVector: inputVectors) { checkSameDimensions(inputVector, _inputDimCount); values.push_back(inputVector[dimId]); } auto result = std::minmax_element(values.begin(), values.end()); _minmax[dimId] = {*result.first, *result.second}; } } InputVector::value_type DataNormalizer::normalizeValue(InputVector::value_type value, std::size_t dimId) const { // clamp if (value > _minmax[dimId].max) value = _minmax[dimId].max; else if (value < _minmax[dimId].min) value = _minmax[dimId].min; return (value - _minmax[dimId].min) / (_minmax[dimId].max - _minmax[dimId].min); } void DataNormalizer::normalizeData(InputVector& a) const { checkSameDimensions(a, _inputDimCount); for (std::size_t dimId = 0; dimId < _inputDimCount; ++dimId) { a[dimId] = normalizeValue(a[dimId], dimId); } } void DataNormalizer::dump(std::ostream& os) const { for (std::size_t i = 0; i < _inputDimCount; ++i) os << "(" << _minmax[i].min << ", " << _minmax[i].max << ")"; } } // namespace SOM