def per_step()

in eval/PER_src/seq_alignment.py [0:0]


def per_step(valLoader,
             model,
             criterion,
             downsamplingFactor):

    model.eval()
    criterion.eval()

    avgPER = 0
    varPER = 0
    nItems = 0

    print("Starting the PER computation through beam search")
    bar = progressbar.ProgressBar(maxval=len(valLoader))
    bar.start()

    for index, data in enumerate(valLoader):

        bar.update(index)

        with torch.no_grad():
            seq, sizeSeq, phone, sizePhone = prepare_data(data)
            c_feature = model(seq)
            sizeSeq = sizeSeq / downsamplingFactor
            predictions = torch.nn.functional.softmax(criterion.getPrediction(c_feature),
                                                      dim=2).cpu()
            c_feature = c_feature
            phone = phone.cpu()
            sizeSeq = sizeSeq.cpu()
            sizePhone = sizePhone.cpu()

            mutex = Lock()
            manager = Manager()
            poolData = manager.list()

            processes = []
            for b in range(sizeSeq.size(0)):
                l_ = min(sizeSeq[b] // 4, predictions.size(1))
                s_ = sizePhone[b]
                p = torch.multiprocessing.Process(target=get_local_per,
                                                  args=(poolData, mutex, predictions[b, :l_].view(l_, -1).numpy(),
                                                        phone[b, :s_].view(-1).numpy().astype(np.int32), criterion.BLANK_LABEL))
                p.start()
                processes.append(p)
            for p in processes:
                p.join()

            avgPER += sum([x for x in poolData])
            varPER += sum([x*x for x in poolData])
            nItems += len(poolData)

    bar.finish()

    avgPER /= nItems
    varPER /= nItems

    varPER -= avgPER**2
    print(f"Average PER {avgPER}")
    print(f"Standard deviation PER {math.sqrt(varPER)}")