4章は判断木の構成で、データの属するカテゴリと各属性に対する判別結果を入力データとして与え、どの判断を用いて分類すればよいかの選択を支援するプログラムと、後半ではそれを確率探索しています。
後半はまあいいかと思ったので前半部だけ。

/**
  判断木の構成を支援するプログラム
  (判断木を構成するためには、与えられたデータセットを
  適切に分類する属性を選択しなければならない。そこで
  ある属性を選んだ場合にどのように分類されるかを計算
  する。)
  入力は標準入力から与え、出力は標準出力に出力します
  使い方:
    $./decision < (入力ファイル名) > (出力ファイル名)
  入力ファイルでは、属性とカテゴリを0/1で記述します
  出力ファイルには、分類結果を表示します
 **/

#include <iostream>
#include <vector>
#include <sstream>
#include "utf8Func.hpp"
using namespace std;

int stringToInt(const string &str)
{
    int num;
    stringstream ss;
    ss << str;
    ss >> num;
    return num;
}

/**データを読み込んでvectorに格納**/
void readData(vector< vector<int> > &data)
{
    string line;
    while(getline(cin,  line)){
        vector<string> bufferString = split_utf8(line);
        vector<int>    bufferInt;
        for(int i=0; i<bufferString.size(); ++i){
            bufferInt.push_back(stringToInt(bufferString[i]));
        }
        data.push_back(bufferInt);
    }
}

/**属性の評価**/
void evaluateProperty(const vector< vector<int> > &data, const int &i, const int &answer)
{
    int numTotal = 0;
    int numCorrect = 0;
    for(int j=0; j<data.size(); ++j){
        // 求める解答をしているデータがあれば
        if(data[j][i] == answer){
            ++numTotal;
            // 解答が正しい分類に合致していたら
            if(data[j][i] == data[j].back()) ++numCorrect;
        }
    }
    cout << numCorrect << "/" << numTotal << "t"
         << (double)numCorrect/numTotal << endl;
}

int main()
{
    // 解答番号
    const int yes = 1;
    const int no  = 0;

    vector< vector<int> > data;
    readData(data);

    // 各属性による分類
    for(int i=0; i<data[0].size()-1; ++i){
        cout << "property" <<  i+1 << endl;
        // Yesに対応した学習データの数え上げ
        cout << "Yes" << "t";
        evaluateProperty(data,  i,  yes);
        // Noに対応した学習データの数え上げ
        cout << "No" << "t";
        evaluateProperty(data,  i,  no);
        cout << endl;
    }

    return 0;
}

utf8Func.hppはこれ

#ifndef __UTF8FUNC_HPP__
#define __UTF8FUNC_HPP__

#include <vector>
#include <string>

/**utf-8のstringを一文字ずつ分割する**/
std::vector<std::string> split_utf8(const std::string& str) {
    std::vector<std::string> result;
    std::string              tmp;
    bool                     first = true;

    for (size_t i=0; i<=str.size(); ++i) {
        // 各バイトがutf-8の先頭かどうかをチェック
        if (first ||
                (i != str.size() && (str.at(i) & 0xC0) == 0x80)) {
            tmp += str.at(i);
            first = false;
            continue;
        }
        result.push_back(tmp);
        tmp.clear();
        if (i == str.size()) break;
        tmp += str.at(i);
    }
    return result;
};

#endif

5章は遺伝的アルゴリズムはいったん飛ばして、たぶん次は6章のニューラルネットワークのつもり

関連記事

fitbitの睡眠スコアを90弱で安定させる良い睡眠を続ける簡単な方法

m1 ipad pro 12.9 2021のusb-cハブはコレがベスト

Time Machine不要!Macを11.2.3にダウングレードして原神をm1 macbook airでプレイする

MH-Z19CとM5StickCで二酸化炭素濃度モニタリング

【神軽量HMD】Avegant Glyph 改造: 瓶詰堂さんのaltglyphを作った

PC、iPad、Android、switchもドックいらず!あまりに万能なusb-cハブが最強だった

コメント

コメントを返信する

メールアドレスが公開されることはありません。 が付いている欄は必須項目です