JavaScriptマシン学習のKNNアルゴリズム


機械の勉強は簡単ですね.手を動かしてみてください.
Machine Learning with JavaScript:Part 2
Funebug
可読性を保証するために、本文は直訳ではなく意訳を採用する.また、この著作権は元の作者に帰属し、翻訳は学習にのみ使用されます.また、原文のコードの誤りを修正しました.
上の図はplot.lyで描かれています.
前回はJavaScriptで線形企画を実現しました.今回はKNNアルゴリズムについてお話します.
KNNはK-Neares-Neighboursの略語で、学習アルゴリズムを監督するものです.KNNアルゴリズムは分類にも使えるし、回帰問題の解決にも使える.
GitHub倉庫:machine-learning-with-js
KNNアルゴリズムの概要
簡単に言えば、KNNアルゴリズムは自分の一番近いK個のポイントから投票して分類データをどの種類にするかを決定します.
分類されるデータにこれらの隣接データがある場合、NJ:7、NJ:0、IN:4、つまり7つのNJ隣、0つのNJ隣、4つのIN隣があるなら、このデータはNYに分類されるべきです.
郵便局で働くと、郵便配達員のために郵便物を割り当てるのが仕事です.目的は各コミュニティへの配達を最小限にすることです.全部で7ブロックあると仮定してもいいです.これは実際の分類問題です.これらの手紙を分類して、どのコミュニティに属するかを決めます.例えば、上東城、マンハッタン下城などです.
最悪の案は郵便配達員に自由に手紙を割り当てることです.そうすると、各郵便配達員は各コミュニティの手紙を受け取ることができます.
最善の方案は手紙の住所によって分類します.このように各郵便配達員は近隣地域の郵便物を担当するだけです.
「3つの街に近い手紙を同じ郵便配達人に割り当てる」という考えかもしれません.この時、隣の街の数がkです.最良の分配スキームが得られるまで、kを増やし続けることができます.このkは分類問題の最高値です.
KNNコード実現
前回のようにmljsのKNNモジュールml-knnを使って実現します.
各マシンのアルゴリズムにはデータが必要です.今回はIRISデータセットを使います.このデータセットには150個のサンプルが含まれています.いずれもとんびの下の三つの亜属に属しています.それぞれ山とんび、カメレオン、ビギニアのとんびです.4つの特徴を試料の定量的解析として用い,それらはそれぞれガクランと花びらの長さと幅である.
1.モジュールの取り付け
$ npm install [email protected] csvtojson prompt
ml-knn:k-Nearest-Neighboursモジュールは、バージョンによってはインターフェースが異なるかもしれません.このブログは2.0%を使用しています.
csvtojson:CSVデータをJSONに変換するために使用します.
prompt:コンソールでデータを入出力する
2.データを初期化して導入する
IRIISデータセットはカリフォルニア大欧文分校によって提供されます.
curl https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data > iris.csv
NPMプロジェクトを初期化したとします.index.jsに以下の内容を入力してください.
const KNN = require('ml-knn');
const csv = require('csvtojson');
const prompt = require('prompt');

var knn;

const csvFilePath = 'iris.csv'; //    
const names = ['sepalLength', 'sepalWidth', 'petalLength', 'petalWidth', 'type'];

let seperationSize; //          

let data = [],
    X = [],
    y = [];

let trainingSetX = [],
    trainingSetY = [],
    testSetX = [],
    testSetY = [];
  • seperationSizeは、データとテストデータを分割するために使用される
  • .
    csvtojsonモジュールのfrom Fileを使用してデータをロードします.
    csv(
        {
            noheader: true,
            headers: names
        })
        .fromFile(csvFilePath)
        .on('json', (jsonObj) =>
        {
            data.push(jsonObj); //        JS    
        })
        .on('done', (error) =>
        {
            seperationSize = 0.7 * data.length;
            data = shuffleArray(data);
            dressData();
        });
    私たちはseperationSizeをサンプル数の0.7倍に設定します.訓練データセットが小さいと、分類効果が悪くなります.
    データセットは種類によって並べ替えられているので、shuffleAray関数を使ってデータを混同してこそ、トレーニングデータを容易に分割することができます.この関数の定義はStockOverflowの質問How to randomze a JavaScript arrayを参照してください.
    function shuffleArray(array)
    {
        for (var i = array.length - 1; i > 0; i--)
        {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }
    3.データの変換
    データセットごとにJSオブジェクトに変換できます.
    {
     sepalLength: ‘5.1’,
     sepalWidth: ‘3.5’,
     petalLength: ‘1.4’,
     petalWidth: ‘0.2’,
     type: ‘Iris-setosa’ 
    }
    KNNアルゴリズムを使用してデータをトレーニングする前に、これらの処理を行う必要があります.
  • は、属性(sepalLength、sepal Width、petal Length、petal Width)を文字列から浮動小数点に変換する.(parseFloat)
  • 分類を数字で表す
  • function dressData()
    {
        let types = new Set(); 
        data.forEach((row) =>
        {
            types.add(row.type);
        });
        let typesArray = [...types]; 
    
        data.forEach((row) =>
        {
            let rowArray, typeNumber;
            rowArray = Object.keys(row).map(key => parseFloat(row[key])).slice(0, 4);
            typeNumber = typesArray.indexOf(row.type); // Convert type(String) to type(Number)
    
            X.push(rowArray);
            y.push(typeNumber);
        });
    
        trainingSetX = X.slice(0, seperationSize);
        trainingSetY = y.slice(0, seperationSize);
        testSetX = X.slice(seperationSize);
        testSetY = y.slice(seperationSize);
    
        train();
    }
    4.データを訓練してテストする
    function train()
    {
        knn = new KNN(trainingSetX, trainingSetY,
        {
            k: 7
        });
        test();
    }
    trin方法には、2つの必要なパラメータが必要です.入力データ、すなわち、萼と花びらの長さと幅です.実際の分類は山鳶尾、カメレオン、ビギニアの鳶尾です.さらに、第3のパラメータは、KNNアルゴリズムを調整する内部パラメータを提供するために任意である.kパラメータを7に設定します.標準値は5です.
    モデルを訓練してから、テストデータを使って正確さを確認することができます.私たちは主に予測ミスの個数に興味があります.
    function test()
    {
        const result = knn.predict(testSetX);
        const testSetLength = testSetX.length;
        const predictionError = error(result, testSetY);
        console.log(`Test Set Size = ${testSetLength} and number of Misclassifications = ${predictionError}`);
        predict();
    }
    予測値と真実値を比較すると、エラーの数が得られます.
    function error(predicted, expected)
    {
        let misclassifications = 0;
        for (var index = 0; index < predicted.length; index++)
        {
            if (predicted[index] !== expected[index])
            {
                misclassifications++;
            }
        }
        return misclassifications;
    }
    5.予測(オプション)
    属性値を任意に入力すると予測値が得られます.
    function predict()
    {
        let temp = [];
        prompt.start();
        prompt.get(['Sepal Length', 'Sepal Width', 'Petal Length', 'Petal Width'], function(err, result)
        {
            if (!err)
            {
                for (var key in result)
                {
                    temp.push(parseFloat(result[key]));
                }
                console.log(`With ${temp} -- type =  ${knn.predict(temp)}`);
            }
        });
    }
    6.完全プログラム
    完全なプログラムindex.jsはこのようです.
    const KNN = require('ml-knn');
    const csv = require('csvtojson');
    const prompt = require('prompt');
    
    var knn;
    
    const csvFilePath = 'iris.csv'; //    
    const names = ['sepalLength', 'sepalWidth', 'petalLength', 'petalWidth', 'type'];
    
    let seperationSize; //          
    
    let data = [],
        X = [],
        y = [];
    
    let trainingSetX = [],
        trainingSetY = [],
        testSetX = [],
        testSetY = [];
    
    
    csv(
        {
            noheader: true,
            headers: names
        })
        .fromFile(csvFilePath)
        .on('json', (jsonObj) =>
        {
            data.push(jsonObj); //        JS    
        })
        .on('done', (error) =>
        {
            seperationSize = 0.7 * data.length;
            data = shuffleArray(data);
            dressData();
        });
    
    function dressData()
    {
        let types = new Set(); 
        data.forEach((row) =>
        {
            types.add(row.type);
        });
        let typesArray = [...types]; 
    
        data.forEach((row) =>
        {
            let rowArray, typeNumber;
            rowArray = Object.keys(row).map(key => parseFloat(row[key])).slice(0, 4);
            typeNumber = typesArray.indexOf(row.type); // Convert type(String) to type(Number)
    
            X.push(rowArray);
            y.push(typeNumber);
        });
    
        trainingSetX = X.slice(0, seperationSize);
        trainingSetY = y.slice(0, seperationSize);
        testSetX = X.slice(seperationSize);
        testSetY = y.slice(seperationSize);
    
        train();
    }
    
    
    //   KNN      
    function train()
    {
        knn = new KNN(trainingSetX, trainingSetY,
        {
            k: 7
        });
        test();
    }
    
    
    //        
    function test()
    {
        const result = knn.predict(testSetX);
        const testSetLength = testSetX.length;
        const predictionError = error(result, testSetY);
        console.log(`Test Set Size = ${testSetLength} and number of Misclassifications = ${predictionError}`);
        predict();
    }
    
    
    //       
    function error(predicted, expected)
    {
        let misclassifications = 0;
        for (var index = 0; index < predicted.length; index++)
        {
            if (predicted[index] !== expected[index])
            {
                misclassifications++;
            }
        }
        return misclassifications;
    }
    
    
    //         
    function predict()
    {
        let temp = [];
        prompt.start();
        prompt.get(['Sepal Length', 'Sepal Width', 'Petal Length', 'Petal Width'], function(err, result)
        {
            if (!err)
            {
                for (var key in result)
                {
                    temp.push(parseFloat(result[key]));
                }
                console.log(`With ${temp} -- type =  ${knn.predict(temp)}`);
            }
        });
    }
    
    
    //         
    function shuffleArray(array)
    {
        for (var i = array.length - 1; i > 0; i--)
        {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }
    コンソールでnode index.jsを実行します.
    $ node index.js
    出力は以下の通りです
    Test Set Size = 45 and number of Misclassifications = 2
    prompt: Sepal Length:  1.7
    prompt: Sepal Width:  2.5
    prompt: Petal Length:  0.5
    prompt: Petal Width:  3.4
    With 1.7,2.5,0.5,3.4 -- type =  2
    参照リンク
  • K NEAREST NEIGHBORアルゴリズム
  • 安森鳶尾花卉データセット
  • Funebugの全スタックBUG監視交流グループに参加してください.62292485.
    著作権声明:転載する時、作者のFunebugと本文の住所を明記してください.https://blog.fundebug.com/2017/07/10/javascript-machine-learning-knn/