branch 병합 시 충돌 해결

|

branch 병합 시 충돌 해결

  • merge 과정에서 파일 내용이 서로 다를 경우 충돌 발생 가능
  • git branch exp로 새로운 브랜치 생성
  • vim master.txt를 만들고, 내용을 a로 작성 후 git add master.txt, git commit -m "6" 으로 커밋
  • git checkout expvim exp.txt를 만들고, 내용은 a, git add exp.txt, git commit -m "7"으로 커밋
  • git checkout mastergit log --branches --graph --decorate를 확인해보면, master는 6번, exp는 7번을 가르키고 있는상태
  • 다음으로 git merge exp를 하면, 두개가 서로 각자 수정한부분이 있기에 merge 커밋이 생김
  • 다음으로 git log --branches --graph --decorate 를 확인해 보면 master와 exp가 병합된 새로운 master가 생성된 상태
  • ls -al 하면 exp 브랜치에서 만들어진 exp.txt가 생성 된 것을 확인 해 볼 수 있음
  • 만약 파일이 같으면 문제가 발생하게 됨
    • master 브랜치와 exp 브랜치에 같은 파일이 존재하는 경우 문제 발생
  • git checkout expvim common.txt, 내용 function a() 작성 후 git add common.txt, git commit -m "8"로 커밋
  • git checkout mastergit merge exp로 merge 실행
  • ls -al로 확인해보면 exp에만 존재하던 common.txt가 master에도 존재하게 되는것을 확인 할 수 있음
  • 다음으로 vim common.txt에서 function b() 라는 내용을 맨 위에 추가 (현재 master branch)
  • git commit -am "9"로 커밋
  • git checkout expvim common.txt에서 function c() 내용을 아래에 추가후 git commit -am "10"으로 커밋
  • git checkout master
    • 현재 common.txt파일에 대해 master와 exp가 서로 다른 부분을 수정하게 되어있는 상태가 됨
  • git merge exp하여 병합
    • vim common.txt로 확인해보면, master에서 작성한 내용과 exp에서 작성한 내용이 둘 다 병합 된 것을 볼 수 있음
    • 즉, 같은 파일임에도 서로 수정한 위치가 다르다면 자동으로 합쳐주게 됨
    • 같은 부분을 수정하게 되면 문제 발생
  • 현재 mater의 common.txt의 내용은 병합된 상태로 function a(), function b(), function c()가 모두 보임
  • git checkout exp 후 common.txt의 내용을 확인해보면 function a(), function c()만 보임
    • exp 브랜치의 내용을 master로만 병합한 상태이므로 master의 추가/변경된 내용이 exp 브랜치에 넘어오지 않은 상태
  • git merge master 하면 common.txt의 내용이 master와 같은 상태가 된 것을 확인 할 수 있음
  • git checkout matervim common.txt에서 function b()를 function b(master)로 수정
  • git commit -am "11" 으로 커밋
  • git checkout expvim common.txt에서 function b()를 function b(exp)로 수정
  • git commit -am "12" 으로 커밋
  • git checkout master로 mater 브랜치로 온 후 git merge exp를 수행
    • Auto-merging common.txt에 대해 CONFLICT 에러 발생한 것을 확인 할 수 있음
    • git status로 상태 확인해보면 unmerged path가 있다며 common.txt 파일이 양쪽 다 수정되어있다고 빨간색으로 뜸
    • 병합 실패한 상태
  • vim common.txt파일을 열음 (내용이 에러에 관해 추가되어있는 상태임)
    • 중간에 =========이 구분자 역할을 함.
    • 구분자를 중심으로 위쪽에 <<<<<<<<<HEAD라고 되어있는 부분이 현재(master 브랜치)의 수정사항
    • 구분자를 중심으로 아래에 >>>>>>>>>exp라고 되어있는는 부분이 다른(exp 브랜치)의 수정사항
    • 현재 git이 자동으로 병합하는것에 실패했기 때문에 merge를 실행한 사용자가 충돌을 해결하라고 위임한 상태임
      • 사용자가 직접 표시된 부분에 대한 코드 수정이 필요함
    • 구분자 및 HEAD, exp를 나타내는 관련 기호들 모두 삭제 후 충돌나는 부분에 대한 수정 실행
      • function b()의 내용을 function(master, exp)로 수정
  • git add common.txtgit status로 확인해보면 초록색으로 conflict 상태가 사라지고 modified 상태가 된 것을 확인 할 수 있음
    • git add conflicted_file은 충돌난 파일에 대한 작업이 끝났다는것을
  • git commit 하면 conflict가 낫던것을 수정했다는 도움말과 함께 merge가 됨
  • git log를 보면 성공적으로 커밋이 된 것을 볼 수 있음
  • vim common.txt로 내용을 보면 잘 처리가 된 것을 확인 할 수 있음

stash

|

stash

  • 감추다, 숨겨두다라는 뜻을 갖고 있는 단어
  • 브랜치에서 작업중 branch에서 작업하던 내용을 끝내지 않고 다른 branch로 checkout을 해서 다른일을 해야 하는 경우에 사용
  • stash 기능을 통해 작업이 끝나지 않은 작업을 commit하지 않고 작업했던 내용을 숨겨둘 수 있게 됨
    • 해당 branch의 최신 커밋(HEAD version)으로 작업중 파일이 이동하여 현재 branch의 상태를 깔끔하게 만들고 다른 branch로 checkout할 수 있게 됨
  • 새로운 디렉터리를 만들고 git init으로 초기화
  • vim f1.txt로 파일을 만들고 내용을 a로 저장, git add f1.txt, git commit -m 1로 버전을 만듦
  • 이 상태에서 새로운 브랜치 만들기 위해 git checkout -b exp로 exp 브랜치를 만듦
  • vim f1.txt에서 내용 b를 추가하고 저장.
  • 현재 상태에서 git checkout master를 하면 git status에서 exp브랜치에서 수정한 내용이 master에까지 영향을 주게 됨
  • git checkout expgit status를 확인하면 동일한 modified 붉은색 상태를 확인 가능
  • 이럴 때 exp 브랜치에서 stash를 사용하면 됨
  • git stash --help 로 필요한 옵션 넣어 사용하면 됨
  • git stash 치면 working directory의 내용이 exp에 저장되었고 index도 저장 됨.
    • 현재 WIP(Working in process)상태의 내용들이 저장되었다는 의미
  • git status를 해 보면 commit 할 것이 없다고 뜸
    • 즉, f1.txt는 수정한 내용을 갖고있지 않은 상태
  • git checkout master 로 master에서 작업을 자유롭게 할 수 있음
  • git checkout exp로 이동하여 git stash apply를 쳐 f1.txt가 살아나 modified 상태가 된 것을 확인
    • f1.txt의 내용도 실제로 살아난 것을 볼 수 있음
  • git stash list로 f1.txt에 대한 내용이 남아있음
  • git reset --hard HEAD로 하면 최신 커밋 상태로 working copy를 보내게 됨(다 지우게 됨)
  • git status를 하면 아무것도 커밋할것이 없다고 뜸
  • 하지만 stash의 내용을 잃어버린것이 아님
    • git stash list로 확인해보면 reset 전과 동일한 f1.txt에 대한 내용이 남아있는것을 확인 할 수 있음
  • git stash apply를 하면 다시 f1.txt에 대한 내용이 다시 복원 된 것을 확인 가능
  • 즉, stash list의 내용은 명시적으로 삭제하지 않으면 항상 살아있게 됨
  • git reset --hard로 초기화 후 vim f2.txt에서 내용을 a로 저장
  • git add f2.txt 후 이 상태에서 f2.txt의 내용을 stash하기 위해 git stash
  • git status로 확인해보면 수정된 사항이 없다고 뜸
  • git stash list로 확인해보면 2개의 stash가 저장 된 것을 확인 가능
    • 가장 최근에 처리한 stash는 가장 위에 존재하게 됨
      • git stash apply라는 명령어를 치면 가장 위에 있는 stash를 적용하게 됨
  • git stash apply를 친 후(f2.txt가 생성됨) git stash list를 확인해보면 아직도 f2.txt에 대한 내용이 존재하는것을 확인 가능
  • git stash drop을 통해 가장 최근의 stash를 삭제하면 됨
  • git stash list를 보면 하나만 남아있는것을 확인 가능
  • git stash apply; git stash drop;을 치면 적용 후 바로 삭제 가능
  • git status로 확인 해 보면 f1.txt와 f2.txt가 모두 살아났으며 git stash list를 하면 아무것도 남아있지 않은것을 확인 할 수 있음
  • git reset --hard로 초기화
  • vim f1.txt에 내용 b를 추가 후 git add f1.txt, git stash를 하면 해당 내용이 감춰지고 변경사항이 없는 상태가 됨
  • git stash apply; git stash drop과 동일한 작업을 하는 git stash pop 명령허를 수행
    • stash가 자동으로 apply가 되고 drop이 된 것을 확인 할 수 있음
  • git reset --hard로 초기화 후 vim f1.txt에 내용 b를 추가, vim f2.txt에 내용 a를 추가
  • git status로 확인 해 보면 f1.txt는 tracked 상태이므로 modified 상태, f2.txt는 untracked 상태인것을 확인 가능
  • git stash를 치면 f2.txt는 tracked 상태가 아니기때문에 stash 되지 않은 것을 알 수 있음
  • 즉, stash는 tracked 상태인 파일에만 적용 가능한 것을 알 수 있음

Neural network loss landscape 시각화하기

|

Neural network loss landscape 시각화하기(Visualizing the Loss Landscape of Neural Nets)

  • Visualizing the Loss Landscape of Neural Nets 논문에 대한 implementation code다.
  • Codes from https://github.com/tomgoldstein/loss-landscape
  • git clone https://github.com/tomgoldstein/loss-landscape.git 로 코드 다운로드

환경 설정

  • 하나 이상의 GPU
  • Pytorch 0.4
    • virtual env를 만들어 별도로 설치
    • pytorch 0.4, python 3.6, cuda 9.0
    • pip install https://download.pytorch.org/whl/cu90/torch-0.4.0-cp36-cp36m-linux_x86_64.whl
  • openmpi 3.1.2
    • https://www.open-mpi.org/software/ompi/v3.1/ 에서 3.1.2 탭의 openmpi-3.1.2.tar.gz 다운로드
    • mkdir ~/openmpi 폴더 만들고 해당 폴더로 openmpi-3.1.2.tar.gz파일 이동 후 tar -zxvf openmpi-3.1.2.tar.gz로 압축 풀기
    • cd openmpi-3.1.2/ 로 폴더 이동
    • ./configure --prefix=$HOME/openmpi로 configure 후 compile
    • make -j8 all로 make(5~10분 소요)
    • make install로 설치
    • vim ~/.bashrc로 bashrc에 path 설정
      • export PATH=$HOME/openmpi/bin:$PATH
      • export LD_LIBRARY_PATH=$HOME/openmpi/lib:$LD_LIBRARY_PATH
    • 저장 후 나가서 source ~/.bashrc
    • mpiexec --versionmpirun --version으로 설치 확인(버전 뜨면 설치 잘 된 상태)
  • mpi4py 2.0.0
    • pip install mpi4py==2.0.0
  • numpy 1.15.1
    • pip install numpy
  • h5py 2.7.0
    • pip install h5py==2.7.0
  • matplotlib 2.0.2
    • pip install matplotlib
  • scipy 0.19
    • pip install scipy
  • seaborn
    • pip install seaborn
  • scikit-learn
    • pip install scikit-learn

Pre-trained models

  • https://github.com/tomgoldstein/loss-landscape 에서 pretrained weight file들을 받아 해당 directory 내의 폴더에 저장
    • ex. ..../loss-landscape/cifar10/trained_nets/

Visualizing 1D loss curve

  • 실제 코드 돌릴때에는 openmpi 사용시 코드가 돌지 않아 그냥 돌렸다.
    • 하기 코드에서 mpirun -n 4를 빼고 돌리면 됨

Creating 1D linear interpolations

  • 1D linear interpolation 방법[1]은 같은 network loss function의 두 개의 minimizer사이의 방향을 따라 loss 값을 평가한다.
  • 이 방법은 다양한 batch size로 학습된 네트워크의 minizer의 평탄도를 비교하기 위해 적용된다[2].
  • 1D linear interpolation plot은 plot_surface.py를 사용하여 생성된다.

mpirun -n 4 python plot_surface.py --mpi --cuda --model vgg9 --x=-0.5:1.5:401 --dir_type states \
--model_file cifar10/trained_nets/vgg9_sgd_lr=0.1_bs=128_wd=0.0_save_epoch=1/model_300.t7 \
--model_file2 cifar10/trained_nets/vgg9_sgd_lr=0.1_bs=8192_wd=0.0_save_epoch=1/model_300.t7 --plot

  • --x=-0.5:1.5:401: Plot의 범위(range)와 해상도(resolution)를 설정한다. Plot의 x축 좌표는 -0.5부터 1.5까지(minimizer들이 각각 0과 1에 위치하므로)로 설정되며, loss값들은 x축을 따라 총 401개의 위치에서 측정된다.
  • --dir_type states: BN layer들의 통계(running_mean과 running_var) 뿐만 아니라 모든 parameter들의 dimension을 포함하는 방향을 의미한다. 하나의 화면에서 두 개의 솔루션을 한번에 plot할 때 running_mean과 running_var를 무시하게 될 경우 올바른 loss값을 생성 할 수 없다.

Producing plots along random normalized directions

  • 모델에서 생성된 parameter들과 동일한 차원의 random direction을 만들고 filter-normalize된다. 다음으로 loss값을 그 방향에 따라 sample할 수 있게된다.

mpirun -n 4 python plot_surface.py --mpi --cuda --model vgg9 --x=-1:1:51 \
--model_file cifar10/trained_nets/vgg9_sgd_lr=0.1_bs=128_wd=0.0_save_epoch=1/model_300.t7 \
--dir_type weights --xnorm filter --xignore biasbn --plot

  • --dir_type weights: Direction이 BN 레이어의 bias 및 parameter들을 포함하며, 학습 된 parameter와 동일한 크기를 가진다.
  • -- xnorm filter: Filter level에서의 random direction을 normalize한다. 여기서 filter는 single feature map을 생성하는 parameter들을 의미한다. Fully connected layer의 경우 filter는 단일 뉴런에 기여하는 weight를 포함한다.
  • --xignore biasbn: Bias 및 BN parameters에 해당하는 direction을 무시한다.(Random vector의 해당 항목을 0으로 채움)

Visualizing 2D loss contours

  • Loss contour을 plot하기 위해 두 개의 임의의 방향을 선택하고 1D plotting과 같은 방식으로 정규화(normalize)한다.

mpirun -n 4 python plot_surface.py --mpi --cuda --model resnet56 --x=-1:1:51 --y=-1:1:51 \
--model_file cifar10/trained_nets/resnet56_sgd_lr=0.1_bs=128_wd=0.0005/model_300.t7 \
--dir_type weights --xnorm filter --xignore biasbn --ynorm filter --yignore biasbn  --plot

  • 우선 surface가 생성되고 .h5파일에 저장되면, plot_2D.py파일을 이용해 contour plot을 cutomize하고 생성 할 수 있다.

python plot_2D.py --surf_file path_to_surf_file --surf_name train_loss

  • --surf_name: Surface의 타입을 명시한다. 기본은 train_loss이다.
  • --vmin, --vmax: Plot 될 값들의 범위를 설정한다.
  • --vlevel: Contour의 step을 설정한다.(얼마나 촘촘히/듬성듬성)

Visualizing 3D loss surface

  • ploy_2D.py는 matplotlib 라이브러리를 이용하여 기본적인 3D loss surfcace를 plot한다. 만약 조명을 이용한 세부 정보를 표시할 수 있도록 보다 세부적인 렌더링이 필요할 경우 ParaView를 이용하여 loss surface를 렌더링 할 수 있다.
    1. .h5파일을 .vtp파일로 변환한다.
      • python h52vtp.py --surf_file path_to_surf_file --surf_name train_loss --zmax 10 --log
      • 위 스크립트를 통해 log scale로 최댓값이 10인 loss surface 정보를 담고있는 VTK파일을 생성한다.
    1. ParaView를 이용하여 .vtp파일을 연다. ParaView에서 VTK reader를 이용하여 .vtp파일을 연다. Figure가 보이도록 하기 위해 Pipeline Browser의 눈 모양 아이콘을 누른다. Surface를 따라 drag를 할 수도 있으며, Properties창에서 색을 바꿀 수도 있다.
    1. 만약 surface가 매우 얇거나 바늘처럼 좁게 보일 경우 왼쪽의 control panel의 transforming 파라미터를 조절한다. 넓게 하고 싶은 축의 ‘scale’ 값에 1 이상의 값을 넣는다.
    1. 결과를 영상으로 저장하려면 File 메뉴의 Save screenshot을 누른다.

References

  • [1] Ian J Goodfellow, Oriol Vinyals, and Andrew M Saxe. Qualitatively characterizing neural network optimization problems. ICLR, 2015.
  • [2] Nitish Shirish Keskar, Dheevatsa Mudigere, Jorge Nocedal, Mikhail Smelyanskiy, and Ping Tak Peter Tang. On large-batch training for deep learning: Generalization gap and sharp minima. ICLR, 2017.

branch 병합

|

branch 병합

  • 작업을 분기를 해서 각자의 작업을 이어가다 병합 할 때 병합(merge)하는 방법에 대하여 학습
  • git log --branches --graph --decorate --oneline로 상태 확인
    • 현재 공통 브랜치 사항(커밋 메세지 1, 2)과 분기된 브랜치 사항(exp에 대하여 커밋 메세지 3, 4 / master에 대하여 커밋 메세지 5)에 대하여 확인 가능
  • exp의 내용을 master로 옮기기
    • exp branch에서 작업한 3, 4의 내용을 master로 옮기는 작업
    • master로 checkout 후 master에서 merge 하면 됨
  • git ckeckout mastergit merge exp 입력
    • 에디터가 열리며 맨 위에 Merge branch ‘exp’ 확인 가능
  • git log --branches --graph --decorate --oneline로 상태 확인
    • 현재 master branch로 exp가 합쳐진 것을 확인 할 수 있음
    • 커밋 메세지는 자동으로 작성 된 Merge branch exp를 확인 가능 (HEAD -> master 옆에서)
    • 해당 커밋은 두개의 부모 커밋을 가짐
      • master에서 작업한 5번 커밋과 exp에서 작업한 3, 4번 커밋을 모두 가지고 있는 상태가 됨
  • ls -al로 파일 리스트 확인해보면 모든 파일이 보이는것을 확인할 수 있음
  • exp에 대해서도 5번 커밋을 갖도록 하기 위해 git checkout exp 입력
    • git merge master 입력하여 병합
  • git log --branches --graph --decorate --oneline로 상태 확인
    • (HEAD -> exp, master)를 확인함으로써 같은 상태로 존재하는것을 확인 가능
    • 3, 4, 5를 공통으로 부모로 하는 커밋이 되었기때문에 완전히 같은 branch가 됨
  • git checkout mastergit branch -d exp를 하여 exp branch를 삭제
  • git log --branches --graph --decorate --oneline로 상태 확인
    • exp가 사라지고 master만 남아있게 된 것을 확인 할 수 있음

190225 백준 알고리즘 문제풀기

|

[9012] 괄호

문제

  • 괄호가 올바르게 배열 된 것을 VPS라 한다.
  • 주어지는 문자열에서 괄호가 올바르게 열리고 닫히게끔 되면 YES를, 아니면 NO를 출력한다.

  • 첫 문자열이 ‘)’이거나 전제 문자열 길이가 홀수개면 무조건 VPS를 만족하지 못하므로 ‘NO’를 출력한다.
  • 그렇지 않은경우, 문자열에 ‘)’가 포함되어 있다면 ‘)’를 제거하고 바로 ‘(‘를 제거한다.
  • 만약 문자열에 ‘)’가 포함되어 있다면 ‘)’가 남아있는 경우이므로 ‘NO’를 출력한다.
  • 만약 문자열이 모두 제거되어 길이가 0이 된 경우 ‘YES’를 출력한다.

정답

for _ in range(int(input())):
    ps = list(input())
    while len(ps) != 0:
        if ps[0] == ')' or len(ps)%2 != 0:
            print('NO')
            break
        else:
            if ')' in ps:
                ps.remove(')')
                ps.remove('(')
            else:
                print('NO')
                break
    if len(ps) == 0:
        print('YES')
  • 스택을 사용하여 문제를 풀 경우 아래와 같다.
    • 문자열에 ‘(‘가 있는경우 push를 한다.
    • 만약 그렇지 않은 경우(‘)’가 들어오는 경우), 스택이 비어있지 않다면 pop을 한다.
      • 만약 스택이 비어있다면 ‘NO’를 출력한다.
      • 이는 이전에 들어온 ‘(‘가 없는데 현재 ‘)’가 들어왔단 의미이므로 VPS가 절대 될 수 없다.
    • 해당 입력 문자열에 대해 위의 for loop을 돌고 난 후, 만약 스택이 비어있다면 성공적으로 모두 push/pop이 된 것이므로 ‘YES’를 출력한다.

정답

class Stack:
    def __init__(self):
        self.len = 0
        self.list = []

    def push(self, num):
        self.list.append(num)
        self.len += 1

    def pop(self):
        if self.size() == 0:
            return -1
        pop_result = self.list[self.len-1]
        del self.list[self.len-1]
        self.len -= 1
        return pop_result

    def size(self):
        return self.len

    def empty(self):
        return 1 if self.len == 0 else 0

    def top(self):
        return self.list[-1] if self.size() != 0 else -1

stack = Stack()
result = ''
for _ in range(int(input())):
    stack.list = []
    stack.len = 0
    result = ''
    ps = list(input())
    for j in range(len(ps)):
        if ps[j] == '(':
            stack.push(ps[j])
        else:
            if stack.empty() == 0:
                stack.pop()
            else:
                result = 'NO'
                break
    if stack.empty() and result != 'NO':
        print('YES')
    else:
        print('NO')