图1
初始化和viterbi给结构解码
class Decoder(object):
def __init__(self, alphas, betas, steps):
....................
def viterbi_decode(self):
# 注意这里的[:2]是取前两维的意思,就是取图1中的网络框架。
prob_space = np.zeros((self.network_space.shape[:2]))
path_space = np.zeros((self.network_space.shape[:2])).astype('int8')
# 循环遍历layer层,即图1中的横向坐标。
for layer in range(self.network_space.shape[0]):
if layer == 0: # 初始化prob和path的值。
prob_space[layer][0] = self.network_space[layer][0][1]
prob_space[layer][1] = self.network_space[layer][0][2]
path_space[layer][0] = 0
path_space[layer][1] = -1
else: # 开始遍历每一层中的每一级节点。
for sample in range(self.network_space.shape[1]):
# 特殊节点处理。
if layer - sample < - 1:
continue
# 先分别计算向上,同级和向下一级,三种情况时的概率。
local_prob = []
# 遍历向上,同级和向下共三级。
for rate in range(self.network_space.shape[2]): # k[0 : ➚, 1: ➙, 2 : ➘]
# 特殊情况处理。
if (sample == 0 and rate == 2) or (sample == 3 and rate == 0):
continue
else:
# 记录当前rate指向路径的prob。(出发节点的prob * 当前rate指向路径的prob)
local_prob.append(prob_space[layer - 1][sample + 1 - rate] *
self.network_space[layer][sample + 1 - rate][rate])
# 到达当前节点的prob为所有rate指向路径的prob的最大值。
prob_space[layer][sample] = np.max(local_prob, axis=0)
# 获得沿轴axis=0,local_prob中最大值的索引。
rate = np.argmax(local_prob, axis=0)
# 为啥sample==3的时候就变成-rate了呢???
path = 1 - rate if sample != 3 else -rate
path_space[layer][sample] = path # path[1 : ➚, 0: ➙, -1 : ➘]
# 最后一层中prob最大值的索引。axis=-1表示纵轴。
output_sample = prob_space[-1, :].argmax(axis=-1)
# 这边的12是指一共12层。
actual_path = np.zeros(12).astype('uint8')
# 最后一层的输出就是最大的prob索引。然后逐层往前推算。
actual_path[-1] = output_sample
for i in range(1, self._num_layers):
actual_path[-i - 1] = actual_path[-i] + path_space[self._num_layers - i, actual_path[-i]]
# 返回路径和路径转空间的结果,后者就是建一个12x4x3的零矩阵,然后把对应位置填1而已。
return actual_path, network_layer_to_space(actual_path)
给cell结构解码
这里发现跟我原本想的有出入,我原以为是每一个cell对应一组alpha,现在发现是所有的cell共享一组alpha
def genotype_decode(self):
def _parse(alphas, steps):
gene = []
start = 0
n = 2
# steps即要建立的块数。
for i in range(steps):
end = start + n
# 将start到end范围内的alpha按行最大值从大到小排序。 *****
edges = sorted(range(start, end), key=lambda x: -np.max(alphas[x, 1:])) # ignore none value
# 选择前两条alpha参数最大的边,对应当前block的两个输入值。
top2edges = edges[:2]
for j in top2edges:
# 获取alphas中第j行的最大值索引。j对应输入向量的块。
best_op_index = np.argmax(alphas[j]) # this can include none op
# 压入list。
gene.append([j, best_op_index])
# 更新start和n值,由于此时block多了一块,因此n要加一。
start = end
n += 1
return np.array(gene)
# 按纵轴进行softmax操作。
normalized_alphas = F.softmax(self._alphas, dim=-1).data.cpu().numpy()
# 获取当前cell的结构。
gene_cell = _parse(normalized_alphas, self._steps)
return gene_cell