厳密には、したほうがいい場合としないほうがいい場合があるらしい。
標準化の式は以下。各値から値全体の平均を引き、その値を標準偏差で割る。これをすべての値に対して行う。
エクセルにはSTANDARDIZEという関数がある。ただしこれを使うためには平均と標準偏差をそれぞれ別途計算する必要がある。
自前実装したコードと上記Excelで半自動計算したものと比較。同じ値が出ている。
#include <iostream> #include <vector> #include <array> using vector3f = std::vector<std::array<float, 3>>;
//! @brief データの平均を求める //! @param [in] vec データの配列 //! @return 各要素の平均 std::array<float, 3> Average(const vector3f& vec) { // 初期化 std::array<float, 3> ave; ave[0] = 0; ave[1] = 0; ave[2] = 0; // 各要素平均 for (size_t i = 0; i < vec.size(); i++) { ave[0] += vec[i][0]; ave[1] += vec[i][1]; ave[2] += vec[i][2]; } ave[0] /= vec.size(); ave[1] /= vec.size(); ave[2] /= vec.size(); return ave; }
//分散 std::array<float, 3> Distributed(const std::array<float, 3>& average, const vector3f& vec) { int n = vec.size(); std::array<float, 3> s2{ 0,0,0 }; for (int j = 0; j < 3; j++) { for (const auto& v : vec) { s2[j] += std::pow(v[j] - average[j], 2); } s2[j] = 1.f / n * s2[j]; } return s2; }
//標準偏差 std::array<float, 3> StandardDeviation(const std::array<float, 3>& average, const vector3f& vec) { std::array<float, 3> d = Distributed(average, vec); d[0] = sqrt(d[0]); d[1] = sqrt(d[1]); d[2] = sqrt(d[2]); return d; }
//標準化 平均を引いて標準偏差で割る // average 平均 // sd 標準偏差 void Standardization(vector3f& src, const std::array<float, 3>& average, const std::array<float, 3>& sd) { for (auto&& p : src) { p[0] = (p[0] - average[0]) / sd[0]; p[1] = (p[1] - average[1]) / sd[1]; p[2] = (p[2] - average[2]) / sd[2]; } }
int main() { vector3f data; data.push_back({ -1.841658711,0.324050009,1.041258931 }); data.push_back({-1.449076772,0.431593835,0.987673104 }); data.push_back({-1.04681015,0.415599823,1.049820662 }); data.push_back({-0.646572888,0.42549479,1.087714672 }); data.push_back({-0.25920701,0.599574149,0.971796691 }); data.push_back({ 0.149769783,0.497985959,1.114130974 }); data.push_back({-1.883069754,0.6849733,1.249212146 }); data.push_back({-1.481496215,0.677821219,1.303076267 }); data.push_back({-1.083532453,0.716715276,1.313803315 }); std::array<float, 3> _s = Average(data); std::array<float, 3> sd = StandardDeviation(_s, data); Standardization(data, _s, sd); for (size_t i = 0; i < data.size(); i++) { printf("%lf , %lf , %lf\n", data[i][0], data[i][1], data[i][2]); } }