a = np.zeros([2,2]) # 2*2 0행렬 생성 b = np.ones((1,2)) # ()를 사용하던 []를 사용하던 상관 x c = np.full((2,2), 7) # 모든 값을 7로 채운 배열 d = np.eye(2) # 단위백터 e = np.random.random((2,2)) # random vector 생성
numpy배열 인덱싱하기. (슬라이싱)
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) a[1] == [5,6,7,8] a[1][3] == 7 a[:2, 1:3] == 0,1행과 1,2열 == [[2 ,3],[6,7]] b = a[:2, 1:3] # 단순복사 -> copy of reference
numpy배열 인덱싱하기. (불연속적인 원소 가져오기)
a = np.array([[1,2], [3, 4], [5, 6]]) b = a[[0, 1, 2], [0, 1, 0]] == [a[0, 0], a[1, 1], a[2, 0]] # 즉 행렬의 (0,0) (1,1) (2,0) 원소만 가져오기 즉 1*3행렬
응용하기. b = np.array([0, 2, 0, 1]) c = a[np.arange(4), b] # 즉 a행렬의 (0,0) (1,2) (2,0) (3 1)원소 즉 1*4행렬 # arange/linespace c += 10 print(a) # copy of reference이므로 위의 a행렬의 일부 원소도 10이 더해져 있을 것이다.
불리언 배열(mask 배열)
a = np.array([[1,2], [3, 4], [5, 6]]) bool_idx = (a > 2) print(a[bool_idx]) # 출력 “[3 4 5 6]” print(a[a > 2]) # 출력 “[3 4 5 6]”
자료형
배열 원소의 모든 자료형은 동일 x = np.array([1, 2]) print(x.dtype) # 자료형 알려주는 맴버함수 x = np.array([1, 2], dtype=np.int64) # 특정 자료형을 명시적으로 지정해주는 방법
배열 연산
x + y // x - y // x * y // x / y # 기본 사칙 연산자를 사용해서 해당 위치의 원소들과 계산 된다. np.sqrt(x) # 배열 전체에 sqrt처리 하기
우리는 위성으로부터 수집된 영상의 정밀한 객체 인식하는 문제를 해결하고자 하며, 특히 선박들의 위치와 종류를 파악하는 알고리즘을 연구하고 개발하고자 한다.
실제 해상에서 일어나고 있는 다양한 문제들을 해결하기 위해서는 인공위성 영상으로부터 객체 검출을 위한 알고리즘개발은 매우 중요하며 필수적이다. 특히 삼면이 바다인 한반도에서는 실시간 위성 영상으로부터 자동으로 다양한 종류와 크기의 해상 표적을 검출하는 것이 필수적인 기술이다.
따라서 최신 깊은 인공신경망과 딥러닝을 이용한다면 해상 표적탐지 핵심 기술 역량을 확보할 수 있을 것으로 예상한다. 실제 해당 기술을 활용하면, 불법적인 선박을 효율적으로 검출 및 추적뿐만 아니라 해상 조난이 발생했을 경우, 조난 선박의 위치를 더 정확하고 신속히 파악하여 대처하는 것이 가능하다.
인공위성 영상로부터 정밀 객체를 검출해내는 과제에서의 가장 큰 문제점은위성 사진은 다른 여타 사진들과는 다르게 해상도가 많이 떨어진다는 것이다. 그러므로 우리가 해결해야 하는 과제는 해상도를 높이는 작업과 객체를 정밀 검출하는 작업으로 총 2가지로 구분될 수 있다.
3. 한학기 전체 계획 및 목표
인공위성 영상으로부터 선박의 종류를 인식하고 그 선박의 위치를 검출하는 딥러닝 모델을 구축하기 위해 다음의 절차를 수행한다.
1) 데이터 전처리
딥러닝 모델을 만들기 위해, 최대한 많은 인공위성 사진을 수집한다.
단지 사진만 주어지면, 학습이 불가능하므로 주어진 사진에 선박이 어디에 있는지, 그리고 그 선박의 종류가 무엇인지에 관한 정보를 추가한다.
2) 신경망 구성
인공위성 사진은 화질이 낮으므로, 그대로 객체 검출에 사용하기에 부적절하다. 따라서 초해상화(Super-Resolution)를 하는 신경망을 따로 구성하여 객체 검출의 정확도를 높인다.
해상도가 높아진 사진을 기반으로 객체 검출(Object Detection)을 하는 신경망을 제작하고 학습시킨다.
3) 결과 확인
선박 위치 탐색과 객체 검출을 성공적으로 수행하는지 판단하여, 우리가 구축한 모델이 정확히 동작하는지 확인한다.
구축한 모델이 잘 동작하지 않는다면, 모델을 수정해가면서 최상의 성능으로 동작하는 모델을 구축해 나간다.
프로젝트의 전체 흐름도
4. 대회 결과
주어진 시간이 2주라는 시간 밖에 없었고, (늦게 대회를 신청해서..)
컴퓨팅 파워(코랩, DLPC 사용)가 부족해서 매우 좋은 성과는 내지 못하였습니다.
하지만 대회를 대회를 준비하면서 많은 것을 배우고 느꼈습니다.
60팀 참가 중 10위를 했지만, 다른 1위~7위 사람들에 비해서는 그래도 많이 낮은 성능을 보였습니다.
일정한 확률을 갖고 발생하는 사건(event) 또는 사상(事象)에 수치가 부여되는 함수. 일반적으로 대문자X로 나타낸다. 확률변수 X의 구체적인 값에 대해서는 보통 소문자를 사용해서, 예를 들어 X가 p의 확률로 x의 값을 가진다는 것은 P(X = x) = p 등의 확률함수로 표현할 수 있다. (즉 X는 확률변수 : 가능한 모든 경우 x : 그 가능한 모든 경우 중 특정한 경우 하나)
예시 : X : 주사위를 2번 던졌을때 나오는 모든 경우(36가지) -> x : 1다음에 5가 나오는 경우 -> 이때 P(X = x) = 1/36
머신러닝에서 확률백터와 확률 분포
위의 경우처럼 ‘가능한 모든 경우’가 확률 분포가 된다. 이때 특정한 x가 나올 확률을 찾는다면, 이와 같다.
P(X = x{5,5,10,6}) = 1/156132156
결합 확률과 독립 사건
어떤 2가지 상황이 독립 사건이면 다음과 같은 식이 성립한다.
P(x,y) = p(x)*p(y)
하지만 2가지 상황이 결합이면 다음과 같은 식이 성립한다.(결합 : 2가지 사건이 연결, 연관 되어 있는 경우 ex) 내가 국민대학교를 가서 돈까스를 먹을 확률 = 국민대학교를 갈 확률 * (국민대학교에서)돈까스를 먹을 확룰)
P(x,y) = p(x)*p(y|x)
P(x,y) = p(y)*p(x|x)
이것을 묶은게 오른쪽 베이즈 정리이다.
우도(가능도/likelyhood)
오른쪽 경우에 대해, 다음의 문제를 생각해보자.
“하얀 공이 나왔다는 사실만 알고 어느 병에서 나왔는지 모르는데, 어느 병 인지 추정하라.”
이는 위에서 배운 베이즈 정리를 이용하면 된다.
다른 관점으로 다시 생각해보자. 베이즈 정리는 [사후확률][우도][사전확률]을 이용한 수식이다.
사후 확률 : 사건 발생 후의 확률
사전 확률 : 사건 x와 무관하게 미리 알 수 있는 확률
우도 : 사후확률을 구하기 위해 사용! 여기서는 이렇게 사용되었지만, 사실 우도는 이와 같이 쓰인다.
- 우도 추정 = 역 확률 문제
- p(알고있음x | 추정해야 할 사건y) = L(y,x) 라고 표현된다.
그렇다면 우리가 이 우도를 왜 배우고 있는 것일까? 기계학습의 적용에서 공부해보자.
우도 지도 학습에 적용
지도 학습은 x와 y를 다음과 같이 적용할 수 있다. y = 클래스, 라벨, 타겟 x = 특징 백터
예를 들어 오른쪽 그림과 같다.
이 예제에서 p(y|x)는 이와 같이 해석할 수 있다. feature가 …일 때 그것이 ,,,꽃일 확률
이 확률들을 이산확률분포라고 가정하고 일일이 구하는 것은 불가능하다. (특징이 …일때 이 것은 ,,, 꽃일 확률이 몇%이다. 라고 전부 정의하는 것은 어렵다.) 따라서 우리는 베이즈 정리를 이용해서 p(y|x)값을 구할 수 있다.
p(x|y)를 구하기 쉬운가? x는 높은 차원이 될수 있지만, y는 일반적으로 고정된 샘이다, (유한한 클래스 갯수) 따라서 각각의 클래스들은 독립적으로 확률분포를 추정할 수 있고, 그렇게 독립된 분포를 보고 확률을 추정하면 되므로, 훨씬 쉽다고 할 수 있다.
최대 우도법
의 병 문제를 다시 생각해보자. p((1)|하양)은 우리가 전체적은 그림을 알고 있다고 가정하고 베이즈 정리를 사용해서 계산을 했다. 그렇다면 다음의 경우에는 어떻게 계산할까?
다시 한번 생각해보면, 데이터 집합 X는 구할 수 있다. q3는 모른다. q3의 추정값을 찾기 위해서 X를 이용하는 방법이 최대우도법이다.
이때 우리는 X ={흰공, 파랑공, 흰공, 파란공} 과 같은 위의 표현을 이와 같이 쓸 수 있다.
X= {x1, x2, x3,x4} 이것은 위의 식의 P(X|theta)는 다음과 같이 쓸 수 있다
이것은 확률의 곱이므로 너무 작은 값이 될 수 있다. 따라서 다음과 같이 최대 로그 우도 추정을 사용한다.
기계학습에서의 최대 우도 공식**
W = argmax P(X|W)
임의의 데이터 분포(date set)에 대해서, 그 분포처럼 나오게 하는, 최대로 적절한 신경망의 가중치 W값
블로그 내용정리
우도와 가능도
모수 θ에 의해 만들어진 확률변수 X. 모수는 위에서 q3와 같이, 분포 곡선을 생성하기 위해 확률 분포 함수(PDF)의 입력 값으로 사용되는 모집단 전체를 설명하는 측도입니다.
L(θ|x)는 표본 x에 대해서 모수 θ의 가능도이다. 풀어 쓰자면, 특정 모수를 가지는 모집단에 대해서, 표본 x가 나왔을 때, 그 표본이 나올수 있게 하는 모수 θ의 가능도(가능성-이 모수를 가지는것이 몇%로 정확한 것인가?)를 L(θ
x)라고 한다.
참고로 위의 | 는 조건부 확률의 |가 아니다. 그냥 모수 θ를 가지는 모집단에서 xn이 나올 확률이다. (이해가 안된다면 맨 위에서 부터 차근차근 아래로 내려오자.)
(여기서 부터 모수 θ == 모수 μ)
최대 가능도 방법
표본 x가 있을 때, 가장 가능한(적절한) 모수 θ의 확률(분포)를 구하는 것이다.
이항 분포 : 속된 n번의 독립적 시행에서 각 시행이 확률 p를 가질 때의 이산 확률 분포이다
베르누이 분포 : 매 시행마다 오직 두 가지의 가능한 결과만 일어난다고 할 때, 이러한 실험을 1회 시행하여 일어난 두 가지 결과에 의해 그 값이 각각 0과 1로 결정되는 확률변수 X
여기서 μ는 위에서 봤던 모수 θ를의미한다. 그리고 x는 0 또는 1이다.(베르누이 분표에서의 0과 1사용)
직접 0과 1을 대입해보면 P(x=0) = 1-μ 그리고P(x=1) = μ가 됨을 확인할 수 있다.
p(앞2뒷2|μ)=μ^2(1−μ)^2 = P(x=0) * P(x=0)* P(x=1) *P(x=1)라고 말할 수 있다. 그리고 이것을 그림으로 그리면 다음과 같이 표현 된다.
이것으로써 우리는 P가 최대(0.063)가 되는 μ가 0.5 라는 것을 알 수 있다.
이것을 일반화해서 적으면 다음과 같다.
즉 다시 말해서, 관측된 Data가 나올 확률을 Likelihood라고 하고, 이 방법을 Maximum Likelihood Estimation, 줄여서 MLE라고 한다. 또 위의 파란색 부분을 일반화 하면
자. 위에서 내가 μ에 대해서 그래프를 그렸다. P가 최대가 되는 μ를 찾기 위해 항상 그래프를 그려야할까??
아니다. μ에 대해서 미분을 하면 되지 않는가?? 그리고 미분한 그 함수가 0이 되는 지점이 최대값이나 최솟값이 되는 지점이겠지…
그냥 미분을 하면 너무 힘드므로, 바로 위의 식에 양변에 log를 씌우고 미분을 해서, 미분한 함수가 0이 되는 μ값을 찾아보자.
즉 우리가 원하는 μ의 MLE
이때 N은 총 수행 횟수이다. (앞앞앞뒤뒤 -> N = 5)
즉 xn(동전의 앞면) = 1 에 대해서 μ는 (1/N) *(N/2) = 1/2 가 될 것이다. (시그마 xn ~= N/2 이기 때문에.)
원본 글 위치 : https://junha1125.tistory.com/45?category=836123
@#### **<전체 구조="">**전체>
@ 오리지널 깃 사이트 : [https://github.com/facebookresearch/detectron2]
@ install : [https://github.com/facebookresearch/detectron2/blob/master/INSTALL.md]
@ doecker : [https://github.com/facebookresearch/detectron2/blob/master/docker/Dockerfile]
\- dockerfile 구동 방법 : [http://pyrasis.com/Docker/Docker-HOWTO#dockerfile]
\- 그냥 dockerfile이 있는 위치에서 다음의 명령어 실행
\- docker로 하면, 어떻게 될지는 궁금하나,
현재는 우리의 데이터셋을 이용하기 위함까지 해야하므로, 로컬에 우선 설치하자.
$ docker build --tag detectron2:1.0
$ docker run --name facebookDetectron -d -p 80:80 -v [host path]:[container path] detectron2:1.0
@ 차근 설치법(코랩) : [[drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5#scrollTo=QHnVupBBn9eR](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5#scrollTo=QHnVupBBn9eR)]
@ source를 다운받아서 직접 build하는 방법.
@ pre-built 되어 있는 source를 다운받는 방법.
\- 쿠다 버전 관리 주의
\- 이것은 가장 최신 버전의 파일이므로, 깃에 있는 파일과 양립하지 않을 수 있다.
@ Quick Start : [https://github.com/facebookresearch/detectron2/blob/master/GETTING_STARTED.md]
\- 위의 코랩이, 이 내용까지 포함하고 있다.
@ Document : [https://detectron2.readthedocs.io/index.html]
ps.
intallation를 보다 보면 드는 의문 : ‘pip install’ 과 ‘python setup.py intsall’ 는 표면적으로 같은 역활을 한다.[https://stackoverflow.com/questions/15724093/difference-between-python-setup-py-install-and-pip-install] 여기서는 pythion pip install을 사용했다. pip install과 동일한 것 같다.
남의 코드 보다가 모르는거 있으면 제발 print 해보아라. 디버깅을 해야 그게 뭔지 알지!! 눈으로만 보고 document로만 읽고 하면 기억에 남는것도 별로 없고, 확실히 알지도 못한다.
<코랩 - Run a pre-trained detectron2 model>
\1. torch==1.4.0+cu100 // torchvision==0.5.0+cu100 로 파이토치 버전을 바꿔준다.
\1. 우선 detectron2에서 우리의 데이터를 얻는 방법을 알려줘야한다. 우리의 json파일을 읽고, 그 json파일을 해석하는 방법을 다음과 같이 함수로 직접 정의하면 된다.
\2. 그리고 DatasetCatalog와 MetadataCatalog 함수를 이용해서, 위에서 정의한 함수가 있다는 것을 알려준다. str으로 내가 원하는 데이터 셋을 찾을 수 있다. 다양한 데이터 셋을 한방에 관리하게 위해 DatasetCatalog와 같은 함수를 사용한다고 한다.
\3. 그렇게 DatasetCatalog과 MetadataCatalog로 정의된 데이터 셋을 살펴보면 다음과 같다.
여기서 주의할 점은, os.makedirs(cfg.OUTPUT_DIR) 에 의해서 현재 나의 위치(pwd)에 output이라는 폴더가 만들어졌고, 그 안에 파일들이 저장되고 있음을 확인할 수 있다.
**
\1. 학습이 완료되면 다음과 같이 pth라는 파일이 생긴다. 이것은 tensorflow에서 cpkt와 같은 역활을 한다. 즉 model의 parameter를 저장해놓는 역활을 한다.
\2. 아래와 같이 predictor를 명시만 해준다. (그 predictor는 지금까지 내가 학습시킨 파라메터인 model_final을 사용한다)
\3. 아래와 같은 방법으로 이미지를 가져오고, 가져온 이미지를 predictor를 이용해 predict을 진행한다. 그 후 outputs에 predict의 정보가 저장되고, 그 정보는 아래와 같은 get_fields()[output정보를 dict으로 바꿔줌]과 같은 메소드를 이용해서 해석할 수 있다.
pred_masks에 mask정보가 있다. true, false값을 사용해 이미지의 한 픽셀픽셀이 객체의 부분인지를 말해준다.(다각형 꼭지점 좌표를 이용한 mask 데이터 아님.)
알파 프로젝트를 하면서, 완성된 신경망을 통해 나온 결과를 CSV파일이 아닌 직접 눈으로 확인할 필요가 많았다. 예를 들어서 코드를 돌려서 나온 결과는 다음과 같다.
이 출력이 정말 좋은 값들로 출력이 된 것인지 확인할 필요가 있었다. 예를 들어 이 데이터를 이용해서 사진에 박스를 처줌으로써 우리의 신경망이 배를 잘 찾았는지 확인하는 것처럼 말이다. <원본>  <박스를 친="" 사진="">  ### **b.** **완성한 코드** ```python from matplotlib import pyplot as plt import numpy as np import argparse from PIL import Image from matplotlib import pyplot as plt import cv2 import pandas as pd from PIL import ImageFont from PIL import ImageDraw def save_image_with_box(box_info, imageName , start_index, last_index , image_path, save_path): """ box_info : panda로 받아드린 csv파일 image_Name : image_Num.png 파일을 봐야한다. start, last : box_info['file_name'][start ~ last]가 image_Num.png에 대한 정보를 담고 있다. img_path : 이미지가 있는 directory name save_path : 이미지가 저장될 directory name """ try: im = Image.open(image_path + imageName) except : print("no such file in directory : ", imageName) return plt.figure(figsize = (30,30)) plt.imshow(im) color_set = ['r','b','y','g'] for i in range(start_index, last_index+1): point1 = (box_info["point1_x"][i],box_info["point1_y"][i]) point2 = (box_info["point2_x"][i],box_info["point2_y"][i]) point3 = (box_info["point3_x"][i],box_info["point3_y"][i]) point4 = (box_info["point4_x"][i],box_info["point4_y"][i]) plt.plot([point1[0],point2[0]],[point1[1],point2[1]], linewidth=3, color = col-or_set[box_info['class_id'][i] - 1]) plt.plot([point2[0],point3[0]],[point2[1],point3[1]], linewidth=3, color = col-or_set[box_info['class_id'][i] - 1]) plt.plot([point3[0],point4[0]],[point3[1],point4[1]], linewidth=3, color = col-or_set[box_info['class_id'][i] - 1]) plt.plot([point4[0],point1[0]],[point4[1],point1[1]], linewidth=3, color = col-or_set[box_info['class_id'][i] - 1]) plt.savefig(save_path + imageName) plt.close() print("saved : ", imageName) if __name__ == "__main__": # 기본 설정 # image_path = './Alpha-project/images/' # save_path = './Alpha-project/images_with_boxs/' # csv_path = './Alpha-project/baseline.csv' parser = argparse.ArgumentParser(description='draw_rbox_in_images') parser.add_argument('--image_path', type=str, default='images') parser.add_argument('--save_path', type=str, default='images_with_boxs') parser.add_argument('--csv_path', type=str, default='baseline.csv') args = parser.parse_args() image_path = args.image_path + '/' # imagepath == images/ save_path = args.save_path + '/' # save_path == images_with_boxs/ csv_path = args.csv_path #csv file load box_info = pd.read_csv(csv_path) #run start_index = 0 for i in range(len(box_info)+1): try: # i+1번째 파일이 다른 이미지라면, i번째 파일에 대해서 박스가 처진 그림을 그린다. if box_info['file_name'][i][0:-4] != box_info['file_name'][i+1][0:-4]: save_image_with_box(box_info, box_info['file_name'][i] , start_index, i, image_path ,save_path ) start_index = i+1 except: # box_info['file_name'][i+1]가 존재하지 않으면 , 즉 999.png 이후를 바라본다면 save_image_with_box(box_info,box_info['file_name'][i],start_index,i, image_path ,save_path ) ``` ### **c.** **코드 사용하는 방법** **<****실행 방법>** ```python python drawRbox_in_Images.py --image_path=./images --save_path=./images_with_boxs --csv_path=./baseline.csv ``` <****위 실행을 위한 data structure>** drawRbox_in_Images.py images \- 0.png \- 1.png \- 2.png images_with_box \- (empty) baseline.csv **<****세부 사항>** \- images에 있는 사진만 박스 친다. \- test사진 1240장 모두가 꼭 있어야 하는 것은 아니다. ### **d.** **이를 통해 배운 내용: 원하는 코드 찾는 방법** 여러가지 코드를 작성하다 보면, 이런 생각이 들 때가 있다. “내가 하고 있는 작업을 누군가 하지 않았을까?” 이럴 때 다른 사람들의 코드를 찾아보는 방법이 아래의 3가지가 있다. 위의 코드를 만들 때도 이 방법을 사용해서 코드를 찾아보곤 했다. **코드 검색을 위해, 다음을 이용하자.** \1. 케글 - 이미 개발된 코드가 있을 수 있고, discussion에 data augmentation에 대한 정보도 많다 \2. 깃 - 패키지 안에, 검색을 함으로써 이미 만들어진 코드를 검색할 수 있다. \3. 구글 - 어떤 코드, 함수를 찾으려면 위의 방법을 이용하는게 낫다. [~하는 코드]는 구글에서 찾기 힘들다 박스를>원본>