中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

機器學習算法:k近鄰

發布時間:2020-06-17 05:28:07 來源:網絡 閱讀:1426 作者:BoyTNT 欄目:編程語言

前言:

最近在研究機器學習,過程中的心得體會會記錄到blog里,文章與代碼均為原創。會不定期龜速更新,注意這不是正式的教程,因為本人也是初學者,但是估計C#版本的代碼能幫到一些剛入門的同學去理解復雜的公式。


------------------------ 我是分割線 ------------------------


k近鄰(k-Nearest Neighbor,KNN)算法,應該是機器學習里最基礎的算法,其核心思想是:給定一個未知分類的樣本,如果與它最相似的k個已知樣本中的多數屬于某一個分類,那么這個未知樣本也屬于這個分類


所謂相似,是指兩個樣本之間的歐氏距離小,其計算公式為:

機器學習算法:k近鄰

其中Xi為樣本X的第i個特征。


k近鄰算法的優點在于實現簡單,缺點在于時間和空間復雜度高。


上C#版代碼,這里取k=1,即只根據最相近的一個點確定分類:

首先是DataVector,包含N維數據和分類標簽,用于表示一個樣本。

using System;

namespace MachineLearning
{
    /// <summary>
    /// 數據向量
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DataVector<T>
    {
        /// <summary>
        /// N維數據
        /// </summary>
        public T[] Data { get; private set; }
        /// <summary>
        /// 分類標簽
        /// </summary>
        public string Label { get; set; }

        /// <summary>
        /// 構造
        /// </summary>
        /// <param name="dimension">數據維度</param>
        public DataVector(int dimension)
        {
            Data = new T[dimension];
        }
        
        public int Dimension
        {
            get { return this.Data.Length; }
        }
    }
}


然后是核心算法:

using System;
using System.Collections.Generic;

namespace MachineLearning
{
    /// <summary>
    /// k近鄰法
    /// </summary>
    public class NearestNeighbour
    {
        private int m_K;
        private List<DataVector<double>> m_TrainingSet;
        
        public NearestNeighbour(int k = 1)
        {
            m_K = k;
        }
        
        /// <summary>
        /// 訓練
        /// </summary>
        /// <param name="trainingSet"></param>
        public void Train(List<DataVector<double>> trainingSet)
        {
            m_TrainingSet = trainingSet;
        }

        /// <summary>
        /// 分類
        /// </summary>
        /// <param name="vector"></param>
        /// <returns></returns>
        public string Classify(DataVector<double> vector)
        {
            //K=1時可簡化處理提高效率
            if(m_K == 1)
            {
                double minDist = double.PositiveInfinity;
                int targetIndex = -1;
                for(int i = 0;i < m_TrainingSet.Count;i++)
                {
                    //計算距離
                    double distance = ComputeDistance(vector, m_TrainingSet[i], minDist);

                    //找最小值
                    if(distance < minDist)
                    {
                        minDist = distance;
                        targetIndex = i;
                    }
                }
            
                return m_TrainingSet[targetIndex].Label;
            }
            else
            {
                var dict = new SortedDictionary<double, string>();
                
                for(int i = 0;i < m_TrainingSet.Count;i++)
                {
                    //計算距離并記錄
                    double distance = ComputeDistance(vector, m_TrainingSet[i]);
                    dict[distance] = m_TrainingSet[i].Label;
                }
                
                //找最多的Label
                var labels = new List<string>();
                int count = 0;
                foreach(var label in dict.Values)
                {
                    labels.Add(label);
                    if(++count > m_K - 1)
                        break;
                }

                return GetMajorLabel(labels);
            }
        }
    
        /// <summary>
        /// 計算距離
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="minValue"></param>
        /// <returns></returns>
        private double ComputeDistance(DataVector<double> v1, DataVector<double> v2, double minValue = double.PositiveInfinity)
        {
            double distance = 0.0;
            minValue = minValue * minValue;
            for(int i = 0;i < v1.Data.Length;++i)
            {
                double diff = v1.Data[i] - v2.Data[i];
                distance += diff * diff;
            
                //如果當前累加的距離已經大于給定的最小值,不用繼續計算了
                if(distance > minValue)
                    return double.PositiveInfinity;
            }

            return Math.Sqrt(distance);
        }
        
        /// <summary>
        /// 取多數
        /// </summary>
        /// <param name="dataSet"></param>
        /// <returns></returns>
        private string GetMajorLabel(List<string> labels)
        {
            var dict = new Dictionary<string, int>();
            foreach(var item in labels)
            {
                if(!dict.ContainsKey(item))
                    dict[item] = 0;
                dict[item]++;
            }

            string label = string.Empty;
            int count = -1;
            foreach(var key in dict.Keys)
            {
                if(dict[key] > count)
                {
                    label = key;
                    count = dict[key];
                }
            }
            
            return label;
        }
    }
}


需要注意的是,計算距離時,數量級大的維度會對距離影響大,因此大多數情況下,不能直接計算,要對原始數據做歸一化,并根據重要性進行加權。歸一化可以使用公式:value = (old-min)/(max-min),其中old是原始值,max是所有數據的最大值,min是所有數據的最小值。這樣計算得到的value將落在0至1的區間上。


這個算法太簡單,暫時不上測試代碼了,有時間再補吧。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

屏南县| 双牌县| 江华| 广河县| 江孜县| 南澳县| 越西县| 宣城市| 大洼县| 榆林市| 临颍县| 宣武区| 中方县| 阿合奇县| 济源市| 清水河县| 姚安县| 中卫市| 满洲里市| 兰考县| 清丰县| 新源县| 海门市| 正蓝旗| 平乡县| 石楼县| 时尚| 和田市| 荔浦县| 孟州市| 彰武县| 泾川县| 广安市| 东港市| 镇江市| 绥棱县| 丁青县| 淮南市| 南岸区| 新疆| 永川市|