天天看點

機器學習-sklearn.datasets-load_iris資料集-回歸算法和K近鄰法(KNN)1、 load_iris資料集2、資料集處理3、線性回歸4、K近鄰(KNN)算法5、繪制函數圖像6、運作結果展示7、完整代碼

學習機器學習一個月了,開始嘗試做一些簡單的練習

文章目錄

  • 1、 load_iris資料集
  • 2、資料集處理
  • 3、線性回歸
    • 3.1 回歸訓練
    • 3.2 回歸測試
    • 3.3 對輸入點進行判斷
  • 4、K近鄰(KNN)算法
    • 4.1 距離計算
    • 4.2 計算準确率
    • 4.3 k近鄰法判斷輸入點類别
  • 5、繪制函數圖像
  • 6、運作結果展示
  • 7、完整代碼

1、 load_iris資料集

Iris資料集在模式識别研究領域應該是最知名的資料集了,有很多文章都用到這個資料集。這個資料集裡一共包括150行記錄,其中前四列為花萼長度,花萼寬度,花瓣長度,花瓣寬度等4個用于識别鸢尾花的屬性,第5列為鸢尾花的類别(包括Setosa,Versicolour,Virginica三類)。也即通過判定花萼長度,花萼寬度,花瓣長度,花瓣寬度的尺寸大小來識别鸢尾花的類别。

這裡使用資料集的data、target兩個屬性進行機器學習的訓練

from sklearn.datasets import load_iris

iris = load_iris()
data = iris.data
target= iris.target
print(data)
print(target)
           

這裡data為訓練所需的資料集,target為資料集對應的分類标簽,屬于監督學習

data資料集中的資料一共有4個屬性,分别為

target為分類标簽,與data中的資料相對應

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]
           

data中的資料,前50個屬于0類,中間50個屬于1類,後50個屬于2類

通過觀察data資料集中的資料可知,在分類中四個屬性,前兩個屬性的辨識度不是很高,後兩個屬性辨識度較高

這裡因為是在做練習,是以隻取資料集的前100個資料的前兩個屬性進行練習,當然取後兩個屬性也行,不過太簡單了

2、資料集處理

首先是資料擷取函數,沒什麼好說的,就是得到load_iris的資料并傳回,代碼如下:

# 資料擷取
def get_data():
    iris = load_iris()
    data = iris.data
    result = iris.target
    return data, result
           

之後是對資料集的處理,将資料集分為訓練集和測試集,這裡資料比較少隻有100條,分的時候應該盡可能随機,我的代碼如下:

# 将資料處理為訓練集和測試集
def data_deal(data, result):
    data_list = []
    for i in data:
        tem_list = [i[0], i[1]]
        data_list.append(tem_list)
    res_list = []
    for j in result:
        res_list.append(j)
    train_list = data_list[0: 10] + data_list[20: 80] + data_list[90: 100]
    train_result = res_list[0: 10] + res_list[20: 80] + res_list[90: 100]
    test_list = data_list[0: 40] + data_list[60: 100]
    test_result = res_list[0: 40] + res_list[60: 100]

    return data_list, train_list, test_list, train_result, test_result
           

這個分法并不好,提供一種思路:生成100以内随機數,将訓練樣本和訓練結果對應的資料傳回,選取80個作為訓練集,将剩餘的作為測試集

這裡傳回值為訓練集、訓練結果、測試集、測試集标準結果(用于與測試集最終結果比對計算準确率)

3、線性回歸

3.1 回歸訓練

這裡我用的方法并不是标準的線性回歸方法,是自己的一個思路

下面是回歸的訓練方法,這裡使用線性模型

y = w x + b y=wx+b y=wx+b

1、首先說明思路,先對訓練集中的所有點x,y分别進行相加,除以個數,得到所有訓練樣本的幾何中點

2、之後以這條線為回歸模型上的一個定點,對回歸模型進行旋轉,設定初始w=0,b=0,即為水準線

3、通過學習率,對每次旋轉的角度進行調整

4、在進行一次旋轉時,若訓練集中的樣本的結果更加符合标準結果,那麼繼續向這個方向旋轉,反之,若訓練集結果與标準結果差的更遠,那麼則向反方向旋轉

5、這裡就涉及到一個斜率更新問題,斜率根據學習率進行更新,標明好的學習率也很重要

衆所周知

斜 率 = t a n 夾 角 斜率=tan夾角 斜率=tan夾角

機器學習-sklearn.datasets-load_iris資料集-回歸算法和K近鄰法(KNN)1、 load_iris資料集2、資料集處理3、線性回歸4、K近鄰(KNN)算法5、繪制函數圖像6、運作結果展示7、完整代碼

根據tan函數圖像可知,初始時刻(w=0,b=0)的斜率為0

這時在tan的導數 較小>0 增長率較慢

是以在初始時刻時,要選取一個較大的學習率來對斜率進行更新,随着逐漸的更新,斜率的增長率開始變快,此時就需要一個較小的學習率來控制斜率了,因為此時斜率的變化對所拟合的直線會有較大的影響。

為此,初始的學習率給定為1,之後在每進行一次疊代,學習率乘0.9,這樣可以使學習率較好的取适應拟合的直線,得到更高的準确率

乘0.9是通過測試得到的 ,疊代次數為1000此也是測試得到,而且繼續增加疊代次數對模型的影響微乎其微,還會增加運作時間

# 回歸方法訓練
def train(learning_rate, iter_num, train_data, result):
    x_c = 0
    y_c = 0
    for i in train_data:
        x_c = x_c + i[0]
        y_c = y_c + i[1]
    m = x_c/len(train_data)
    n = y_c/len(train_data)
    w = 0
    b = 0
    ok_rate = 0
    for i in range(iter_num):
        train_r = []
        b = n-w*m
        count = 0
        for j in train_data:
            if j[1] > w*j[0]+b:
                train_r.append(0)
            else:
                train_r.append(1)
        for ii in range(len(result)):
            if result[ii] == train_r[ii]:
                count = count+1
        train_ok_rate = count/len(train_data)
        if ok_rate <= train_ok_rate:
            w = w + learning_rate
        else:
            w = w - learning_rate
        learning_rate = learning_rate*0.9
        ok_rate = train_ok_rate

    return ok_rate, w, b
           

3.2 回歸測試

将回歸得到的線性模型,用于對測試集中資料準确率的測試

将其測試結果與标準結果進行比對,得到測試準确率

# 回歸方法測試
def test(w, b, test_list, test_result):
    test_res = []
    count = 0
    for j in test_list:
        if j[1] > w * j[0] + b:
            test_res.append(0)
        else:
            test_res.append(1)
    for i in range(len(test_result)):
        if result[i] == test_res[i]:
            count = count + 1
    oks = count/len(test_result)
    return oks
           

3.3 對輸入點進行判斷

判斷輸入點屬于哪一類的一個方法,帶入線性模型,判斷其位于線上方還是下方

# 回歸方法判斷點的類型
def check_point(w, b, dot):
    y = w*dot[0] + b
    if y > dot[1]:
        return "回歸判斷該點類别為0"
    else:
        return "回歸判斷該點類别為1"
           

4、K近鄰(KNN)算法

4.1 距離計算

沒什麼好說的,就是簡單的點到點的距離

# k近鄰法計算距離方法
def distance(A, B):
    return (abs((B[0]-A[0])**2+(B[1]-A[1])**2))**0.5
           

4.2 計算準确率

k近鄰法思路為:給定一個點,選取與其距離最近的n個點,若這n個點中屬于0類的點多,那麼可以近似的認為該點也屬于0類,否則将該點歸為1類

在對所有點進行分類後,與标準結果進行比對,得出準确率

# k近鄰法訓練,測試準确率
def K_train(train_list, train_result, k):
    dis_list = []
    # 所有點到别的點的距離
    for i in train_list:
        dis = []
        for j in train_list:
            dis.append(distance(i, j))
        dis_list.append(dis)

    # 擷取到訓練集中每個點的最近5個點的索引
    min_dis_list = []
    for m in range(len(dis_list)):
        temp = []
        for n in range(int(k+1)):
            temp.append(dis_list[m].index(min(dis_list[m])))
            dis_list[m][dis_list[m].index(min(dis_list[m]))] = 100
            temp.sort()
        x = temp[1:]
        min_dis_list.append(x)

    # 根據索引判斷對應點的類别
    dot_type = []
    for ii in min_dis_list:
        mm = 0
        nn = 0
        for jj in ii:
            if jj <= 50:
                mm = mm+1
            else:
                nn = nn+1
        if mm >= nn:
            dot_type.append(0)
        else:
            dot_type.append(1)

    # 計算準确率
    count = 0
    for xx in range(len(dot_type)):
        if dot_type[xx] == train_result[xx]:
            count = count+1

    return count/len(dot_type)
           

4.3 k近鄰法判斷輸入點類别

輸入一個點,使用k近鄰法判斷其所屬類别

# k近鄰法判斷點的類型
def K_check_point(dots, check_list, result):
    dis = []
    for i in check_list:
        dis.append(distance(dots, i))
    min_dis = []
    for j in range(5):
        min_dis.append(dis.index(min(dis)))
        dis[dis.index(min(dis))] = 100
    zero = 0
    one = 0
    for s in min_dis:
        if result[s] == 0:
            zero = zero+1
        else:
            one = one+1
    if one > zero:
        return "K近鄰法判斷該點類别為0"
    else:
        return "K近鄰法判斷該點類别為1"
           

5、繪制函數圖像

使用matplotlib進行繪圖,一張繪制所有點,另一張對訓練集和測試集進行分别繪制

并将使用者輸入的點繪制到圖像上

# 繪制函數圖像和輸入點
def fun_image(w, b, dot):
    iris = load_iris()
    irisFeature = iris.data
    irisTarget = iris.target

    ax1 = plt.subplot(1, 2, 1)
    ax2 = plt.subplot(1, 2, 2)

    plt.sca(ax1)
    for i in range(0, 100):
        if irisTarget[i] == 0:
            type11 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="r")
        elif irisTarget[i] == 1:
            type22 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="g")

    plt.title("show train and test")
    plt.xlabel("ewidth")
    plt.ylabel("elength")
    x = np.linspace(4, 7, 256)
    plt.plot(x, w * x + b, color='black')
    plt.legend((type11, type22), ('0', '1'))
    plt.plot(dot[0], dot[1], color='black', marker='+')

    plt.sca(ax2)
    for i in range(20, 80):
        if irisTarget[i] == 0:
            type1 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="r", marker="8")
        elif irisTarget[i] == 1:
            type2 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="g", marker="8")
    for i in range(0, 20):
        if irisTarget[i] == 0:
            type3 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="blue", marker="v")
        elif irisTarget[i] == 1:
            plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="orange", marker="v")
    for i in range(80, 100):
        if irisTarget[i] == 0:
            plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="blue", marker="v")
        elif irisTarget[i] == 1:
            type4 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="orange", marker="v")


    plt.title("show all")
    plt.xlabel("ewidth")
    plt.ylabel("elength")
    x = np.linspace(4, 7, 256)
    plt.plot(x, w*x+b, color='black')
    plt.plot(dot[0], dot[1], color='black', marker='+')

    plt.legend((type1, type2, type3, type4), ('train-0', 'train-1', 'test-0', 'test-1'))
    plt.show()

           

6、運作結果展示

函數圖像為:

其中包含 + 為手動輸入的點

機器學習-sklearn.datasets-load_iris資料集-回歸算法和K近鄰法(KNN)1、 load_iris資料集2、資料集處理3、線性回歸4、K近鄰(KNN)算法5、繪制函數圖像6、運作結果展示7、完整代碼

控制台輸出的結果:

機器學習-sklearn.datasets-load_iris資料集-回歸算法和K近鄰法(KNN)1、 load_iris資料集2、資料集處理3、線性回歸4、K近鄰(KNN)算法5、繪制函數圖像6、運作結果展示7、完整代碼

7、完整代碼

from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np

# 資料擷取
def get_data():
    iris = load_iris()
    data = iris.data
    result = iris.target
    return data, result

# 将資料處理為訓練集和測試集
def data_deal(data, result):
    data_list = []
    for i in data:
        tem_list = [i[0], i[1]]
        data_list.append(tem_list)
    res_list = []
    for j in result:
        res_list.append(j)
    train_list = data_list[0: 10] + data_list[20: 80] + data_list[90: 100]
    train_result = res_list[0: 10] + res_list[20: 80] + res_list[90: 100]
    test_list = data_list[0: 40] + data_list[60: 100]
    test_result = res_list[0: 40] + res_list[60: 100]

    return data_list, train_list, test_list, train_result, test_result

# 回歸方法訓練
def train(learning_rate, iter_num, train_data, result):
    x_c = 0
    y_c = 0
    for i in train_data:
        x_c = x_c + i[0]
        y_c = y_c + i[1]
    m = x_c/len(train_data)
    n = y_c/len(train_data)
    w = 0
    b = 0
    ok_rate = 0
    for i in range(iter_num):
        train_r = []
        b = n-w*m
        count = 0
        for j in train_data:
            if j[1] > w*j[0]+b:
                train_r.append(0)
            else:
                train_r.append(1)
        for ii in range(len(result)):
            if result[ii] == train_r[ii]:
                count = count+1
        train_ok_rate = count/len(train_data)
        if ok_rate <= train_ok_rate:
            w = w + learning_rate
        else:
            w = w - learning_rate
        learning_rate = learning_rate*0.9
        ok_rate = train_ok_rate

    return ok_rate, w, b


# 回歸方法測試
def test(w, b, test_list, test_result):
    test_res = []
    count = 0
    for j in test_list:
        if j[1] > w * j[0] + b:
            test_res.append(0)
        else:
            test_res.append(1)
    for i in range(len(test_result)):
        if result[i] == test_res[i]:
            count = count + 1
    oks = count/len(test_result)
    return oks


# 繪制函數圖像和輸入點
def fun_image(w, b, dot):
    iris = load_iris()
    irisFeature = iris.data
    irisTarget = iris.target

    ax1 = plt.subplot(1, 2, 1)
    ax2 = plt.subplot(1, 2, 2)

    plt.sca(ax1)
    for i in range(0, 100):
        if irisTarget[i] == 0:
            type11 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="r")
        elif irisTarget[i] == 1:
            type22 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="g")

    plt.title("show train and test")
    plt.xlabel("ewidth")
    plt.ylabel("elength")
    x = np.linspace(4, 7, 256)
    plt.plot(x, w * x + b, color='black')
    plt.legend((type11, type22), ('0', '1'))
    plt.plot(dot[0], dot[1], color='black', marker='+')

    plt.sca(ax2)
    for i in range(20, 80):
        if irisTarget[i] == 0:
            type1 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="r", marker="8")
        elif irisTarget[i] == 1:
            type2 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="g", marker="8")
    for i in range(0, 20):
        if irisTarget[i] == 0:
            type3 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="blue", marker="v")
        elif irisTarget[i] == 1:
            plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="orange", marker="v")
    for i in range(80, 100):
        if irisTarget[i] == 0:
            plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="blue", marker="v")
        elif irisTarget[i] == 1:
            type4 = plt.scatter(irisFeature[i, 0], irisFeature[i, 1], c="orange", marker="v")


    plt.title("show all")
    plt.xlabel("ewidth")
    plt.ylabel("elength")
    x = np.linspace(4, 7, 256)
    plt.plot(x, w*x+b, color='black')
    plt.plot(dot[0], dot[1], color='black', marker='+')

    plt.legend((type1, type2, type3, type4), ('train-0', 'train-1', 'test-0', 'test-1'))
    plt.show()

# 回歸方法判斷點的類型
def check_point(w, b, dot):
    y = w*dot[0] + b
    if y > dot[1]:
        return "回歸判斷該點類别為0"
    else:
        return "回歸判斷該點類别為1"


# k近鄰法計算距離方法
def distance(A, B):
    return (abs((B[0]-A[0])**2+(B[1]-A[1])**2))**0.5


# k近鄰法訓練,測試準确率
def K_train(train_list, train_result, k):
    dis_list = []
    # 所有點到别的點的距離
    for i in train_list:
        dis = []
        for j in train_list:
            dis.append(distance(i, j))
        dis_list.append(dis)

    # 擷取到訓練集中每個點的最近5個點的索引
    min_dis_list = []
    for m in range(len(dis_list)):
        temp = []
        for n in range(int(k+1)):
            temp.append(dis_list[m].index(min(dis_list[m])))
            dis_list[m][dis_list[m].index(min(dis_list[m]))] = 100
            temp.sort()
        x = temp[1:]
        min_dis_list.append(x)

    # 根據索引判斷對應點的類别
    dot_type = []
    for ii in min_dis_list:
        mm = 0
        nn = 0
        for jj in ii:
            if jj <= 50:
                mm = mm+1
            else:
                nn = nn+1
        if mm >= nn:
            dot_type.append(0)
        else:
            dot_type.append(1)

    # 計算準确率
    count = 0
    for xx in range(len(dot_type)):
        if dot_type[xx] == train_result[xx]:
            count = count+1

    return count/len(dot_type)


# k近鄰法判斷點的類型
def K_check_point(dots, check_list, result):
    dis = []
    for i in check_list:
        dis.append(distance(dots, i))
    min_dis = []
    for j in range(5):
        min_dis.append(dis.index(min(dis)))
        dis[dis.index(min(dis))] = 100
    zero = 0
    one = 0
    for s in min_dis:
        if result[s] == 0:
            zero = zero+1
        else:
            one = one+1
    if one > zero:
        return "K近鄰法判斷該點類别為0"
    else:
        return "K近鄰法判斷該點類别為1"



if __name__ == '__main__':
    data, result = get_data()
    data_list, train_list, test_list, train_result, test_result = data_deal(data, result)
    learning_rate = 1
    iter_num = 1000
    ok_rate, w, b = train(learning_rate, iter_num, train_list, train_result)
    test_ok_rate = test(w, b, test_list, test_result)
    k = 5
    K_ok_rate = K_train(train_list, train_result, k)
  
    print("回歸方法"
          "數學模型:y={}x+{}\n"
          "learning_rate:{}\titer_num:{}\n"
          "訓練模型準确率:{}\n"
          "測試模型準确率:{}\n".format(round(w, 3), round(b, 3), learning_rate, iter_num, ok_rate, test_ok_rate))
    print("K近鄰法\n"
          "K值選取為{}\n"
          "判斷準确率為{}\n".format(k, K_ok_rate))

    dots = list(map(float, input("請輸入要判斷的點:").split()))
    fun_image(w, b, dots)
    print(check_point(w, b, dots))
    print(K_check_point(dots, train_list, train_result))

           

耗時一晚上,終于做出來了,這是我做的第二個機器學習的練習,可能方法并不标準,代碼寫的也比較亂,太忙了,沒有時間顧及這些了。

準研一暑假的自學,加油,自己!未來可期!