一、实验目的
1、熟练使用numpy模块;
2、熟练使用matplotlib模块;
3、掌握ε-贪心算法的代码实现;
4、掌握softmax算法的代码实现。
二、实验设备
计算机:CPU四核i7 6700处理器;内存8G; SATA硬盘2TB硬盘; Intel芯片主板;集成声卡、千兆网卡、显卡; 20寸液晶显示器。
编译环境:python解释器、Pycharm编辑器
三、实验内容
1、新建项目和文件,并导入numpy和matplotlib
(1)打开Pycharm,新建项目,并在该项目下新建文件kmeans_clustering.py。
(2)导入一些编程中需要的包。
import numpy as np
import matplotlib.pyplot as plt
2、构造一个类KArmedBandits
(1)该类实现K摇臂赌博机游戏,即每个摇臂对应一个概率分布,每次使用该摇臂,可以根据它对应的概率分布产生一个正整数。初始化该类时,需要将摇臂的个数k作为参数。
(2)定义一个类方法play,需要参数k,即使用的摇臂的编号,该函数根据当前摇臂对应的概率分布,返回一个正整数。
class KArmedBandits:
def __init__(self,k):#初始化类
self.k = k#将摇臂的个数k作为参数
def start(self):
a=np.random.randint(1,100,[self.k,5])
return a
def R(self,p):
index = np.random.choice([8, 6, 4, 2, 0], p = p.ravel())
return index #返回当次预测的奖赏
def play(self,b,c):
k = c[b] / np.sum(c[b]) #b是选择的摇臂,c是start方法生成的矩阵 此时的k是5个小数,并且相加等于1,符合做概率的条件
k = np.sort(k) #概率从小到大排列
return k
3、编写一个类EpsilonGreedy
(1)构造一个类EpsilonGreedy,并定义构造函数,该类用于实现ε-贪心算法。
(2)定义类方法learn,实现实现ε-贪心算法,并返回游戏次数和游戏次数对应的平均reward。
(3)定义类方法use,该方法用于在learn结束之后,实现贪心算法,并返回游戏次数和游戏次数对应的平均reward。
# 编写一个类EpsilonGreedy
class EpsilonGreedy: # ε-贪心算法
def __init__(self, maxitem, c, item):
self.t = maxitem
self.us = item
self.k = [0, 1, 2, 3, 4]
self.c = c
self.avg = np.zeros(5)
def learn(self, e):
r = 0;
count = np.zeros(5)
avgsum1 = np.zeros(self.t)
for i in range(self.t):
if np.random.random() < e: # 随机生成一个大于0小于1的小数,判断是否小于e,如果小于,探索,否则,利用
k = np.random.choice(self.k)
print("探索")
else:
k = np.argmax(self.avg)
print("利用")
print("选择的臂", k) # 选择的臂
q = KArmedBandits.play(self, k, self.c) # q是k摇臂对应的重置的概率
v = KArmedBandits.R(self, q)
print("奖赏值", v)
r = r + v
avgsum1[i] = r / (i + 1)
self.avg[k] = ((self.avg[k] * count[k]) + v) / (count[k] + 1) # 计算每个摇臂对应的平均奖赏函数,
count[k] += 1
return avgsum1
def use(self, e):
r = 0
count = np.zeros(5)
avgsum2 = np.zeros(self.us)
for i in range(self.us):
k = np.argmax(self.avg)
print("选择的臂", k)
q = KArmedBandits.play(self, k, self.c)
v = KArmedBandits.R(self, q)
print("奖赏值", v)
r = r + v
avgsum2[i] = r / (i + 1)
print("平均奖赏值:", avgsum2[i])
self.avg[k] = ((self.avg[k] * count[k]) + v) / (count[k] + 1)
count[k] += 1
return avgsum2, self.avg
4、编写一个类Softmax
(1)构造一个类Softmax,并定义构造函数,该类用于实现Softmax算法。
(2)定义类方法learn,实现实现Softmax算法,并返回游戏次数和游戏次数对应的平均reward。
(3)定义类方法use,该方法用于在learn结束之后,实现贪心算法,并返回游戏次数和游戏次数对应的平均reward。
class Softmax:
def __init__(self,maxium,avgk,item,gama):
self.t = maxium
self.gama = gama
self.avgk = avgk
self.k = [0,1,2,3,4]
self.us = item
def P(self): #重置摇臂选择概率
index = np.zeros(5)
index[0] = np.exp(self.avgk[0]/self.gama) / np.sum(np.exp(self.avgk/self.gama))
index[1] = np.exp(self.avgk[1]/self.gama) / np.sum(np.exp(self.avgk/self.gama))
index[2] = np.exp(self.avgk[2]/self.gama) / np.sum(np.exp(self.avgk/self.gama))
index[3] = np.exp(self.avgk[3]/self.gama) / np.sum(np.exp(self.avgk/self.gama))
index[4] = np.exp(self.avgk[4]/self.gama) / np.sum(np.exp(self.avgk/self.gama))
return index
def learn(self,c):
r = 0;avg = np.zeros(5);count = np.zeros(5);avgsum = np.zeros(self.t)
for i in range(self.t):
p = self.P() #选择摇臂概率
k = np.random.choice(self.k, p = p.ravel())
q = KArmedBandits.play(self,k,c) #c是重置的概率矩阵
v = KArmedBandits.R(self,q)
r = r + v
avgsum[i] = r / (i+1)
self.avgk[k] = ((self.avgk[k]*count[k])+v) / (count[k]+1)
count[k] +=1
return avgsum
def use(self):
r = 0;count = np.zeros(5)
avgsum = np.zeros(self.us)
for i in range(self.us):
k=np.argmax(self.avgk)
print("选择的臂",k)
q = KArmedBandits.play(self,k,c) #c是重置的概率矩阵
v = KArmedBandits.R(self,q)
print("奖赏值",v)
r = r + v
avgsum[i] = r / (i+1)
self.avgk[k] = ((self.avgk[k]*count[k])+v) / (count[k]+1)
print("平均奖赏值:",avgsum[i])
count[k] +=1
return avgsum
5、编写if _ name ==” main _”:
(1)构造if _ name ==” main _”:。
(2)使用不同的参数,调用EpsilonGreedy类和Softmax类
(3)使用每次调用learn和use之后返回的数据,绘制折线图
(4)比较算法。
if __name__ == "__main__":
KArmedBanditsinit = KArmedBandits(5)
c = KArmedBanditsinit.start()
EpsilonGreedy = EpsilonGreedy(10000,c,1000)
avg_1_lean = EpsilonGreedy.learn(0.3)
avg_2_lean = EpsilonGreedy.learn(0.1)
avg_1_use,avg_1 = EpsilonGreedy.use(0.3)
avg_2_use,avg_2 = EpsilonGreedy.use(0.1)
Softmax_1 = Softmax(10000,avg_1,1000,0.1)
Softmax_2 = Softmax(10000,avg_1,1000,1)#根据e概率为0.3时返回的平均奖赏作softmax运算
avg_1__lean = Softmax_1.learn(c)
avg_2__lean = Softmax_2.learn(c)
avg_1__use = Softmax_1.use()
avg_2__use = Softmax_2.use()
#折线图,数据可视化处理
plt.figure()
plt.subplot(121)
plt.plot(avg_1_lean,"r",avg_2_lean,"b",avg_1__lean,"y",avg_2__lean,"g")
plt.subplot(122)
plt.plot(avg_1_use,"r",avg_2_use,"b",avg_1__use,"y",avg_2__use,"g")
plt.show()
四、实验总结
通过本次实验,自己对机器的学习有了更深的理解,主要学习了强化学习中的K-摇臂赌博机,对比了ε-贪心算法和softmax算法实现,尝试用不同的方法来实现某一功能,比较不同算法在摇臂赌博机上的性能。