分类 深度学习 下的文章
深度学习 复习
E7 Q-learning
以下是使用SARSA算法修改后的代码:
# 开始训练Q表格
all_episode_reward = [] # 用于记录每次迭代的总奖励,这样就可以知道智能体是否有进步了
for i in range(num_episodes):
## 初始化环境,得到初始状态
s, _= env.reset() # 初始状态值
rAll = 0 # 用于记录这次游戏的总奖励,这里先初始化为0
## The SARSA algorithm
## 首先,根据epsilon-greedy选择当前状态s下的动作a
a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
for j in range(99):
if render: env.render()
## 与环境交互得到下一个状态s1和即时奖励r
s1, r, d, _, _ = env.step(a)
## 根据epsilon-greedy选择在状态s1下的下一个动作a1
a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
## 使用SARSA更新Q表格
Q[s, a] = Q[s, a] + lr * (r + lambd * Q[s1, a1] - Q[s, a])
## 更新当前状态和动作
rAll += r
s = s1
a = a1
if d is True:
break
if i == 0:
all_episode_reward.append(rAll)
else:
all_episode_reward.append(all_episode_reward[-1] * 0.99 + rAll * 0.01)
print(
'Training | Episode: {}/{} | Episode Reward: {:.4f} | all_episode_reward: {:.4f} | Running Time: {:.4f}'.format(
i + 1, num_episodes, rAll, all_episode_reward[i], time.time() - t0
)
)
# 保存Q表格
path = os.path.join('model', '_'.join([alg_name, env_id]))
if not os.path.exists(path):
os.makedirs(path)
np.save(os.path.join(path, 'Q_table.npy'), Q)
# 绘制迭代的总奖励
plt.plot(all_episode_reward)
if not os.path.exists('image'):
os.makedirs('image')
plt.savefig(os.path.join('image', '_'.join([alg_name, env_id])))
# 打印Q表格
print("Final Q-Table Values:/n %s" % Q)
相对于原始代码,使用SARSA算法修改后的主要变化是:
在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
使用SARSA更新Q表格时,将下一个状态和动作的Q值Q[s1, a1]考虑进去。
这样就能够实现SARSA算法来训练Q表格,从而实现强化学习任务。
以下是使用SARSA算法修改后的代码:
# 模型评估
path = os.path.join('model', '_'.join([alg_name, env_id]))
Q = np.load(os.path.join(path, 'Q_table.npy'))
sum_rAll = 0
for i in range(num_episodes):
## 初始化环境,得到初始状态
s, _ = env.reset()
rAll = 0
## The SARSA algorithm
## 首先,根据epsilon-greedy选择当前状态s下的动作a
a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
for j in range(99):
## 与环境交互得到下一个状态s1和即时奖励r
s1, r, d, _, _ = env.step(a)
## 根据epsilon-greedy选择在状态s1下的下一个动作a1
a1 = np.argmax(Q[s1, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
## 更新当前状态和动作
rAll += r
s = s1
a = a1
if d is True:
break
print(
'Testing | Episode: {}/{} | Episode Reward: {:.4f} | Running Time: {:.4f}'.format(
i + 1, num_episodes, rAll,
time.time() - t0
)
)
sum_rAll += rAll
print('游戏中成功闯关比例: {:.4f}'.format(sum_rAll/num_episodes))
相对于原始代码,使用SARSA算法修改后的主要变化是:
在每个状态s下,先根据epsilon-greedy选择一个动作a,然后在与环境交互得到下一个状态s1后,再根据epsilon-greedy选择在状态s1下的下一个动作a1。
在模型评估时,使用SARSA算法更新当前状态和动作,并且在选择动作时也根据epsilon-greedy进行选择。
8.7.2 支持向量机手写数字识别
from os import mkdir, listdir
from os.path import isdir, basename
from random import choice, randrange
from string import digits
from PIL import Image, ImageDraw # pillow
from PIL.ImageFont import truetype
from sklearn import svm
from sklearn.model_selection import train_test_split
图像尺寸、图片中的数字字体大小、噪点比例
width, height = 30, 60
fontSize = 40
noiseRate = 8
def generateDigits(dstDir='datasets', num=4000):
# 生成num个包含数字的图片文件存放于当前目录下的datasets子目录
if not isdir(dstDir):
mkdir(dstDir)
# digits.txt用来存储每个图片对应的数字
with open(dstDir+'\\digits.txt', 'w') as fp:
for i in range(num):
# 随机选择一个数字,生成对应的彩色图像文件
digit = choice(digits)
im = Image.new('RGB', (width,height), (255,255,255))
imDraw = ImageDraw.Draw(im)
font = truetype('c:\\windows\\fonts\\TIMESBD.TTF',
fontSize)
imDraw.text((0,0), digit, font=font, fill=(0,0,0))
# 加入随机干扰
for j in range(int(noiseRate*width*height)):
w, h = randrange(1, width-1), randrange(height)
# 水平交换两个相邻像素的颜色
c1 = im.getpixel((w,h))
c2 = im.getpixel((w+1,h))
imDraw.point((w,h), fill=c2)
imDraw.point((w+1,h), fill=c1)
im.save(dstDir+'\\'+str(i)+'.jpg')
fp.write(digit+'\n')
def loadDigits(dstDir='datasets'):
# 获取所有图像文件名
digitsFile = [dstDir+'\\'+fn for fn in listdir(dstDir)
if fn.endswith('.jpg')]
# 按编号排序
digitsFile.sort(key=lambda fn: int(basename(fn)[:-4]))
# digitsData用于存放读取的图片中数字信息
# 每个图片中所有像素值存放于digitsData中的一行数据
digitsData = []
for fn in digitsFile:
with Image.open(fn) as im:
data = [sum(im.getpixel((w,h)))/len(im.getpixel((w,h)))
for w in range(width)
for h in range(height)]
digitsData.append(data)
# digitsLabel用于存放图片中数字的标准分类
with open(dstDir+'\\digits.txt') as fp:
digitsLabel = fp.readlines()
digitsLabel = [label.strip() for label in digitsLabel]
return (digitsData, digitsLabel)
生成图片文件
generateDigits(num=4000)
加载数据
data = loadDigits()
print('数据加载完成。')
随机划分训练集和测试集,其中参数test_size用来指定测试集大小
X_train, X_test, y_train, y_test = train_test_split(data[0],
data[1],
test_size=0.1)
创建并训练模型
svcClassifier = svm.SVC(kernel="linear", C=1000, gamma=0.001)
svcClassifier.fit(X_train, y_train)
print('模型训练完成。')
使用测试集对模型进行评分
score = svcClassifier.score(X_test, y_test)
print('模型测试得分:', score)
8.6.2 决策树算法原理与Sklearn 实现
import numpy as np
from sklearn import tree
X = np.array([[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]])
y = [0,1,1,1,2,3,3,4]
clf = tree.DecisionTreeClassifier()
clf.fit(X,y)
clf.predict([[1,0,0]])
import graphviz
dot_data = tree.export_graphviz(clf, out_file=None)
graph = graphviz.Source(dot_data)
graph.render('result')