質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.35%

  • C++

    2412questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

ファジィ識別器について

受付中

回答 0

投稿 2017/11/26 17:08

  • 評価
  • クリップ 0
  • VIEW 51

pontyo

score 1

#include <iostream>
#include<fstream>
#include<sstream>
#include<cmath>
#include<stdio.h>
#include<stdlib.h>

//データ数
#define N 61
//次元数
#define N_d 2
//クラス数
#define N_c 3
//個体群サイズ(ルール数)
#define N_rp 16

using namespace std;


class Fuzzy {
public:
    //コンストラクタ
    Fuzzy() {

        //ファジィルール初期化
        int i = 0;
        int j = 0;
        rule[0][0] = 1;
        rule[1][0] = 1;
        rule[2][0] = 1;
        rule[3][0] = 1;
        rule[4][0] = 2;
        rule[5][0] = 2;
        rule[6][0] = 2;
        rule[7][0] = 2;
        rule[8][0] = 3;
        rule[9][0] = 3;
        rule[10][0] = 3;
        rule[11][0] = 3;
        rule[12][0] = 0;
        rule[13][0] = 0;
        rule[14][0] = 0;
        rule[15][0] = 0;
        rule[0][1] = 1;
        rule[1][1] = 2;
        rule[2][1] = 3;
        rule[3][1] = 0;
        rule[4][1] = 1;
        rule[5][1] = 2;
        rule[6][1] = 3;
        rule[7][1] = 0;
        rule[8][1] = 1;
        rule[9][1] = 2;
        rule[10][1] = 3;
        rule[11][1] = 0;
        rule[12][1] = 1;
        rule[13][1] = 2;
        rule[14][1] = 3;
        rule[15][1] = 0;

        //ルール選択配列初期化
        for (int i = 0; i<N_rp; i++) {
            rule_select[i] = 1;
            rule_select_2[i] = 1;
        }
        fitness = 0;
    }

        //学習用データの読み込み
    void read_data() {

        double data1x[N][N_d];
        double x1[N];    //臨時配列(パターン1)
        double x2[N];    //臨時配列(パターン1)
        int c11[N];    //臨時配列(パターン1)
        int i = 0;

        FILE *fp1;
        errno_t error1;

        if ((error1 = fopen_s(&fp1, "kadai3_pattern1.txt", "r")) != 0) {
            printf("cannot open the file\n");
        }
        else {
            while (fscanf_s(fp1, "%lf,%lf,%d", &x1[i], &x2[i], &c11[i]) != EOF) {
                data[i][0] = x1[i];
                data[i][1] = x2[i];
                data[i][2] = (double)c11[i];
                i++;
            }
        }

        fclose(fp1);
        //データの格納終了


    }

    //適合度計算
    void calc_fit() {
        double a, tmp, fit;
        for (int h = 0; h < N_rp; h++) {
            for (int i = 1; i <= N; i++) {
                fit = 1;
                //各ルールでの各データパターンでの適合度計算
                for (int j = 0; j < N_d; j++) {
                    //don't care ならメンバシップ値は1
                    if ((int)rule[h][j] == 0)continue;
                    a = (double)(rule[h][j] - 1) / 2;
                    tmp = 1 - 2 * abs(a - data[i][j]);
                    if (tmp > 0) {
                        fit *= tmp;
                    }
                    else {
                        fit = 0;
                        break;
                    }
                }
                rule_fit[h][i - 1] = fit;

            }
        }
    }

    //信頼度計算
    void calc_trust() {
        //適合度の和を入れる tmp2はクラスhを指すデータの適合度の和
        double tmp, tmp2;
        for (int k = 0; k < N_rp; k++) {
            //クラスは3種
            for (int i = 0; i < 3; i++) {
                tmp = 0;
                tmp2 = 0;
                for (int j = 1; j <= N; j++) {

                    if ((int)data[j][2] == i) {
                        tmp2 += rule_fit[k][j - 1];
                    }
                    tmp += rule_fit[k][j - 1];
                }
                rule_class[k][i] = tmp2 / tmp;
            }
        }
    }

    //各ルール結論クラス決定
    void calc_class() {
        double tmp;
        int tmp_class;
        for (int i = 0; i <N_rp; i++) {
            tmp = rule_class[i][0];
            tmp_class = 0;
            //最も信頼度の高いクラスに決定
            for (int j = 1; j <3; j++) {
                if (tmp < rule_class[i][j]) {
                    tmp = rule_class[i][j];
                    tmp_class = j;
                }
            }
            //結論部クラス決定
            rule[i][2] = tmp_class;
            //ルール重み計算
            for (int j = 0; j <3; j++) {
                if (j != tmp_class) {
                    tmp -= rule_class[i][j];
                }
                //ルール重みが0以下ならそのルールは不要
                if (tmp <= 0) {
                    rule[i][4] = 0;
                    break;
                }
                rule[i][3] = tmp;
            }
        }
    }


    //総ルール長とルール数の計算
    void count_rule() {
        rule_len = 0;
        rule_num = 0;
        for (int i = 0; i<N_rp; i++) {
            if ((int)rule[i][4] == 1 && rule_select[i] == 1) {

                if ((int)rule[i][0] != 0)rule_len++;
                rule_num++;
                if ((int)rule[i][1] != 0)rule_len++;
            }
        }
    }

    //識別率計算
    void calc_ans() {
        double tmp;
        //異なる結論クラスを持つが適合度とルール重みの和が等しくなった時にチェック
        bool check = false;
        //それぞれ正解した数、合計数
        int collect_num = 0;
        int sum = 0;
        double win_tmp = 0;
        int win_num = 0;
        for (int j = 1; j <= 60; j++) {
            win_tmp = 0;
            win_num = 0;
            check = false;
            for (int i = 0; i < N_rp; i++) {

                //勝者ルールの決定

                //不使用ルール
                if ((int)rule[i][4] == 0 || rule_select[i] == 0)continue;


                tmp = rule[i][3] * rule_fit[i][j - 1];
                if (win_tmp < tmp) {
                    win_tmp = tmp;
                    win_num = i;
                    check = false;
                }
                else if (tmp == 0)continue;
                else if ((win_tmp == tmp) && (rule[win_num][2] != rule[i][2])) check = true;
            }
            //勝者ルールでの識別
            if (check == true)continue;
            else if (data[j][2] == rule[win_num][2])collect_num++;
            sum++;
        }
        ans_rate = collect_num / (double)sum;

    }

    //識別率、総ルール数、ルール長の表示
    void show1() {
        cout << "calc:" << ans_rate << endl;
        cout << "rule_num:" << rule_num << endl;
        cout << "rule_len:" << rule_len << endl;
    }

    //識別率、総ルール数、ルール長の表示
    void show2() {
        cout << "calc:" << ans_rate_2 << endl;
        cout << "rule_num:" << rule_num_2 << endl;
        cout << "rule_len:" << rule_len_2 << endl;
    }

    //ファジィルール集合選択
    void create_rule(int num) {
        if (num == 0) {
            for (int i = 0; i < 2; i++) {
                rule_select[num] = i;
                //識別率の計算
                calc_ans();
                //ルール数と相ルール長の計算
                count_rule();
                //加重和適応度の計算
                if ((1000 * ans_rate - rule_num - rule_len) > fitness) {
                    fitness = 1000 * ans_rate - rule_num - rule_len;
                    ans_rate_2 = ans_rate;
                    rule_len_2 = rule_len;
                    rule_num_2 = rule_num;
                    for (int j = 0; j<N_rp; j++) {
                        rule_select_2[j] = rule_select[j];
                    }
                }
            }
        }
        else {
            for (int i = 0; i<2; i++) {
                rule_select[num] = i;
                create_rule(num - 1);
            }

        }
    }


protected:
    ///////////////////データ読み込みに関するメンバ

    //学習データ格納 要素,クラスの順 0行目は入力データの情報 1行目からデータ
    double data[N][N_d + 1];




    //ルール配列 条件ファジイ集合,結論クラス,ルール重み、利用bitの順 利用bitが1ならそのルールは使用しない
    double rule[N_rp][5];
    //各ルールの適合度計算
    double rule_fit[N_rp][N];
    //各ルールの信頼度計算
    double rule_class[N_rp][3];
    //ルール数
    int rule_num;
    //総ルール長
    int rule_len;
    //識別率
    double ans_rate;
    //ルール集合選択配列
    int rule_select[N_rp];
    //加重和適応度
    double fitness;

    //ルール集合選択後の結果
    //ルール数
    int rule_num_2;
    //総ルール長
    int rule_len_2;
    //識別率
    double ans_rate_2;
    //ルール集合選択配列
    int rule_select_2[N_rp];



};


int main() {

    ////////////////準備///////////////////////
    //オブジェクト生成
    Fuzzy fuzzy;

    //学習データ読み込み
    fuzzy.read_data();

    /////////////////////学習開始/////////////////////////
    ////適合度計算
    fuzzy.calc_fit();
    ////信頼度計算
    fuzzy.calc_trust();
    ////結論部クラス決定、ルール重み計算
    fuzzy.calc_class();
    fuzzy.count_rule();


    ////////////未知パターン識別////////////////
    ////識別率計算
    fuzzy.calc_ans();

    fuzzy.show1();


    ////ファジィルール選択
    fuzzy.create_rule(15);

    fuzzy.show2();

    return 0;
}

      ファジィ識別器をC++で作成しています。show1,show2関数で識別率、ルール数、総ルール長を表示するようにしています。実行結果は、show1では、順に91.667,0,0となり、show2では93.0,0,0となりました。識別率に関しては正解データと一致しました。ただ、ルール数と総ルール長はshow1に関しては13,22で、show2に関しては5,8が正解となります。どこで間違っているのかがよく分からないのでよろしければ教えてください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.35%

関連した質問

  • 解決済

    二分法(2変数)

    前提・実現したいこと xを0から2πまで動かしたとき、cos(x)+cos(y)=0 をyについて解きたいです。 発生している問題・エラーメッセージ xを動かしてもyが動

  • 受付中

    この問題のプログラムはどうなるのですか?

    実現したいこと 初歩的な質問だとは思うのですが、答えていただけると幸いです 下の問題を解くとプログラムはどういう風になるのかプログラムを書いていただけると幸いです。 お願いし

  • 解決済

    double型の範囲について

    前提・実現したいこと 毎度お世話になっております。グラフで曲線を描きたいと思っております。 結果を格納する変数にdouble型を用いているのですが、途中から値がおかしくなります

  • 解決済

    配列の要素間の和を全パターン求めるプログラムを作成したい。

    皆様ありがとうございました。 前提・実現したいこと <CもしくはC++> 配列の要素間の和を全パターン求めるプログラムを作成したい。 【例】 /*-------------

  • 受付中

    Ajax通信でCGIを使いJSONデータを操作したいです

    前提・実現したいこと AjaxでPOST関数を使い、C++で作成したCGIを呼び出し、JSONデータを取得したいです。 Ajaxからは JSONデータを送信しています。 そのため、

  • 解決済

    [c]一つのデータでカラム数が変わるデータの読み込み

    質問失礼します。プログラム初心者です。 以下のような〜〜〜.datを fp1 = fopen(fname1,"r"); while((ret = fscanf(fp1,"%d %d

  • 解決済

    ファイル名に変数を用いて繰り返し読み込み処理を行いたい

    現在画像編集のプログラムopnCVとC++を用いた上で作成している初歩的段階です。 複数枚の画像に対してimreaの処理をかけた上で繰り返し画像の読み込み画像番号順に(1から並んで

  • 解決済

    【vector】vector.erase()を高速化したい

     解決済みですが、まだまだこんなのあるよ!という方のコメントを随時募集してます! 前提・実現したいこと タイトルの通り、C++のSTLコンテナの一つvectorクラスの"vecto

同じタグがついた質問を見る

  • C++

    2412questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。