实现PLA和PLA Pocket。visit example次序是顺序或者random cycle。Question 18 中“visit examples purely randomly”需要循环前先设定一个random cycle,再loop整个random ordered example。我开始的实现是每次random挑一个example,这样error很高,感觉是因为没有保证每个example被visit的次数相同。
import random
import numpy as np
def get_sign(w, x, y):
weighted_sum = 0
for j in range(0, len(w)):
weighted_sum += w[j] * x[j]
if weighted_sum * y <= 0:
# print weighted_sum, y
return False
return True
def standardPLA():
x = []
y = []
try:
fin = open("hw1_15_train.dat", 'r')
except IOError:
return
for data in fin:
data = data.strip("\n")
data = data.strip("\r")
items = data.split("\t")
# print items
y.append(float(items[1]))
items2 = items[0].split(" ")
# print items2
tmp = [1]
for i in range(0, len(items2)):
tmp.append(float(items2[i]))
x.append(tmp)
print x[-1], y[-1]
fin.close()
# return
w = [0 for i in range(0, len(x[0]))]
cnt = 0
correct_num = 0
idx = 0
while True:
if get_sign(w, x[idx], y[idx]) is False:
for j in range(0, len(w)):
w[j] += y[idx] * x[idx][j]
cnt += 1 # add one correction
# print w, y[i], cnt
correct_num = 0
print cnt
else:
correct_num += 1
idx = (idx + 1) % len(x)
if correct_num >= len(x):
print cnt
break
# flg = True
# for i in range(0, len(x)):
# if get_sign(w, x[i], y[i]) is False:
# for j in range(0, len(w)):
# w[j] += y[i] * x[i][j]
# cnt += 1 # add one correction
# # print w, y[i], cnt
# print cnt
# flg = False
# if flg is True:
# print cnt
# break
def random_cycle_PLA(rate=1.0):
x = []
y = []
try:
fin = open("hw1_15_train.dat", 'r')
except IOError:
return
for data in fin:
data = data.strip("\n")
data = data.strip("\r")
items = data.split("\t")
# print items
y.append(float(items[1]))
items2 = items[0].split(" ")
# print items2
tmp = [1]
for i in range(0, len(items2)):
tmp.append(float(items2[i]))
x.append(tmp)
print x[-1], y[-1]
fin.close()
# return
cycle = [i for i in range(0, len(x))]
repeat_num = 2000
ave_cnt = []
for rep in range(0, repeat_num):
w = [0 for i in range(0, len(x[0]))]
np.random.shuffle(cycle)
cnt = 0
correct_num = 0
idx = 0
while True:
if get_sign(w, x[cycle[idx]], y[cycle[idx]]) is False:
for j in range(0, len(w)):
w[j] += rate * y[cycle[idx]] * x[cycle[idx]][j]
cnt += 1 # add one correction
# print w, y[i], cnt
correct_num = 0
# print cnt
else:
correct_num += 1
idx = (idx + 1) % len(x)
if correct_num >= len(x):
print cnt
ave_cnt.append(cnt)
break
print np.mean(ave_cnt)
def load_test_data():
x = []
y = []
try:
fin = open("hw1_18_test.dat", 'r')
except IOError:
return
for data in fin:
data = data.strip("\n")
data = data.strip("\r")
items = data.split("\t")
# print items
y.append(float(items[1]))
items2 = items[0].split(" ")
# print items2
tmp = [1]
for i in range(0, len(items2)):
tmp.append(float(items2[i]))
x.append(tmp)
# print x[-1], y[-1]
fin.close()
return x, y
def test_pocket(w, x, y):
error = 0
for i in range(0, len(x)):
if get_sign(w, x[i], y[i]) is False:
error += 1
return 1.0 * error / len(x)
def pocket():
x = []
y = []
try:
fin = open("hw1_18_train.dat", 'r')
except IOError:
return
for data in fin:
data = data.strip("\n")
data = data.strip("\r")
items = data.split("\t")
# print items
y.append(float(items[1]))
items2 = items[0].split(" ")
# print items2
tmp = [1]
for i in range(0, len(items2)):
tmp.append(float(items2[i]))
x.append(tmp)
print x[-1], y[-1]
fin.close()
# return
test_x, test_y = load_test_data()
cycle = [i for i in range(0, len(x))]
repeat_num = 2000
ave_err = []
for rep in range(0, repeat_num):
w = [0 for i in range(0, len(x[0]))]
w_pocket = [0 for i in range(0, len(x[0]))]
np.random.shuffle(cycle)
index = 0
cnt = 0
while True:
# idx = np.random.randint(0, len(x))
idx = cycle[index]
if get_sign(w, x[idx], y[idx]) is False:
for j in range(0, len(w)):
w[j] += y[idx] * x[idx][j]
cnt += 1 # add one correction
if test_pocket(w, test_x, test_y) < test_pocket(w_pocket, test_x, test_y):
w_pocket[:] = w
# print w, y[i], cnt
# print cnt
index = (index + 1) % len(cycle)
if cnt >= 100:
# print cnt
tmp = test_pocket(w_pocket, test_x, test_y)
# tmp = test_pocket(w, test_x, test_y)
print rep, tmp
ave_err.append(tmp)
break
print np.mean(ave_err)
if __name__ == '__main__':
np.random.seed(1111)
# standardPLA()
# random_cycle_PLA(0.5)
pocket()