• 카테고리

    질문 & 답변
  • 세부 분야

    딥러닝 · 머신러닝

  • 해결 여부

    미해결

공분산들의 평균에 대해서 궁금한 점이 있습니다

21.06.03 19:59 작성 조회수 148

0

안녕하세요

여러 배치들의 공분산을 구하려고 했는데, 대상은 이미지의 피처맵입니다

(메모리 문제 때문에 분리해서 진행) 예를 들어 전체 배치가 100이라고 하면 (25, 25, 25, 25)로 나눠서 각각

np.cov 함수로 공분산을 구했는데 마지막에 합칠 때는 단순하게 더해서 /4를 했습니다

그런데 결과도 이상하게 나오고 실제 100 전체를 했을 때랑 값 차이도 있는데 배치 100개를 한 번에 못봐서 그런 것인지 아니면 제가 합칠 때 잘못 하는건지 궁금하네요

답변 3

·

답변을 작성해보세요.

0

당연히 전체 데이터의 평균과 샘플링된 데이터의 평균은 다릅니다만,

전체 데이터가 정규 분포를 이루고 있을때, 샘플링 데이터 평균을 여러번 반복해서 구한 뒤에 개별 평균값들을 다시 평균해 보면 전체 데이터의 평균에 가까워지는 특성이 있습니다. 코드는 이런 특성을 이용해서 구성한 것 같습니다.

유영재님의 프로필

유영재

질문자

2021.06.09

답변 감사드립니다. 혹시 공분산도 마찬가지일까요?

유영재님의 프로필

유영재

질문자

2021.06.10

약 epoch 20번 정도 실험했을 때는 보완을 하는 것 같습니다

0

유영재님의 프로필

유영재

질문자

2021.06.08

코드는 아래와 같습니다. train_dataloader에서 배치사이즈(32)만큼 불러와서 추론을 하게 됩니다

그리고 미리 hook으로 설정한 레이어 출력(layer1, layer2, layer3)을 가지고 서로 다른 피처맵 사이즈기 때문에 fold, unfold 기법으로 사이즈를 맞춰준 후 concat을 합니다

그러면 각 피처맵이 56x56(H*W)으로 동일하게 나온 상황에서 각 56x56 위치의 평균과 공분산을 구하게 됩니다 (mean, cov)

그런데 여기서 제가 궁금한 점은 하드웨어 제약 때문에 모든 train에 대한 mean, cov를 구하지 못하고, 미니 배치 단위로 mean, cov를 구하고 이를 전체를 아우르는 mean_output, cov_output에 np.add를 실행합니다. 그리고 모든 epoch과 배치가 끝나고 총 iteration만큼 나눠줍니다. 그런데 이것이 전체에 대한 mean, cov 식과 동일하다고 말할 수 있나? 이게 찝찝합니다

그러니까 따로 구한 공분산을 가지고 합할 때 합한 후 iteration으로 나눠도 구하려는 최종 값에 근접하는지? mean 부분도 문제가 되는지 궁금합니다

 감사합니다

for epoch in range(num_epochs):
    for (x, _) in tqdm(train_dataloader, '| feature extraction | train | %s |' % class_name):
        train_outputs = OrderedDict([('layer1', []), ('layer2', []), ('layer3', [])])

        # model prediction
        with torch.no_grad():
            _ = model(x.to(device))
        # get intermediate layer outputs
        for k, v in zip(train_outputs.keys(), outputs):
            train_outputs[k].append(v.cpu().detach())
        # initialize hook outputs
        outputs = []

        for k, v in train_outputs.items():
            train_outputs[k] = torch.cat(v, 0)

        # Embedding concat
        embedding_vectors = train_outputs['layer1']
        try:
            for layer_name in ['layer2', 'layer3']:
                embedding_vectors = embedding_concat(embedding_vectors, train_outputs[layer_name])
        except:
            print('memory lack error')

        # randomly select d dimension
        embedding_vectors = torch.index_select(embedding_vectors, 1, idx)
        # calculate multivariate Gaussian distribution
        B, C, H, W = embedding_vectors.size()
        print('B: {}, C: {}, H: {}, W: {}'.format(B, C, H, W))

        embedding_vectors = embedding_vectors.view(B, C, H * W)
        mean = torch.mean(embedding_vectors, dim=0).numpy()
        cov = torch.zeros(C, C, H * W).numpy()
        cov_inv = torch.zeros(C, C, H * W).numpy()
        I = np.identity(C)

        for i in range(H * W):
            cov[:, :, i] = np.cov(embedding_vectors[:, :, i].numpy(), rowvar=False) + 0.01 * I
            cov_inv[:, :, i] =  np.linalg.inv(cov[:, :, i])
        
        if not isinstance(mean_outputs, np.ndarray):
            mean_outputs = mean
        else:
            mean_outputs = np.add(mean_outputs, mean)

        if not isinstance(cov_inv_outputs, np.ndarray):
            cov_inv_outputs = cov_inv
        else:
            cov_inv_outputs = np.add(cov_inv_outputs, cov_inv)

        iteration += 1

mean_outputs /= iteration
cov_inv_outputs /= iteration

train_outputs = [mean_outputs, cov_inv_outputs]

with open(train_feature_filepath, 'wb') as f:
    pickle.dump(train_outputs, f,protocol=pickle.HIGHEST_PROTOCOL)

0

안녕하십니까,

어떤 문제인지 질문 내용으로는 제가 잘 이해가 되지 않는군요.

좀 더 상세하게 질문 기재 요청드립니다. 코드가 원하시는 바대로 안되시는 것 같은데, 해당 코드와 뭐가 문제인지들을 자세히 기재 부탁드립니다.