學習機器學習一個月了,開始嘗試做一些簡單的練習
文章目錄
- 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夾角
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL0cGVOpXSU9keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zROBlL3gzNxIjNzkTM5IzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
根據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、運作結果展示
函數圖像為:
其中包含 + 為手動輸入的點
控制台輸出的結果:
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))
耗時一晚上,終于做出來了,這是我做的第二個機器學習的練習,可能方法并不标準,代碼寫的也比較亂,太忙了,沒有時間顧及這些了。
準研一暑假的自學,加油,自己!未來可期!