今天周日,我一早就出门吃早饭,发现昨天经过一夜的大雨,今天的天气凉爽了一点,看了去实验室应该
不会太热,因此我就去实验室,然后就把一周学到的代码再次复习一遍,不知不觉一天就过去了,晚上理个发
然后休息休息吧~
今天继续总结本周学习到的知识:
周四周五
库函数调研
在成功得到序列的预测模型后,面临一个输入显示结果的情况,因此我决定使用树的数据结构进行操作。 然后使用一种工具进行绘制。
Treelib
库函数使用
既然选择好了使用的库函数,接下来就是将结果实践一下。
Treelib
为了进行树的数据结构的时候,我首先在github上面检索tree structure
,最后得到了一个代码:Treelib代码
该代码我直接下载,然后通过python
安装,之后阅读了一下文档,
发现了一些测试的例子:
>>> from treelib import Node, Tree
>>> tree = Tree()
>>> tree.create_node("Harry", "harry") # root node
>>> tree.create_node("Jane", "jane", parent="harry")
>>> tree.create_node("Bill", "bill", parent="harry")
>>> tree.create_node("Diane", "diane", parent="jane")
>>> tree.create_node("Mary", "mary", parent="diane")
>>> tree.create_node("Mark", "mark", parent="jane")
>>> tree.show()
Harry
├── Bill
└── Jane
├── Diane
│ └── Mary
└── Mark
很明显,该库的使用非常简单,仅仅使用create_node
就可以随意的增加节点,因此直接使用该函数就可以顺利的增加节点了。然后我所需要
的效果就是能够随时增加子叶节点,仔细观察该函数tree.create_node(tag[, identifier[, parent[, data]]])
发现参数中有一个tag
是
标签,还有一个identifier
是非常重要的,因为以后如果想要索引到节点,必须使用 tree.children(nid)
函数,里面传入的nid
就是
标签的意思,说明文档里面也说明了节点的nid
是唯一表示符。因此我在生成新的id的时候,首先使用tree.size()
得到现在树中的节点
数目,然后就直接增加一个即可当成现在新生成的节点id。生成新节点的递归函数如下所示。
def genChildren(tree,nid,before_list,next_n,depth,pro_threshold): #tree树,nid当前节点的id,before_list包含到当前节点的序列
# print('预测到列表%s'%before_list)
if len(before_list) > depth : #如果深度超过指定深度,则退出函数
return
pred = model.prediction_next_n(before_list,converter.vocab_size,next_n)
pro_com = 0
pred.reverse()
for tup in pred:
new_nid = str(tree.size()+1)
tree.create_node(converter.int_to_word_table[tup[0]],
new_nid,
nid,
OpData(converter.int_to_word_table[tup[0]],tup[0],'%.2f%%'%(tup[1]*100)))
new_before_list = before_list.copy() #一定要拷贝
if converter.int_to_word_table[tup[0]] != endToken: #如果当前不是结尾,则继续调用递归函数进行预测
new_before_list.append(tup[0])
genChildren(tree,new_nid,new_before_list,next_n,depth,pro_threshold) #递归调用本身函数
pro_com = pro_com + tup[1]
if pro_com > pro_threshold: #如果大于给定阈值则返回
return
上面的递归函数就生成了我需要的树
注意,为了保存节点内部内容和传递概率,我自定义一个类来存储相关数据:
class OpData(object):
def __init__(self, op,opNum,probability):
self.op = op
self.opNum = opNum
self.probability = probability
Graphviz
Graphviz是开放源码图形可视化软件。 图形可视化是一种将结构信息表示为抽象图形和网络图的方法。它在网络、生物信息学、软件工程、数据库和 网页设计、机器学习以及其他技术领域的可视化界面中都有重要的应用。
实际上它有固定的语法,根据固定的语法,该工具就可以生成对应的图像。比如:
在使用的时候,我们需要安装两个工具graphviz
和python-graphviz
第一个工具安装好后可以在相应的文件下找到dot
命令,我们只要使用该命令就可以编译上述语法的文件变成
pdf或者png之类的图像数据。因此要把这个命令的路径加入到环境变量Path里面,以便让系统能够找到这个命令的位置!
第二个工具是一个python库,用来通过编程语言生成绘图的语法,可以实现自动化。
下面就是我自动生成一个任意树的代码:
def drawChildren(dot,tree,nid):
for child_node in tree.children(nid):
child_nid = child_node.identifier
dot.node(child_nid,str(child_node.data.opNum))
dot.edge(nid,child_nid,child_node.data.probability)
drawChildren(dot,tree,child_nid)
上面的递归函数就绘制出来了树的图像。
最终加载数据生成外加绘制代码
if __name__ == '__main__':
startToken = 'start(开始)'
endToken = 'end(结尾)'
n_seqs = 10
n_steps = 100
model_path = os.path.join('model', 'behavior')
checkpoint_path = model_path
with open(os.path.join(model_path,'allData.pkl'),'rb') as f: #读取所有数据
allData = pickle.load(f)
with open(os.path.join(model_path,'testData.pkl'),'rb') as f: #读取测试数据
testData = pickle.load(f)
with open(os.path.join(model_path,'trainData.pkl'),'rb') as f: #读取测试数据
trainData = pickle.load(f)
converter = read_utils.TextConverter(allData) #要用所有数据编码
if os.path.isdir(checkpoint_path):
checkpoint_path =\
tf.train.latest_checkpoint(checkpoint_path)
model = model.CharRNN(converter.vocab_size,sampling=True,
num_seqs=n_seqs,
num_steps=n_steps,
# lstm_size=FLAGS.lstm_size,
# num_layers=FLAGS.num_layers,
# learning_rate=FLAGS.learning_rate,
# train_keep_prob=FLAGS.train_keep_prob,
use_embedding=True,
# embedding_size=FLAGS.embedding_size
)
model.load(checkpoint_path) #读取权重
# position = model.prediction_next_n([5],converter.vocab_size,3)
#下面开始建立一个树
tree = Tree()
#创建第一个节点
tree.create_node(startToken,
str(tree.size()+1),
data=OpData(startToken,converter.word_to_int_table[startToken],'100%')) #(tag[, identifier[, parent[, data]]])
#tree,nid,before_list 下面开始递归的绘制所有节点!
nid = str(tree.size())
before_list = [converter.word_to_int_table[startToken]]
next_n = 3 #设置预测步数
depth = 50 #设置树的深度
pro_threshold = 0.5 #设置显示阈值数目
#开始函数
if len(before_list) > depth:
# return
pass
pred = model.prediction_next_n(before_list,converter.vocab_size,next_n)
pred.reverse()
pro_com = 0
for tup in pred:
new_nid = str(tree.size()+1)
tree.create_node(converter.int_to_word_table[tup[0]],
new_nid,
nid,
OpData(converter.int_to_word_table[tup[0]],tup[0],'%.2f%%'%(tup[1]*100)))
new_before_list = before_list.copy() #一定要拷贝
if converter.int_to_word_table[tup[0]] != endToken: #如果当前不是结尾,则继续调用递归函数进行预测
new_before_list.append(tup[0])
genChildren(tree,new_nid,new_before_list,next_n,depth,pro_threshold) #递归调用生成树
pro_com = pro_com + tup[1]
if pro_com > pro_threshold:
break
#下面开始绘制这颗树
dot = Digraph(comment='The Test Table')
dot.node(nid, str(tree.get_node(nid).data.opNum))
#dot,tree,nid下面开始递归的绘制所有图像
for child_node in tree.children(nid):
child_nid = child_node.identifier
dot.node(child_nid,str(child_node.data.opNum))
dot.edge(nid,child_nid,child_node.data.probability)
drawChildren(dot,tree,child_nid)
dot.render('test-output/test-table.gv', view=True)