【Pytorch】 Pytorch 튜토리얼 3 - pytorch로 딥러닝하기

(Pytorch) Pytorch 튜토리얼 3 - pytorch로

NEURAL NETWORKS 구성

"""
# nn 패키지를 사용한 신경망 생성

신경망의 학습 과정
1. 학습 가능한 매개변수(또는 가중치(weight))를 갖는 신경망을 정의합니다.
2. 데이터셋(dataset)을 이용해 아래의 과정을 반복한다.
3. 입력을 신경망에서 전파(process == forward)합니다.
4. 손실을 계산합니다.
5. 변화도(gradient)를 신경망의 매개변수들에 역으로 전파 -> d_Loss / d_parametar 를 구한다. 
6. 신경망의 가중치를 갱신합니다. weight = weight - learning_rate * gradient
"""
pass
import torch
import torch.nn as nn
import torch.nn.functional as F 
# F를 import하는 이유 : Implements forward and backward definitions of an autograd operation. 
class Net(nn.Module): # nn.Module 클래스를 상속하여 Net 클래스를 생성한다.
    def __init__(self): # para 없음
        super(Net,self).__init__()  # child class에서 parent class의 __init__ 내용들을 사용하고 싶다.
        self.conv1 = nn.Conv2d(1,6,kernel_size = 3)
        self.conv2 = nn.Conv2d(6,16,kernel_size = 3)
        
        self.relu = nn.ReLU()
        self.maxP1 = nn.MaxPool2d(kernel_size=2,stride=2)

        self.fc1 = nn.Linear(16*6*6, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x): # para에 x가 들어간다!
        '''[홈페이지 방법]
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        print(x.size()) # 1*6*15*15
        '''
        x = self.maxP1(self.relu(self.conv1(x)))
        # print(x.size()) # masP1의 stride가 1일 때. -> 1*6*29*29. // stride가 2일 때. -> 1*6*15*15 
        
        x = F.max_pool2d(F.relu(self.conv2(x)), 2) # maxpool은 정사각형이기 때문에 2만 넣어도 (2,2)로 인식한다.
        x = x.view(-1, self.num_flat_features(x))  # torch.Size([1, 16, 6, 6])  -> num_flat_feature를 하고 난 후의 x의 torch.Size([1, 576])

        # x = F.relu(self.fc1(x)) [홈페이지 방법]
        # print("num_flat_feature를 하고 난 후의 x의" , x.shape)
        x = self.relu(self.fc1(x)) 
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension (3차원이면 channel, 4차원이면 이미지 갯수)
        num_features = 1
        for s in size:
            num_features *= s   # 예를 들어 tensor sief (120, 6, 6) 라면, 6*6 = 36 을 return 한다.
        return num_features  

net = Net()
print(net)  # __init__ 에 정의한 내용이 나타난다. forward 아님! 

"""
forward 함수만 정의하고 나면, (변화도를 계산하는) backward 함수는 autograd 를 사용하여 자동으로 정의된다. 
모델의 학습가능한 매개변수들은 nn.Module 클래스의 parameters 매소드를 통해 확인할 수 있다.
"""
pass
Net(
  (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
  (relu): ReLU()
  (maxP1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=576, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)
params = list(net.parameters())
print(len(params))       # 10개에는 conv filter의 parameter, FC의 parameter, bias 등이 포함되어 있다. 자세한 건 나중에 더 자세히 알아보기
print(params[0].size())  # conv1's .weight
10
torch.Size([6, 1, 3, 3])
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)

"""
*** NOTE 중요  ***
굳이 1*1*32*32의 이미지를 넣는 이유 : 
torch.nn 은 미니-배치(mini-batch)만 지원합니다. torch.nn 패키지 전체는 하나의 샘플이 아닌, 샘플들의 미니-배치만을 입력으로 받습니다.
만약 하나의 샘플만 있다면, input.unsqueeze(0) 을 사용해서 가짜 차원을 추가합니다.
"""
pass
num_flat_feature를 하기 전의 x의 torch.Size([1, 16, 6, 6])
num_flat_feature를 하고 난 후의 x의 torch.Size([1, 576])
tensor([[ 0.0136,  0.0084,  0.1542, -0.0920, -0.0778,  0.0385, -0.0898,  0.0524,
         -0.0445,  0.0961]], grad_fn=<AddmmBackward>)
net.zero_grad()  # 1. Sets gradients of all model parameters to zero.
out.backward(torch.randn(1, 10)) # # 2. Backpropa. 1*10 백터를 정규분포에서 랜덤한 값을 가져와 생성한 tensor.
# print(input.grad) -> None 이라고 나온다. 아직은 뭔지 모르겠으니 좀 더 공부해보자.


Loss Function

https://pytorch.org/docs/stable/nn.html#loss-functions

여기에 존재하는 다양한 loss functions 중에서 하나를 사용해보자.

MSEloss는 가장 단순한 mean-squared error Loss이다. (평균제곱오차)

input = torch.randn(1, 1, 32, 32)
out = net(input)  # 예측값
target = torch.randn(10)   # 정답값
# target = target.unsqueeze(1) -> tensor.size([10,1])
target = target.view(1,-1)
print("out의 사이즈 : {}  ==(같아야 한다) target의 사이즈 {}".format(out.size(), target.size()))

criterion = nn.MSELoss() # 이 loss function을 기준으로 삼겠다.
loss = criterion(out, target)
print("{} type, loss : {}".format(type(loss),loss))
out의 사이즈 : torch.Size([1, 10])  ==(같아야 한다) target의 사이즈 torch.Size([1, 10])
<class 'torch.Tensor'> type, loss : 1.5556150674819946

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d

  -> view -> linear -> relu -> linear -> relu -> linear

  -> MSELoss

  -> loss
# 다음과 같은 방법으로, 최근에 한 마지막 연산들을 찾아갈 수 있다.
# 아래의 grad_fn 과 next_function은 torch document에도 없고 여기에만 있다... 
print(loss.grad_fn)  # MSELoss  // # 사용자가 마지막으로 이 변수를 만들 때 사용하는 Function을 참조한다. (기억해 놓는다.)
print(loss.grad_fn.next_functions[0][0])  # Linear
print(loss.grad_fn.next_functions[0][0].next_functions)  # ReLU
<MseLossBackward object at 0x000001915F1C0A88>
<AddmmBackward object at 0x000001915F1C0C88>
((<AccumulateGrad object at 0x000001915F1C0A88>, 0), (<ReluBackward0 object at 0x000001915F1C83C8>, 0), (<TBackward object at 0x000001915F1C8908>, 0))

오차(error)를 역전파하기 위해서는 loss.backward() 만 해주면 된다.

과거의 gradient를 없애는 작업이 필요한데( .zero_grad() ), 그렇지 않으면 gradient가 기존의 것과 누적되기 때문이다.
***

각 파라미터(가중치, 편향)에 대한 Loss 미분값을 알아내는 방밥

# 각 파라미터(가중치, 편향)에 대한 Loss 미분값을 알아내는 방밥

net.zero_grad()     # zeroes the gradient buffers of all parameters

print('conv1.bias.grad before backward')
print(net.conv1.bias.grad) # 이렇게 method를 사용하는 것도, 

loss.backward()

print('\nconv1.bias.grad after backward') # d_loss / d_bias_at-conv1
print(net.conv1.bias.grad)

print("\n bias 들의 실제 값 = ", net.conv1.bias)
conv1.bias.grad before backward
tensor([0., 0., 0., 0., 0., 0.])

conv1.bias.grad after backward
tensor([ 0.0211, -0.0160,  0.0067, -0.0190, -0.0056,  0.0125])

ias 들의 실제 값 =  Parameter containing:
tensor([-0.2747, -0.2196, -0.2772, -0.1524,  0.2187,  0.0836],
       requires_grad=True)

위에서 net.conv1.bias 는 그저 tensor이다. (https://pytorch.org/docs/stable/nn.html#conv2d 에서 확인가능 conv2d.weight도 사용 가능.)

그리고 grad는 torch.autograd.grad 를 이용한 것이다. (https://pytorch.org/docs/stable/autograd.html 에서 확인가능)

grad 함수 : xxx.grad에서 d_? / d_xxx 값을 tensor형태로 뱉어 준다.


가중치 갱신

확률적 경사하강법(SGD; Stochastic Gradient Descent)

# 아주 단순하게 가중치 갱신하는 방법
learning_rate = 0.01
# for를 돌아서, 내가 가진 모든 layers의 파라메터를 모두, 한번 갱신한다.
for i, f in enumerate( net.parameters() ):   
    print("{}번째 parameters 갱신 완료: {}".format(i+1, f.size()))
    f.data.sub_(f.grad.data * learning_rate)
     # 굳이 data method를 사용하는 이유는 모르겠다.
     # https://pytorch.org/docs/stable/tensors.html?highlight=sub_#torch.Tensor.sub_
    
# net.parameters를 이용해도 되고, 위에 처럼 net.conv1을 이용해도 좋다. print를 통해 알아보자.
print("\n", type(list(net.parameters())[0]), '\n', 
            type(list(net.parameters())[0].grad), '\n',
            type(list(net.parameters())[0].grad.data), '\n',
            list(net.parameters())[1].grad, '\n',
            list(net.parameters())[1].grad.data  )
1번째 parameters 갱신 완료: torch.Size([6, 1, 3, 3])
2번째 parameters 갱신 완료: torch.Size([6])
3번째 parameters 갱신 완료: torch.Size([16, 6, 3, 3])
4번째 parameters 갱신 완료: torch.Size([16])
5번째 parameters 갱신 완료: torch.Size([120, 576])
6번째 parameters 갱신 완료: torch.Size([120])
7번째 parameters 갱신 완료: torch.Size([84, 120])
8번째 parameters 갱신 완료: torch.Size([84])
9번째 parameters 갱신 완료: torch.Size([10, 84])
10번째 parameters 갱신 완료: torch.Size([10])

 <class 'torch.nn.parameter.Parameter'> 
 <class 'torch.Tensor'> 
 <class 'torch.Tensor'> 
 tensor([ 0.0211, -0.0160,  0.0067, -0.0190, -0.0056,  0.0125]) 
 tensor([ 0.0211, -0.0160,  0.0067, -0.0190, -0.0056,  0.0125])
# Optimizer를 사용해서 갱신하는 방법. https://pytorch.org/docs/stable/optim.html#algorithms -> 여기에 있는 가중치 갱신 알고리즘 사용할 것.
# 위의 과정이 optimizer.stop() 이라는 것 하나로 그대로 잘 동작한다.
import torch.optim as optim

# Optimizer를 생성합니다.
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 학습 과정(training loop)에서는 다음과 같습니다:
optimizer.zero_grad()   # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # Does the update. 다양한 종류의 optimizer 들은 모두 자신만의 step method가 구현되어 있다.



【Algorithm】 [백준] 11047 동전 0

문제 링크 [https://www.acmicpc.net/problem/11047]

첫 제출 -> 시간초과

coins = []
answer = 0

n, k = map(int, input().split())
for i in range(n):
    coins.append(int(input()))

for i in range(n-1, -1, -1):
    if k >= coins[i]:
        while k >= coins[i]:
            k -= coins[i]
            answer += 1
    else: pass

print(answer)

정답 제출 (시간 : 60ms)

coins = []
answer = 0

n, k = map(int, input().split())
for i in range(n):
    coins.append(int(input()))

for i in range(n-1, -1, -1):
    if k >= coins[i]:
        num, k = divmod(k, coins[i])
        answer += num

print(answer)

배울 만한 코드 (나의 풀이와 크게 다른 건 없다) *(시간 : 52ms)*

N, K = map(int, input().split())

Coins = []
for i in range(N) : Coins.append(int(input()))


ans = 0
while K > 0 :
    coin = Coins.pop()
    ans += K // coin
    K %= coin

print(ans)

【Algorithm】 [프머] 코딩테스트연습/ 스택, 큐/ 쇠막대기

문제 사이트 [https://programmers.co.kr/learn/courses/30/lessons/42585]

손코딩

img

나의 코드

def solution(arr):
    start_stack = []
    answer = 0
    
    for i in range(len(arr)):
        if arr[i] == '(':
            start_stack.append(i)
        else:
            diff = i - start_stack.pop()
            if diff == 1:
                answer += len(start_stack)
            else:
                answer += 1
                
    return answer

좋은 코드

def solution(arrangement):
    answer = 0
    sticks = 0
    rasor_to_zero = arrangement.replace('()','0')

    for i in rasor_to_zero:
        if i == '(':
            sticks += 1
        elif i =='0' :
            answer += sticks
        else :
            sticks -= 1
            answer += 1

    return answer
    
***
    
def solution(arrangement):
    answer = 0
    stack = 0
    laseron = False
    for p in arrangement:
        if p == '(':
            laseron = True
            stack += 1
        else:
            if laseron==True:
                answer += stack-1
                laseron=False
            else:
                answer += 1
            stack -= 1

    return answer
    
    
***
    
    
def solution(arrangement):
    onLaser = 0
    total = 0

    for i in range(len(arrangement) - 1):
        if arrangement[i:i+2] == '((':
            onLaser += 1
        elif arrangement[i:i+2] == '))':
            onLaser -= 1
            total += 1
        elif arrangement[i:i+2] == '()':
            total += onLaser

    return total

【Python】 'torch' has no member error in VSCode, windows10 해결하기

(Python) ‘torch’ has no member error in VSCode, windows10 해결하기

img

이와 같은 간단한 코드에서, torch에 빨간 줄이 처지며 torch has no member ones 라는 에러가 뜨곤 했다.

(.py파일에만 이와 같은 문제가 발생한다. ipynb파일에는 발생하지 않는다.)

이 문제를 해결하기 위해 이 사이트를 참조해 해결했다.

[http://www.programmersought.com/article/9184357862/]

원래 나의 설정 모습

img

변경 후 설정 모습

img

이 path는 terminal (windows powershell) 을 이용했다.

img

【Python】 파이썬 자료구조와 알고리즘 - 교재 서평

[파이썬 자료구조와 알고리즘] 교재 정리 내용 입니다.


1. Immutable 과 mutable

[https://webnautes.tistory.com/1181] 이 사이트에 설정이 매우 자세히 나와 있다. 설명을 요약하자면 다음과 같다.

a = 1 // 변수 a와 1은 별개의 존재입니다.

여기서 a는 변수이고 1은 객체이다. 변수는 단순히 객체를 가리킬 뿐이다.

mutable 객체 : list, set, dict

객체를 생성한 후, 객체의 값을 수정 가능, 변수는 값이 수정된 같은 객체를 가리키게됨.

=연산자를 사용해 copy한 것은 얕은 복사이다. (copy by reference)

immutable 객체 : int, float, complex, bool, string, tuple, frozen set

객체를 생성한 후, 객체의 값을 수정 불가능, 변수는 해당 값을 가진 다른 객체를 가리키게됨.

=연산자를 사용해 copy한 것은 깊은 복사이다. (copy by value)

[그림은 이 사이트 참조 : https://ledgku.tistory.com/54]

2. float숫자끼리의 비교

다음과 같은 문제 때문에 함부로 비교하거나 빼면 안된다.

>> 0.2 * 3 == 0.6

False

>> 1.2 - 0.2 == 1.0

True

>> 1.2 - 0.1 == 1.1

False

이 문제를 해결하기 위해, unittest모듈의 assertAlomostEqual과 같은 메소드를 사용하는 방법도 있다.

하지만 이렇게 문제해결하는 것은 근본적 문제 해결이 아니므로 ‘최대공약수 찾기’와 같은 방법을 사용해야 할 것이다.

더 좋은 방법으로는 decimal 모듈을 사용하는 것이다. [from decimal import Decimal]

3. 숫자 연산에 필요한 메소드

divmod(x,y) : return (x//y, x%y)

rount(x,n) : return 소수점 n자리에서 반올림한 수 return

4. assert

assert 조건문 : 조건문의 결과가 True가 아니면 Error를 발생시킨다.

[https://wikidocs.net/21050]

5. 가장 기본적인 알고리즘 코드

\1. 진법 변환 :

\2. 최대공약수 :

\3. 소수 :

\4. numpy 패키지 :

공부를 위해 해당 페이지 참고 : [http://aikorea.org/cs231n/python-numpy-tutorial/#numpy]


**<이 책에="" 대한="" 나의="" 생각="">**

이 책은 코딩테스트를 위해 좋은 책은 아니다. 코딩 테스트를 준비하기 위해서는 차라리 고득점 킷을 풀어보고, 문제를 풀어보면서 ‘이러한 방법으로 풀면 좋다(완전탐석 DFS HEAP 등)’ 라는 것을 인터넷에서 찾아가며 공부하는 것이 훨씬 좋다.

대신 이 책은 면접을 위해 좋은 책이다. 그리고 파이썬을 통한 프로그램 개발자가 알아두면 좋은 책이다. 알고리즘을 개발하고 프로그램을 개발하는 사람이라면 기본적으로 알아두면 좋은 책이다.

하지만 웹 웹 개발자, 딥러닝 모델 개발자가 알아두면 좋은 책인가? 그건 아니다. 이러한 개발자들은 다른 사람들이 만들어 놓은 모듈을 잘 이용하는 것이 더 중요하다.

따라서 지금 이 책을 공부하는 것은 때가 아니다. 우선 코딩테스트 준비를 완벽하게 하고 난 후에, 어느 정도 여유가 생기고, 공부해야겠다는 생각이 들면, 공부하는 것이 좋을 듯 하다.

이 책에는 몇가지 중요한 메소드(맴버함수)들이 소개되지만, 어차피 책을 통해 공부한다고 한들 무조건 까먹고 나중에 당연히 검색을 해야한다. 따라서 지금 책을 읽어 메소드들을 머리속에 암기하려는 행동보다는 코딩테스트를 준비하면서 유용했던 메소드들을 차근차근 공부하고 기억해나가는 것이 더 좋을 듯 하다.

따라서 지금 이 책은 한 동안 읽지 않으려고 한다. 대략 4개월 정도 후에 공부할 필요성이 느껴진다면 그 때가서 공부를 해야겠다. 지금은 맨 위에서 말했던 대로, [1. 고득점 킷 2. 코딩테스트 기출을 풀면서 몰랐던 이론과 구현법 공부.] 를 해야겠다.

【위성Segment】 학회 월간지 발행문 작성을 위한 사이트 모음

원본 글 위치 : https://junha1125.tistory.com/55?category=836123

1. Satellite

  1. Dstl kaggle 대회 - 논문 정리- https://arxiv.org/abs/1706.06169
  2. 대회들과 IEEE논문 많음 - https://github.com/dronedeploy/dd-ml-segmentation-benchmark
  3. 바로 위의 코드 중 그나마 쓸모 있을 것 같은 코드 - https://github.com/dronedeploy/dd-ml-segmentation-benchmark

2. Segmentation

  1. segmentaion을 쉽게 할 수 있는 코드 같음 -> 여기서 논문 필요하면 읽기 - https://github.com/CSAILVision/semantic-segmentation-pytorch
  2. Awsome 시리즈 : segmentaion 관련코드 모음 - https://github.com/mrgloom/awesome-semantic-segmentation
  3. 이거는 그냥 추가로… - https://arxiv.org/abs/1907.07156

3. Segmentation Good Code with pytorch

  1. https://github.com/qubvel/segmentation_models.pytorch
  2. https://github.com/meetshah1995/pytorch-semseg
  3. https://github.com/CSAILVision/semantic-segmentation-pytorch

【위성Segment】 [위성사진, SAR] 데이터 찾기 - Kaggle, Git

원본 글 위치 : https://junha1125.tistory.com/54?category=836123

ps. [kaggle API 이용해서 데이터 셋 다운로드]

1. kaggle에서 사용가능한 사이트들

\1. https://www.kaggle.com/c/enseeiht/data -> 데이터 너무 적음 \2. https://www.kaggle.com/c/dstl-satellite-imagery-feature-detection/overview -> 데이터는 많고, 약간 유명한 대회였던 것 같다.

2. kaggle에서 괜찮은 사이트 - But 사용불가

\3. https://www.kaggle.com/c/comp-540-spring-2019/overview \4. https://www.kaggle.com/c/epfml17-segmentation \5. https://www.kaggle.com/c/epfml-segmentation/rules 6.https://www.kaggle.com/c/mlhackfest-datos/data

3. Kaggle 들의 주제 모음 - 위성 사진을 이용해서 무엇을 하려했을까?

  • \1. satellite imagery Feature Detection
  • \2. Land-Cover-Classification ( segmentaion )
  • \3. Detect Load in satellite image ( Load 위치 추출, (아래와 같은) i_msk.png 파일 만들기. )
  • 4,5. Road extraction from satellite image ( Load 위치 추출, {road=1, background=0}을 mask 찾기 )
  • \6. Sementic segmentation for satellite image

-> Git에 load detect/ load extract/ setellite segmentaion 등을 찾아보면 좋을 듯 하다.

4. 그나마 이용할 만한, Dstl-satellite-imagery-feature-detection 분석해보기.

1. overview

위성 이미지의 확산으로 지구에 대한 이해가 획기적으로 개선되었다. 특히, 재난시 자원 동원에서 지구 온난화의 영향 모니터링에 이르기까지 모든 것을보다 잘 달성 할 수있었다.

하지만 이와 같은 발전을 가능케 라벨링 기능을 수작업으로 하거나 불완정한 자동화 시스템에 의존하는 것을 당연시 한다는 것은 문제다.

따라서 크고 복잡한 dataset들이 기하급수적으로 늘어나고 있는 현재, 이미지 분석가들의 수고를 덜어주기 위한 새로운 솔루션을 찾기 위해 대회를 열었다.

즉, feature labeling을 자동화 하는 방법에 대한 대회이다.

2. 데이터에 대한 설명

이 경쟁에서 Dstl은 3-band 및 16-band 형식의 1km x 1km 위성 이미지를 제공

이 대회의 목표는 이 지역에서 발견되는 물체의 class를 감지하고 분류하는 것

3 밴드 및 16 밴드 이미지

이 경쟁에는 두 가지 유형의 이미지 스펙트럼 컨텐츠가 제공됨

(1) 3-band 이미지 : 전통적인 RGB 자연 색상 이미지

(2) 16-band 이미지 : 더 넓은 파장 채널을 캡처하여 스펙트럼 정보가 포함된다. 이러한 다중 대역 이미지는 다중 스펙트럼 (400 – 1040nm) 및 단파 적외선 (SWIR) (1195-2365nm) 범위에서 가져온다. 모든 이미지는 GeoTiff 형식이며 GeoTiff 뷰어 (예 : QGIS ) 가 필요할 수 있다. 프로그래밍 방식으로 이미지를 보는 방법 에 대한 자습서 를 참조하면 된다.

직교 준비 표준 이미지 © 2016 DigitalGlobe, Inc.

모든 이미지 크레디트 : Satellite Imagery © DigitalGlobe, Inc.

이미지 세부 사항

  • 센서 : WorldView 3
  • Wavebands :
    • Panchromatic : 450-800 nm
    • 8 Multispectral : (빨강, 빨강 가장자리, 해안, 파랑, 녹색, 노랑, 근적외선 및 근적외선) 400 nm-1040 nm
    • 8 SWIR : 1195nm-2365nm
  • Nadir에서 센서 해상도 (GSD) :
    • Panchromatic : 0.31m
    • Multispectral : 1.24 m
    • SWIR : 7.5m로 전달
  • Dynamic Range
    • Panchromatic 및 Multispectral : 픽셀 당 11 비트
    • SWIR : 픽셀 당 14 비트

객체 유형

위성 이미지에는 도로, 건물, 차량, 농장, 나무, 수로 등과 같은 다양한 객체가 있음

Dstl은 10 가지 클래스로 분류

  1. 건물(Buildings) -대형 건물, 주거용, 비주거용, 연료 저장 시설, 강화 건물
  2. **기타 인공 구조물(Misc. Manmade structures) **
  3. 도로(Road)
  4. 트랙(Track) -불량 / 흙 / 장바구니, 보도 / 트레일
  5. 나무(Trees) -삼림 지대, 산 울타리, 나무 그룹, 독립형 나무
  6. 작물(Crops) -윤곽 쟁기 / 농지, 곡물 (밀) 작물, 줄 (감자, 순무) 작물
  7. 수로(Waterway)
  8. 서있는 물(Standing water)
  9. 차량 대형(Vehicle Large) -대형 차량 (예 : 트럭, 트럭, 버스), 물류 차량
  10. 차량 소형(Vehicle Small) -소형 차량 (자동차, 밴), 오토바이

모든 객체 클래스는 단순히 다각형 목록 인 Polygons 및 MultiPolygons 의 형태로 설명된다. 이러한 형태에 대해 GeoJsonWKT의 두 가지 형식을 제공하며, 이들은 지리 공간 형태를위한 오픈 소스 형식이다.

제출물은 WKT 형식이다.

지리 좌표(Geo Coordinates)

제공하는이 데이터 세트에서 x = [0,1] 및 y = [-1,0] 범위의 지리 좌표 세트를 만든다. 이 좌표는 위성 이미지가 촬영 된 위치를 가리기 위해 변환된다. 이미지는 지구상의 같은 지역에서 나왔다.

이러한 이미지를 활용하기 위해 각 이미지의 격자 좌표를 제공하여 이미지의 크기를 조정하고 이미지를 픽셀 단위로 정렬하는 방법을 알 수 있다. 스케일링을 수행하려면 각 이미지에 대해 Xmax 및 Ymin이 필요하다 ( grid_sizes.csv 제공 ) 이미지를 프로그래밍 방식으로 보는 방법에 대한 자습서 를 참조

파일 설명

  • train_wkt.csv- 모든 교육 레이블의 WKT 형식
  • ImageId-이미지의 ID
  • ClassType-객체 유형 (1-10)
  • MultipolygonWKT-레이블이 지정된 영역으로 WKT 형식으로 표현 된 다중 다각형 지오메트리
  • three_band.zip -3 밴드 위성 이미지의 완전한 데이터 세트. 세 개의 밴드는 파일 이름이 {ImageId} .tif 인 이미지에 있다. MD5 = 7cf7bf17ba3fa3198a401ef67f4ef9b4
  • sixteen_band.zip -16 밴드 위성 이미지의 완전한 데이터 세트. 16 개의 밴드는 파일 이름이 {ImageId} _ {A / M / P} .tif 인 이미지에 배포된다. MD5 = e2949f19a0d1102827fce35117c5f08a
  • grid_sizes.csv- 모든 이미지의 격자 크기
    • ImageId-이미지의 ID
    • Xmax-이미지의 최대 X 좌표
    • Ymin-이미지의 최소 Y 좌표
  • sample_submission.csv- 올바른 형식의 샘플 제출 파일
    • ImageId-이미지의 ID
    • ClassType-객체 유형 (1-10)
    • MultipolygonWKT-레이블이 지정된 영역으로 WKT 형식으로 표현 된 다중 다각형 지오메트리
  • train_geojson.zip- 모든 교육 레이블의 geojson 형식 (본질적으로 train_wkt.csv와 동일한 정보 임)

【Algorithm】 [프머] 코딩테스트연습/ 스택, 큐/ 프린트

문제 : [https://programmers.co.kr/learn/courses/30/lessons/42587]

손코딩

img

< 나의 코드 >

def solution(priorities, location):
    count = 1
    waits = {}
    for i in range(len(priorities)):
        waits[i] = priorities[i]

    values = list(waits.values())
    max_value = max(values)
    number_of_max = values.count(max_value)

    while(1):
        temp = next(iter(waits.items()))
        key_first, value_first =  temp[0], temp[1]
        if value_first == max_value:
            if key_first == location:
                answer = count
                break
            else:
                del waits[key_first]
                count += 1
                number_of_max -= 1
                if number_of_max == 0 :
                    while(1):
                        max_value -= 1
                        number_of_max = values.count(max_value)
                        if number_of_max > 0 : break

        else : 
            del waits[key_first]
            waits[key_first] = value_first
        answer = 0
    return answer

< 눈여겨 봐야할 다른 사람 코드 >

배운점 :

1. 주어진 변수를 잘 이용하자. 괜히 추가적인 변수를 만들면 복잡해 진다.

2. 다양한 방법을 다양하게 고민해보아라. 좀 더 쉬운 방법은 무조건 있다. 창의적으로 생각하라

4. key value도 매력적인 방법이지만, 튜플을 이용하는게 이해가 쉬울 수 있다.

## 1번째
def solution(p, l):
    ans = 0
    m = max(p)
    while True:
        v = p.pop(0)
        if m == v:
            ans += 1
            if l == 0:
                break
            else:
                l -= 1
            m = max(p)
        else:
            p.append(v)
            if l == 0:
                l = len(p)-1
            else:
                l -= 1
    return ans
    
    
    
    
## 2번째
def solution(priorities, location):
    queue =  [(i,p) for i,p in enumerate(priorities)]
    answer = 0
    while True:
        cur = queue.pop(0)
        if any(cur[1] < q[1] for q in queue):
            queue.append(cur)
        else:
            answer += 1
            if cur[0] == location:
                return answer

【Paper Code】 feature pyramid networks - Code review

(논문리뷰) feature pyramid networks - Code review

코드를 설명하는 그림

picture1

코드

'''
FPN in PyTorch.
See the paper "Feature Pyramid Networks for Object Detection" for more details.
'''
import torch
import torch.nn as nn
import torch.nn.functional as F

from torch.autograd import Variable


# 4. block == Bottlenect (for Bottom-up)
class Bottleneck(nn.Module):
    expansion = 4

    # layer1 : (64, 256), (64, 64) , (1 , 1) // layer2 : (256, 512), (128, 128) , (2, 1) // layer3 : (512, 1024), (256, 256) , (2, 1)
    def __init__(self, in_planes, planes, stride=1):
        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False) 
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)  
        self.bn3 = nn.BatchNorm2d(self.expansion*planes)

        # 5. shortcut 정의 하기 = Resnet 을 한다.
        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion*planes: # layer1,2,3,4의 for 2개에서 모두 shortcut이 이루어진다. 
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion*planes)
            )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x))) # x's channel-> layer1 : 64 // layer2 : 128 // layer3 : 256  // layer4 : 512
        out = F.relu(self.bn2(self.conv2(out)))
        out = self.bn3(self.conv3(out))  # out's channel-> layer1 : 256 // layer2 : 512 // layer3 : 1024  // layer4 : 2048
        out += self.shortcut(x)          # bottom-up에서 Resnet의 구조가 작동하는 부분. x와 out의 channel이 다른것은 어떻게 처리하는지는 위에 정의 되어 있다.
        out = F.relu(out)
        return out



class FPN(nn.Module):
    def __init__(self, block, num_blocks):
        super(FPN, self).__init__()
        self.in_planes = 64

        # 1. input channel 3 (RGB) // output channel 64 // kernel size 7*7 // stride가 1이면 같은 size output이지만, stride = 2여서 output == input//2 size
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) 
        self.bn1 = nn.BatchNorm2d(64) 


        # 2. Bottom-up layers. 4개의 layer를 통과하고 나오는 결과 : channel 2048, width와 high는 대략 /(4(#1)*8(layer2,3,4)) 가 된다.. 하나의 _make_layer에 의해서 2로 나눠지므로.
        self.layer1 = self._make_layer(block,  64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)

        # Top layer
        self.toplayer = nn.Conv2d(2048, 256, kernel_size=1, stride=1, padding=0)  # Reduce channels

        # Smooth layers
        self.smooth1 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.smooth2 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.smooth3 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)

        # Lateral layers
        self.latlayer1 = nn.Conv2d(1024, 256, kernel_size=1, stride=1, padding=0)
        self.latlayer2 = nn.Conv2d( 512, 256, kernel_size=1, stride=1, padding=0)
        self.latlayer3 = nn.Conv2d( 256, 256, kernel_size=1, stride=1, padding=0)

    # 3. call block (for Bottom-up)
    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1) # [1or2] + [1] = [1or2 , 1] 
        layers = []
        for stride in strides:
            # layer1 : (64, 256), (64, 64) , (1 , 1) // layer2 : (256, 512), (128, 128) , (2, 1) // layer3 : (512, 1024), (256, 256) , (2, 1) // in_plain, planes, sride
            layers.append(block(self.in_planes, planes, stride))  
            self.in_planes = planes * block.expansion            
        return nn.Sequential(*layers)

    def _upsample_add(self, x, y):
        _,_,H,W = y.size()
        return F.upsample(x, size=(H,W), mode='bilinear') + y
        # upsampling mode 설명 : https://pytorch.org/docs/0.3.1/_modules/torch/nn/modules/upsampling.html#Upsample

    def forward(self, x):
        # Bottom-up
        c1 = F.relu(self.bn1(self.conv1(x)))
        c1 = F.max_pool2d(c1, kernel_size=3, stride=2, padding=1) # 1. 위의 7*7 conv와 max_pool에 의해서 w/h가 /4 처리가 된다. 
        c2 = self.layer1(c1)  # c2 size = torch.Size([1, 256, 150, 225])
        c3 = self.layer2(c2)  # c3 size = torch.Size([1, 512, 75, 113])
        c4 = self.layer3(c3)  # c4 size = torch.Size([1, 1024, 38, 57])
        c5 = self.layer4(c4)  # c5 size = torch.Size([1, 2048, 19, 29])
        # Top-down
        p5 = self.toplayer(c5)
        p4 = self._upsample_add(p5, self.latlayer1(c4))
        p3 = self._upsample_add(p4, self.latlayer2(c3))
        p2 = self._upsample_add(p3, self.latlayer3(c2))
        # Smooth
        p4 = self.smooth1(p4)
        p3 = self.smooth2(p3)
        p2 = self.smooth3(p2)
        return p2, p3, p4, p5


def FPN101():
    # return FPN(Bottleneck, [2,4,23,3])
    return FPN(Bottleneck, [2,2,2,2])


def test():
    net = FPN101()
    fms = net(Variable( torch.randn(1,3,600,900) )) # from torch.autograd import Variable -> dL/dw 처럼 w에 관하여 미분한 값을 구할때 사용. 여기서 randn이 w이다.
    for fm in fms:
        print(fm.size())

test()

"""
input : torch.size([1, 3, 600, 900])

fms[0] = torch.Size([1, 256, 150, 225])   
fms[1] = torch.Size([1, 256, 75, 113])
fms[2] = torch.Size([1, 256, 38, 57])
fms[3] = torch.Size([1, 256, 19, 29])

"""

【Paper】 feature pyramid networks for object detection

이 논문을 읽어봐야겠다는 생각이 든 계기는 다음과 같다.

1. 친구가 발표했던 EfficentDet에 나오는 그림과 똑같은 그림이 나왔다. 이 논문과 feature pyramid networks에 대해 공부를 한다면 EfficentDet을 좀 더 자세히 이해할 수 있을거라 생각했다.

2. Detectron2를 공부해보던 중 다음과 같은 것을 보았다. C4와 DC5는 이미 알고 있는 ResNet을 사용하기 때문에 생소했던 feature pyramid networks를 공부할 필요성이 느껴졌다.

img

3. Object Detection 모델이 잘 정리되어있는 깃에 대표적은 backbone이 다음과 같이 적혀있었다. 3개가 다 뭔지 모르지만… 차근히 공부한다는 마음으로 feature pyramid networks 논문부터 읽어야 겠다는 생각이 들었다.

img


논문 내용 정리 PPT

img

img

img

img

img

img

img

img

img

img

img

Pagination


© All rights reserved By Junha Song.