- pytorch 설치
- CUDA Toolkit 설치
$ wget https://developer.download.nvidia.com/compute/cuda/11.2.0/local_installers/cuda_11.2.0_460.27.04_linux.run
$ sudo sh cuda_11.2.0_460.27.04_linux.run
- Anaconda3 설치
- 다음으로 설치에서 생긴 환경 변수의 변경을 적용하기 위해 bashrc를 실행시킨다.
source ~/.bashrc
환경 변수 적용이 완료되고 설치가 정상적으로 완료 되면 (base) 표시가 생성된다.
conda --version
conda search python # 사용 가능한 python 버전 출력하는 명령어
각 그룹별 나눠서 데이터를 구축해야할 것 같다고 생각해 먼저 그룹을 나눴다.
가족 , 친구 , 연인 , 직장동료 , 기타 등등
나눈 그룹별 이미지를 캐글을 통해 데이터를 수집했다.
- cuDNN 8.1.0 설치
다운로드 받은 파일을 압축풀어서 파일 복사합니다.
$ cd 다운로드
$ tar xvzf cudnn-11.2-linux-x64-v8.1.0.77.tgz
$ sudo cp cuda/include/cudnn* /usr/local/cuda/include
$ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
$ sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
- Tensorflow 설치
- pip 명령을 사용하여 tensorflow를 설치합니다.
$ pip3 install tensorflow
- python에서 tensorflow 모듈을 불러와서 설치가 제대로 되었는지 확인합니다.
$ python3 >> import tensorflow as tf (모듈 로드) >> tf.__version__ (버전 확인) >> tf.config.list_physical_devices('GPU') (GPU 체크)
- Pycharm 설치
- 커뮤니티 버전 다운
- Docker 설치
- 강력하게 독립 환경을 구성하기 위해 Docker 활용
실행 후 cuda, cudnn 설치 확인
$ python >> import torch >> torch.cuda.is_available() True >> torch.backends.cudnn.enabled True
인터프리터 세팅
코드 작성 중
모델을 훈련하려면 이미지와 레이블이 첨부 된 데이터 세트가 필요합니다. 그러나 일반적으로 이미지 분류에 사용할 수있는 데이터 세트는 해당 폴더에 저장된 이미지로 구성됩니다. 데이터 세트는 5가지 유형의 이미지로 구성되며 해당 폴더에 저장됩니다.
이러한 구조에서 데이터 세트를 준비하기 위해 PyTorch는 데이터 세트를 쉽게 준비 할 수있는 ImageFolder 클래스를 제공합니다 . 데이터 디렉토리를 전달하기 만하면 모델 학습에 사용할 수있는 데이터 세트가 제공됩니다
아직 데이터 전처리가 완벽하지 않아 폴더 내 이미지가 없으므로 다음 단계 미진행!
- class별 데이터 개수 차이가 크다 (no relation-30개 미만 / family-1000개)
- traing accuracy와 test accuracy의 차이가 크다 (데이터가 training set에 overfitting이 일어났을 가능성 고려)
- 모델 성능 개선을 위해 train, test, validation 비율 조정 필요
1. friends : 약3300장 -> train:2000 , test:660 , validation:660
2. family : 약1500장 -> train:950 , test:300 , validation:300
3. couple : 약1400장 -> train:900 , test:250 , validation:250
4. professional : 약5000장 -> train:3000 , test:1000 , validation:1000
5. no relation : 약400장 -> train:250 , test:70 , validation:70
- PISC보다 명확하나 클래스별 추가적인 분류작업 필요
- 분류작업 완료시 PISC 데이터셋에서 걸러낸 데이터와 합칠 예정
1. friends : couple클래스와 비슷하거나 사람이 보기에도 부적절한 이미지 제외
2. family : 누가봐도 가족임을 판별가능한 이미지로만 선별
3. couple : 스킨십,친밀도가 강하거나 웨딩사진이 포함된 이미지 위주
4. professional : 옷차림, 물건, 장소 등을 고려하여 이미지 선별
5. no relation : 시선, 거리감, 길거리 등을 고려하여 이미지 선별
1. 표정, 포즈, 감성 등의 핵심적 속성 및 행동 분석
2. 특정 개인 쌍에 대한 관계 예측을 먼저 하고 주변 지역을 사용하여 예측을 구체화 (두 단계를 거쳐 예측)
3. 그래프 뉴럴 네트워크(GGNN) , 그래프 추론 모델(GRM) 등 그래프 Attention 메커니즘을 도입하여 내부 정보를 탐색
4. 이미지 인식 - PPRN으로 추론 모드로 구성 후 RNN을 통해 관계 메시지를 전파
5. 연결된 노드의 가중치 계수를 계산하기 위해 소셜 그래프와 메시지를 집계하여 두 개의 대규모 벤치마크에 대한 실험
* GNN 관련 논문 분석 - 그래프는 점들과 그 점들을 잇는 선으로 이루어진 데이터 구조이기에 관계, 상호작용과 같은 추상적인 개념을 다루기에 적합
* Scene graph generation by iterative message passing : CNN으로 탐지된 물체들을 scene graph를 만들어서 관계를 파악
* 이미지에서 소셜 관계 그래프를 생성 한 다음, 그래프 노드 간의 일관성을 강화하여 새로운 이미지를 수신하여도 예측에 성공하고 그래프를 계속
개선할 수 있도록 작업 예정
-> CNN 모델들을 비교하여 성능 테스트 해볼 것
- ResNet
- AlexNet
- DenseNEt
- Inception
- MobileNet-v3-large(small)
+) Confusion matrix 그리기
1. friends : 남녀 친구인경우 couple 클래스와 비슷하거나, 사람 눈으로도 판별하기 힘든 친구 이미지 제외 (1872 / 693)
2. family : 누가봐도 가족임을 판별가능한 이미지로만 선별 / 아기가 있다면 family, 부부만 있다면 couple (929 / 288)
3. couple : 스킨십,친밀도가 강하거나 웨딩사진이 포함된 이미지 선정 (898 / 294)
4. professional : 옷차림, 스포츠, 장소, 물건 등을 고려하여 이미지 선정 (2811 / 918)
5. no relation : 시장, 이발소 등 손님과의 관계가 있는 사진 / 시선, 거리감, 길거리 등을 고려하여 이미지 선정 (235 / 77)
구성한 모델을 통해 초기화를 한다. 즉 모델 내의 모든 모듈과 하위 모듈에 대해 지정된 기능이 호출됩니다.
class DenseNet(nn.Module):
def __init__(self, nblocks, growth_rate=12, reduction=0.5, num_classes=5, init_weights=True):
super().__init__()
self.growth_rate = growth_rate
inner_channels = 2 * growth_rate # output channels of conv1 before entering Dense Block
self.conv1 = nn.Sequential(
nn.Conv2d(3, inner_channels, 7, stride=2, padding=3),
nn.MaxPool2d(3, 2, padding=1)
)
self.features = nn.Sequential()
for i in range(len(nblocks)-1):
self.features.add_module('dense_block_{}'.format(i), self._make_dense_block(nblocks[i], inner_channels))
inner_channels += growth_rate * nblocks[i]
out_channels = int(reduction * inner_channels)
self.features.add_module('transition_layer_{}'.format(i), Transition(inner_channels, out_channels))
inner_channels = out_channels
self.features.add_module('dense_block_{}'.format(len(nblocks)-1), self._make_dense_block(nblocks[len(nblocks)-1], inner_channels))
inner_channels += growth_rate * nblocks[len(nblocks)-1]
self.features.add_module('bn', nn.BatchNorm2d(inner_channels))
self.features.add_module('relu', nn.ReLU())
self.avg_pool = nn.AdaptiveAvgPool2d((1,1))
self.linear = nn.Linear(inner_channels, num_classes)
# weight initialization
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.conv1(x)
x = self.features(x)
x = self.avg_pool(x)
x = x.view(x.size(0), -1)
x = self.linear(x)
return x
def _make_dense_block(self, nblock, inner_channels):
dense_block = nn.Sequential()
for i in range(nblock):
dense_block.add_module('bottle_neck_layer_{}'.format(i), BottleNeck(inner_channels, self.growth_rate))
inner_channels += self.growth_rate
return dense_block
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
def DenseNet_121():
return DenseNet([6, 12, 24, 6])
원하던 행렬이 아닌데 ,, 문제해결을 위해 원인 찾는중 ,,
1. ResNet : layer들의 feature map을 계속해서 다음 layer의 입력과 연결하는 방식이며, feature map끼리 더하기를 해주는 방식 / Residual Block를 이해하면 전체적인 구조 쉽게 이해 가능
2. DenseNet : layer들의 feature map을 계속해서 다음 layer의 입력과 연결하는 방식이며, feature map끼리 Concatenation 을 시키는 것
3. AlexNet : nn.Sequential and nn.Dropout이 핵심!
Sequential은 여러 계층을 제공하며, Sequential 모듈이 호출되면 각 계층을 순서대로 입력에 적용
Dropout는 정규화의 한 형태다. 모델이 커질수록 많은 데이터셋에서 보다 정확하게 수행하기 위해 훨씬 더 많은 수의 매개 변수를 갖게 된다.
즉, 이미지 분류 학습 동안 일반적인 이미지 기능을 학습하지 않고 암기만 한다. 이는 검증에서 불량한 성능은 보이게 된다. 이 과적합 문제를 해결하기 위해 정규화를 사용!
결과 : Dataset이 충분하지 않고 클래스 수가 5개 밖에 없으므로 cnn구조는 정확도가 가장 좋은 ResNet을 사용하며,
LSTM과 연결지어 2단계를 거처 분류한다면 더 좋은 성능 가능한지 연구
- 1,2차 테스트 결과보다 약 1% 상승하였으나 etc클래스에 일치하지 않는 그림 많이 보임
- { friends, couple, family } 를 중심으로 기준을 명확히 정한 후, 전체적인 전처리 진행 필요성 보임
class MobileNet(nn.Module):
def __init__(self, input_channel, num_classes=4):
super(MobileNet, self).__init__()
self.network = nn.Sequential(
nn.Conv2d(input_channel, 32, kernel_size=3, stride=2, padding=1, bias=False),
nn.BatchNorm2d(32),
nn.ReLU(True),
dw_block(32, kernel_size=3),
one_by_one_block(32, 64),
dw_block(64, kernel_size=3, stride=2),
one_by_one_block(64, 128),
dw_block(128, kernel_size=3),
one_by_one_block(128, 128),
dw_block(128, kernel_size=3, stride=2),
one_by_one_block(128, 256),
dw_block(256, kernel_size=3),
one_by_one_block(256, 256),
dw_block(256, kernel_size=3, stride=2),
one_by_one_block(256, 512),
# 5 times
dw_block(512, kernel_size=3),
one_by_one_block(512, 512),
dw_block(512, kernel_size=3),
one_by_one_block(512, 512),
dw_block(512, kernel_size=3),
one_by_one_block(512, 512),
dw_block(512, kernel_size=3),
one_by_one_block(512, 512),
dw_block(512, kernel_size=3),
one_by_one_block(512, 512),
dw_block(512, kernel_size=3, stride=2),
one_by_one_block(512, 1024),
dw_block(1024, kernel_size=3, stride=2),
one_by_one_block(1024, 1024),
)
self.linear = nn.Linear(1024, num_classes)
def forward(self, x):
body_output = self.network(x)
avg_pool_output = F.adaptive_avg_pool2d(body_output, (1, 1))
avg_pool_flat = avg_pool_output.view(avg_pool_output.size(0), -1)
output = self.linear(avg_pool_flat)
return output
결과 : 커플 이외의 많은 물체 판별
- 임계치를 설정하여 물체 판별 정확도 올리기
- 추론이 아닌 훈련으로 모델을 사용 고려
- 사람 영역 검출만을 가지고 판별하기위해 사람 이외 주변 물체 판별하지 않도록 조절 필요
- 데이터 전처리 필요
import torch
from glob import glob
from sklearn.model_selection import train_test_split
# Model
model = torch.hub.load('ultralytics/yolov5', 'yolov5x') # or s yolov5m, yolov5x, custom
train_img_list = glob('/home/parkchan/anaconda3/envs/PISC/social group/image/train/*/*.jpg')
test_img_list = glob('/home/parkchan/anaconda3/envs/PISC/social group/image/test/*/*.jpg')
# Images
# img = '/home/parkchan/anaconda3/envs/PISC/social group/image/train/couple/06438.jpg' # or file, PIL, OpenCV, numpy, multiple
with open("/home/parkchan/anaconda3/envs/PISC/social group/image/train.txt", "w") as f:
f.write('\n'.join(train_img_list) + '\n')
with open("/home/parkchan/anaconda3/envs/PISC/social group/image/test.txt", "w") as f:
f.write('\n'.join(test_img_list) + '\n')
import yaml
with open('./image/data.yaml', 'r') as f:
data = yaml.load(f)
print(data)
data['train'] = './image/'
data['test'] = './image/'
with open('./image/data.yaml', 'w') as f:
yaml.dump(data, f)
print(data)
-> 이미지내의 bbox 특정 영역을 추출해 그 안에서 관계를 유츄하기로 함.
yolo를 통해 사람이 검출되는 경우에만 예측 진행
이미지 내의 여러 클래스가 존재하고, 두 사람간의 관계를 전부 나타냄
-> 한 이미지의 특정 두사람을 검출하여, 두사람간의 관계를 유추, 즉 이미지내 사람들의 모든 관계 유추
Test_set 설정
아키텍쳐
구성
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
from person_pair import person_pair
from ggnn import GGNN
from torch.distributions import Bernoulli
from vgg_v1 import vgg16_rois_v1
import math
class GRM(nn.Module):
def __init__(self, num_class = 3,
ggnn_hidden_channel = 4098,
ggnn_output_channel = 512, time_step = 3,
attr_num = 80, adjacency_matrix=''):
super(GRM, self).__init__()
self._num_class = num_class
self._ggnn_hidden_channel = ggnn_hidden_channel
self._ggnn_output_channel = ggnn_output_channel
self._time_step = time_step
self._adjacency_matrix = adjacency_matrix
self._attr_num = attr_num
self._graph_num = attr_num + num_class
self.fg = person_pair(num_class)
self.full_im_net = vgg16_rois_v1(pretrained=False)
self.ggnn = GGNN( hidden_state_channel = self._ggnn_hidden_channel,
output_channel = self._ggnn_output_channel,
time_step = self._time_step,
adjacency_matrix=self._adjacency_matrix,
num_classes = self._num_class)
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(self._ggnn_output_channel * (self._attr_num + 1) , 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 1)
)
self.ReLU = nn.ReLU(True)
self._initialize_weights()
def forward(self, union, b1, b2, b_geometric, full_im, rois, categories):
batch_size = union.size()[0]
# full image
rois_feature = self.full_im_net(full_im, rois, categories)
contextual = Variable(torch.zeros(batch_size, self._graph_num, self._ggnn_hidden_channel), requires_grad=False).cuda()
contextual[:, 0:self._num_class, 0] = 1.
contextual[:, self._num_class:, 1] = 1.
start_idx = 0
end_idx = 0
for b in range(batch_size):
cur_rois_num = categories[b, 0].data[0]
end_idx += cur_rois_num
idxs = categories[b, 1:(cur_rois_num+1)].data.tolist()
for i in range(cur_rois_num):
contextual[b, int(idxs[i])+self._num_class, 2:] = rois_feature[start_idx+i, :]
start_idx = end_idx
# first glance scores
scores, fc7_feature = self.fg(union, b1, b2, b_geometric)
# ggnn input
fc7_feature_norm_enlarge = fc7_feature.view(batch_size, 1, -1).repeat(1, self._num_class, 1)
contextual[:, 0: self._num_class, 2:] = fc7_feature_norm_enlarge
ggnn_input = contextual.view(batch_size, -1)
#ggnn forward
ggnn_feature = self.ggnn(ggnn_input)
ggnn_feature_norm = ggnn_feature.view(batch_size * self._num_class, -1)
#classifier
final_scores = self.classifier(ggnn_feature_norm).view(batch_size, -1)
return final_scores
def _initialize_weights(self):
for m in self.classifier.modules():
cnt = 0
if isinstance(m, nn.Linear):
if cnt == 0:
m.weight.data.normal_(0, 0.001)
else :
m.weight.data.normal_(0, 0.01)
m.bias.data.zero_()
cnt += 1
backbone = torchvision.models.vgg16(pretrained=True).features[:-1]
backbone_out = 512
backbone.out_channels = backbone_out
anchor_generator = torchvision.models.detection.rpn.AnchorGenerator(sizes=((128, 256, 512),),aspect_ratios=((0.5, 1.0, 2.0),))
resolution = 7
roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], output_size=resolution, sampling_ratio=2)
box_head = torchvision.models.detection.faster_rcnn.TwoMLPHead(in_channels= backbone_out*(resolution**2),representation_size=4096)
box_predictor = torchvision.models.detection.faster_rcnn.FastRCNNPredictor(4096,21) #21개 class
model = torchvision.models.detection.FasterRCNN(backbone, num_classes=None,
min_size = 600, max_size = 1000,
rpn_anchor_generator=anchor_generator,
rpn_pre_nms_top_n_train = 6000, rpn_pre_nms_top_n_test = 6000,
rpn_post_nms_top_n_train=2000, rpn_post_nms_top_n_test=300,
rpn_nms_thresh=0.7,rpn_fg_iou_thresh=0.7, rpn_bg_iou_thresh=0.3,
rpn_batch_size_per_image=256, rpn_positive_fraction=0.5,
box_roi_pool=roi_pooler, box_head = box_head, box_predictor = box_predictor,
box_score_thresh=0.05, box_nms_thresh=0.7,box_detections_per_img=300,
box_fg_iou_thresh=0.5, box_bg_iou_thresh=0.5,
box_batch_size_per_image=128, box_positive_fraction=0.25
)
for param in model.rpn.parameters():
torch.nn.init.normal_(param,mean = 0.0, std=0.01)
for name, param in model.roi_heads.named_parameters():
if "bbox_pred" in name:
torch.nn.init.normal_(param,mean = 0.0, std=0.001)
elif "weight" in name:
torch.nn.init.normal_(param,mean = 0.0, std=0.01)
if "bias" in name:
torch.nn.init.zeros_(param)
backbone으로 VGG16을 사용하며 마지막 max pooling층은 제거해 줍니다. Faster RCNN을 사용하기 위해서는 fully connected layer를 만들기 위해 최종 backbone output채널이 512임을 알려주어야 합니다. 이후 anchor generator, roi pooler, box head, box predictor를 각각 만들어 줍니다.
모델은 torchvision.models.detection에 있는 FasterRCNN을 사용합니다. 마지막으로 weight와 bias를 초기화합니다.
이후 training을 통해 학습하여 object boxes 로 사용하려 했으나 다시 ... GNN접고 토의 결과대로
1) 데이터 전처리(사람 영역별 자르기)
2) fine tuning
3) feature extraction(vector)
4) concatenate
5) classfication(6가지 클래스)
(2,3과정) 영역에 대한 특징벡터 추출
특징 벡터는 단순히 신경망 계층의 출력에서 가져온 숫자 목록입니다. 이 벡터는 인풋데이터로 다시 사용되며 향후 클래스를 분류하는 작업에 사용할 예정
사전 훈련된 모델(ResNet18)을 통해 특징벡터 추출
def get_vector(image_name):
img = Image.open(image_name)
t_img = Variable(normalize(to_tensor(scaler(img))).unsqueeze(0))
my_embedding = torch.zeros(512)
def copy_data(m, i, o):
my_embedding.copy_(o.data)
h = layer.register_forward_hook(copy_data)
model(t_img)
h.remove()
return my_embedding
pic_one_vector = get_vector(pic_one)
pic_two_vector = get_vector(pic_two)
cos = nn.CosineSimilarity(dim=1, eps=1e-6)
cos_sim = cos(pic_one_vector.unsqueeze(0),
pic_two_vector.unsqueeze(0))
print('\nCosine similarity: {0}\n'.format(cos_sim))
class resnet(nn.Module):
def __init__(self):
super().__init__()
self.model = models.resnet18(pretrained=True)
self.features = nn.Sequential(*list(self.model.children())[:-1])
# class : friends, family, couple, professional, commercial, no_relation
self.num_classes = 6
self.fc1 = nn.Linear(2000, 1024)
self.fc2 = nn.Linear(1024, 512)
self.fc3 = nn.Linear(512, self.num_classes)
def forward(self, x1, x2):
x1 = self.model(x1)
x2 = self.model(x2)
x = torch.cat((x1, x2), dim=1)
x = x.view(x.size(0), -1)
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x
+) 추가적으로 먹방 데이터 수집(URL
대상 : 1~2인상 + 식사하는사람 / 음식+음료 5가지 이상 // 촬영방향:<정면,측면> <45도,10도> // 수집은 4가지 경우를 5개씩 !
고려사항 : 양으로 승부하거나 음식이 다양하지 않은 먹방 제외 / 화면전환이 자주 일어나는 먹방 제외
TypeError: object of type 'NoneType' has no len()
데이터로드 부분에서 문제발생! 해결하기 위해 수정 및 검색중
valueerror: decompressed data too large
from PIL import Image, ImageFile
PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
IndexError: list index out of range
리스트 범위 수정하여 해결
이후 강보경님이 데이터셋 관련 에러를 해결하며 다음 epoch로 넘어갈 수 있었다!
사람영역만을 가지고 관계를 유추하는 것은 이미지 전체 영역에서 특징을 추출하는 것보다 성능이 좋지 못하다.
이미지 전체 및 주변 영향을 받는 것을 알 수 있다. 또한 데이터를 재구성한 것이 성능 측면에서 긍정적인 영향을 미쳤다고 생각한다.
+) 측면 피드백 필요, 추후 다음 데이터 수집부터 고려하여 다시 재수집 예정
- 재구성한 데이터셋으로 70% 내외의 성능을 얻었던 인식기 코드
- 사람 영역을 잘라서 두 사람 간 관계를 유추한 인식기 코드
1) 그룹 활동 인식 모델학습
python main.py --dataset 'volleyball' --num_frame 3 --enc_layers 1 --lr_scheduler 'cyclic' --lr 1e-6 --max_lr 1e-4 --lr_step 5 --drop_rate 0.1
2) 에러발생
ImportError: cannot import name '_new_empty_tensor' from 'torchvision.ops'
1) 에러 해결
ImportError: cannot import name '_new_empty_tensor' from 'torchvision.ops'
Python 3.7.7
Pytorch 1.6.0
Torchvision 0.7.0
2) wandb 계정 생성 및 API key 복사
wandb: (1) Create a W&B account
wandb: (2) Use an existing W&B account
wandb: (3) Don't visualize my results
wandb: Enter your choice: 2
wandb: Paste an API key from your profile and hit enter:
3) 에러 발생
NotADirectoryError: [Errno 20] Not a directory: '/home/parkchan/Downloads/aai4r-Group-Activity-Recognition-main/wandb/run-20210809_165008-kd6602ue'
wandb: ERROR Abnormal program exit
six.raise_from(Exception("problem"), error_seen)
File "<string>", line 3, in raise_from
Exception: problem
wandb 에러 해결
프로젝트 경로 수정 및 wandb api 등록 후 계정 재접속으로 해결
dataload를 위해 데이터셋 다운중 (용량이 커서 오래걸림)
1) volleyball
2) NBA (중국 개발자에게 메일을 보내 답변을 받아 패스워드 입력 후 데이터셋 접근)
다운을 위해 바이두 사이트 회원가입 필요
Social Adaptive Module은 비디오에서 감독되는 그룹 행동 인식에 대한 차별적 제안과 프레임을 선택할 수 있습니다.
약하게 훈련된 사람들을 돕는데 있어 주요 인스턴스(사용자/프레임)는 서로 매우 관련이 깊습니다.
구체적으로, 먼저 가능한 모든 입력 기능에 대한 고밀도 관계 그래프를 구성합니다.
서로 간의 관계를 측정한 후, 선택한 피쳐를 기반으로 관계 그래프가 작성됩니다.
(a) 배구 데이터셋은 비디오 레벨 레이블만 제공하는 약하게 감독된 설정이 그룹 행동 인식에 도입되었습니다.
(b) 보다 까다로운 NBA는 저렴한 비용으로 웹에서 수집됩니다.
(c) 취약하게 감독되는 훈련을 완화하기 위해 Social Adaptive Module 제안.
주요 인스턴스(instance)가 일반적으로 서로 밀접하게 연관되어 있다는 가정.
NBA는 배구 경기에서의 활동에 비해 더 장기적인 시간을 가지고 있다.
구조 및 빠른 이동 속도로 인해 그룹 활동 분석에 새로운 과제가 제기됩니다. 우선, 선수 수는 서로 다를 수 있다.
반면에, 액티비티는 너무 빨라서 싱글 프레임은 이러한 플레이어를 추적하는 데 사용자 수준의 주석이 무용지물이다.
그러므로 배구 경기와 다른 비디오의 모든 사람들에게 라벨을 붙이기는 어렵다.
우리는 약하게 조정된 환경에서 이 벤치마크에 주석을 달았다. 때문에 이 데이터 집합을 사용할 수 있다.
동영상이 주어진 경우 주석의 목표는 그룹을 할당하는 것입니다.
해당 부문에 대한 활동. 수동으로 레이블을 지정하는 데 시간이 오래 걸립니다.
기존 주석 툴을 사용하여 대규모 데이터셋을 구성할 수 있으며, 주석의 효율성을 높이기 위해, NBA의 임원이 제공한 로그를 최대한 활용할 수 있다.
에러발생
해결
Dataset 폴더를 만들어서 경로를 설정해도 같은 에러가 발생해 dataloader.py와 volleyball.py 코드를 참고하여 "data_path"를 수정했다.
if args.dataset == 'volleyball':
data_path = args.dataset
image_path = data_path + "/videos"
1) test_group_acc
2) train_group_acc
3) test_mean_acc
4) train_loss
개인 핫스팟 연결을 통해 웹에 접근할 수는 있으나 웹에서 다운 받을 수는 없고 바이두 클라우드를 통해 받을 수 있다.
바이두 클라우드 계정 회원가입 완료
rpm 패키지 설치완료 " sudo alien -i baidunetdisk_3.5.0_amd64.rpm "
deb 패키지 설치완료 " sudo dpkg -i baidunetdisk_3.5.0_amd64.deb "
그러나 접속에러 ..!
중국측에 구글드라이브 공유 문의했으나 속도측면과 사이즈 크기상 불가능하다는 답변 받음
핸드폰 어플을 통해 다운을 받아 컴퓨터와 연결 후 다시 공유하려했으나 데이터 크기상 핸드폰 다운 실패
그래도 중국 바이두에 대해 처음으로 알아갈 수 있는 시간이였고 .. 용량을 2TB까지 다운가능하나 속도가 정말 느리다는 사실도 알게 되었다. 앞으로 두번다시는 쓸 일 없을 것 같다..
결과 분석 및 코드 확인
학습된 모델을 가지고 하나의 새로운 이미지로 테스트 (도쿄올림픽 여자배구 사진)
에러발생
model.eval()
AttributeError: 'dict' object has no attribute 'eval'
로드하는 도중 문제가 생겨서 수정 예정
> 'r_set' , 'r_spike' , 'r-pass' , 'r_winpoint' , 'l_set' , 'l-spike' , 'l-pass' , 'l_winpoint'
> 'r_set / r-pass' , 'r_spike' , 'r_winpoint' , 'l_set' / 'l-pass' , 'l-spike' , 'l_winpoint'
약 95%의 성능으로 그룹 활동 인식 검증
새로운 단일 이미지로 테스트 해보려했으나 에러를 해결하지 못해 일단 데이터셋 내의 이미지로만 결과 확인
이처럼 여러 개선 방안을 고려해서 모델을 재구축하는 과정에 있다. 각 과정을 그래프로 나타내 validation loss을 비교하며 성능을 개선 중
모델을 직접 구성해 성능을 개선해보려고 했으나 resnet,vgg보다 훨씬 성능이 안나옴
-> 개선방안 고려
resize, horizontally flip, vertically flip, shift, brightness, contrast, gamma, scale label
models.py 에서 사용한 args를 설정(모델링에 필요한 값)
-> argparse 사용
학습된 이미지를 검증하기 위해 로드하는 과정에서 문제발생 .. 간단하게 접근했는데 해결을 못하고 있다..
원인을 분석하던 과정 test loss를 찍어보니 nan값으로 나오는 것을 확인
해결 과정
학습 성능이 너무 높아서 나타나는 현상일 수 있음. 성능을 좀 낮추더라도 네트워크를 다시 구성해야 한다는 의견.
또한 , 가중치가 정규화되지 않았거나 가중치 규제가 필요하다.
1. Class Label에 대한 데이터 개수가 너무 적음 ( label당 불균형한 이미지 )
2. CNN 모델이 너무 얕아 특징을 분리하기 어려울 수 있음
3. validation set에 대한 loss가 커서 이를 줄이기 위한 방법이 필요
1. 단순하게 클래스 수를 줄여서 3가지 클래스로 분류 (professional(5000장)에 대한 이미지를 친구로 이동하거나 버림)
2. CNN 구조 개선 작업
3. Optimizer 와 Learning Rate 조정
SW 검증을 위해 데이터셋 다운로드중
관련된 논문 분석 및 코드 점검
기본 모델은 기능적인 인코딩 네트워크와 추정된 각 대표 클래스 기능의 유사성을 계산하는 분류 계층으로 구성됩니다.
적응에 대한 검증은 분류자에 대해 레이블이 지정되지 않은 대상, 데이터의 조건부를 교대로 최대화하고 특징 인코더에 대해 최소화함으로써 달성됩니다.
AttributeError: module 'torchvision.transforms' has no attribute 'GaussianBlur'
GaussianBlurpytorch 1.6에 존재하지 않았고, 1.7에서 추가되었다.
저번 그룹 행동 인식 검증에서 버전 다운 그레이드를 해서 생긴 에러!
다시 pytorch와 torchvision을 최신버전으로 업데이트!
해당 폴더에 파일 경로가 있는데도 불구하고 계속해서 에러가 발생
파일 경로부분 코드를 수정하면 또 다른 곳에서 파일을 못찾는다는 에러가 반복
다른 곳도 해당 폴더에 파일이 있는 것은 확인
dataset.py / return_dataset.py 내 각 클래스별 root 및 base_path 수정 마무리
utils 폴더의 path관련 py파일 경로 수정 마무리
코드에 알맞게 data폴더의 하위폴더 dataset 재구성 마무리
< 1 >
source domain이 target domain으로 바뀌는 상황을 도메인 이동이라고 하며, 도메인 적응은 높은 성능을 유지하면서 도메인 이동을 달성하는 기법입니다.
데이터셋은 office home / M3SDA이고 라벨이 부착된 데이터와 라벨이 부착되지 않은 데이터를 활용하여 작업을 실행한다.
어떻게든 이전 task(target domain)서 배운 지식을 사용해 새로운 상황에서도 맞출 확률을 올려주는 것이 목표다.
Source domain에서 classification 성능 우수 , Source domain과 target domain을 구별하지 못하게 한다.
< 2 >
학습, 테스트, 검증 loss 값이 전부 nan이 나왔다. 저번과 같은 현상인데 아마 이유가 따로 있을 것 같다.
현 개발자에게 이슈를 남겨놨으니 보고 확인할 예정
정확도 그래프는 심한 편차를 보인다. 저런 현상도 어떠한 것을 나타내는지 자료를 찾아보고있다.