호기심 많은 분석가
[BoostCamp] Week1_Day2. 평화롭지만 치열했던. 본문
부스트캠프
개발자의 지속 가능한 성장을 위한 학습 커뮤니티
boostcamp.connect.or.kr
개요
두 번째 날은 별 다른 이벤트가 있진 않았다. 개인 학습하다가 내일 하는 피어세션이 피어씁니다라는 피어들의 자기소개 시간을 위해 PPT를 제작한 정도? 그리고 과제 하나가 굉장히 어렵게 나와서 2시간 동안 힘들었던 날이었다. 되게 신기했던 건 1학년 때 알던 같은 과 누나가 연락 와서 자기도 이 프로그램에 참여 중이라는 것이다.! 세상 좁지.. 반가움을 안아두고 오늘의 학습에 대해서도 소개해보겠습니다. :)
개인 학습
(AI Math 3,4강)경사하강법
- 미분이 뭔가요?
- 미분은 변수의 움직임에 따른 함숫값의 변화를 측정하기 위한 도구로 최적화에서 제일 많이 사용하는 기법입니다.
-
import sympy as sym from sympy.abc import x sym.diff(sym.poly(x**2+2*x+3), x) # Poly(2*x+2, x, domain='ZZ')
미분은 함수 f의 주어진 점 (x, f(x))에서의 접선의 기울기를 구한다
- 미분은 연속이어야 한다.
- 한 점에서 접선의 기울기를 알면 어느 방향으로 점을 움직여야 함숫값이 증가하는지 / 감소하는지 알 수 있다
- 증가시키고 싶다면 미분 값을 더하고, 감소시키고 싶으면 미분값을 빼준다.
- 다차원에서도 동일하기 때문에 유용
- 미분 값을 더하면 경사상승법(gradient ascent)라 하며 함수의 극대값의 위치를 구할 때 사용한다
- 목적함수를 최대화할 때 사용
- 마찬가지로 미분값을 빼면 경사하강법(gradient descent)라 하며 함수의 극소값의 위치를 구할 때 사용한다
- 목적함수를 최소화할 때 사용
- 경사상승/경사하강 방법은 극값에 도달하면 움직임을 멈춘다
- 극값에선 미분 값이 0이므로 더 이상 업데이트가 이루어지지 않음
# 경사하강법 : 알고리즘 # gradient : 미분을 계산하는 함수 # init : 시작점, lr : 학습률, eps : 알고리즘 종료조건 var = init grad = gradient(var) while (abs(grad) > eps):# 컴퓨터로 계산할 때 미분이 정확히 0이 되는 것은 불가능 # 그래서 eps보다 작을 때 종료 var = var - lr*grad # lr은 학습률로서 미분을 통해 업데이트하는 속도를 조정 grad = gradient(var)
변수가 벡터이면요?
- 벡터가 입력인 다변수 함수의 경우 편미분을 사용한다.
- 각 변수 별로 편미분을 계산한 그레디언트(gradient) 벡터를 이용하여 경사하강/경사상승법에 사용할 수 있다.
- $\nabla f = (\partial_{x_1}f, \partial_{x_2}f, \cdots, \partial_{x_d}f)$
- $-\nabla f$벡터를 그리면 항상 그 함수의 최솟점으로 향하는 벡터가 만들어진다.
# 경사하강법 : 알고리즘
# gradient : 미분을 계산하는 함수
# init : 시작점, lr : 학습률, eps : 알고리즘 종료조건
# 벡터는 절대값을 취할 수 없으므로 대신 노름(norm)을 계산하여 종료조건을 설정
var = init
grad = gradient(var)
while (norm(grad) > eps):# 컴퓨터로 계산할 때 미분이 정확히 0이 되는 것은 불가능
# 그래서 eps보다 작을 때 종료
var = var - lr*grad # lr은 학습률로서 미분을 통해 업데이트하는 속도를 조정
grad = gradient(var)
요약
우리는 데이터를 예측할 때 오차, 즉 손실 함수(loss function)이 최소화되기를 바란다. 그때의 coefficient를 구할 때 가장 최소가 되는 지점을 경사 하강법을 이용하여 구한다. 그때 필요한 것이 미분, 대체로 다변수인 경우가 많으므로 그레이언트가 필수가 된다. 경사하강법이란 시작점에서 미분 값을 계속 빼는 것을 의미하는데, 이렇게 하면 최솟값을 향해 간다.
근데 문제는 무엇이냐, 고차원의 함수는 여러 개의 극값을 가진다. 그래서 최솟값이 아닌 극값에 머무를 수가 있단 말이지, 이걸 해결하는 걸 다음 과정에서 배워보자.
저번 시간에 선형모델의 무어-펜로즈 방법을 이용하여 선형회귀 식을 구하는 것도 좋은 방법이지만, 우리는 앞으로 선형이 아닌 모델도 다룰 것이기에 좀 더 일반적인 경사하강법을 집중적으로 배우자.
- 선형회귀의 목적식은 $\lVert y-X\beta \rVert_2$이고 이를 최소화하는 $\beta$를 찾아야 하므로 다음과 같은 그레디언트 벡터를 구해야한다.
- $\nabla_{\beta}\lVert y-X\beta \rVert_2 = (\partial_\beta{_1}\lVert y-X\beta \rVert_2,\cdots,\partial_\beta{_d}\lVert y-X\beta \rVert_2$
- 주의 : 일반적인 수학의 L2-norm의 풀이 방식과는 살짝 다르다.
- 주의 : 일반적인 수학의 L2-norm의 풀이 방식과는 살짝 다르다.
- 이것은 결국 $-\frac{X^T_{.K}(y-X\beta)}{n\lVert y-X\beta\rVert_2}$와 같아진다.
- 이 식은 $f(x)^{\frac{1}{2}}$를 미분한다고 생각하면 조금 더 이해가 편하다
- 저는 3X3 행렬로 직접 계산해봤는데 여러분도 직접 계산해보시길 추천드립니다.
- $X^T_{.K}$란 행렬 X의 k번째 열(column)벡터를 전치시킨 것을 의미한다
- 결국은 $X\beta$를 계수 $\beta$에 대해 미분한 결과의 Transpose와 같다.
- 그래서 전체 식은 $-\frac{X^T(y-X\beta)}{n\lVert y-X\beta\rVert_2}$와 같다.
- $\nabla_{\beta}\lVert y-X\beta \rVert_2 = (\partial_\beta{_1}\lVert y-X\beta \rVert_2,\cdots,\partial_\beta{_d}\lVert y-X\beta \rVert_2$
요약 : 우리는 선형회귀 목적식이 최소값이 되길 바란다. 그 값을 만들어주는 $\beta$를 찾아야하는데, 어떻게 찾는가? 미분값을 빼면 함수 값도 감소하므로, 계속하여 미분값을 빼주는 경사하강법을 시행, 미분값을 구하기 위해 그레디언트 벡터를 구해준다. 그걸 계속 반복하면, 최소값이 구해질 것.
- 이제 목적식을 최소화하는 $\beta$를 구하는 경사하강법 알고리즘은 다음과 같다. 미분값을 계속 빼주면서 최소값에 가까워지도록, $\lambda$ 라는 학습률로 작업 속도를 조절할 수 있다.
- 우리는 기본적으로 L2-norm을 계산해주는데, L2-norm의 최솟값을 찾나 L2-norm의 제곱값의 최솟값을 찾나 작업 방향은 같기 때문에 계산의 편의성을 위해 L2-norm의 제곱을 계산해주어도 된다.
- $\beta^{(t+1)}\leftarrow\beta^{(t)}-\lambda\nabla_\beta\lVert y-X\beta^{(t)}\rVert$
# 경사하강법 기반 선형회귀 알고리즘
# norm : L2-norm을 계산하는 함수
# lr : 학습률, T : 학습횟수
for t in range(T) :
error = y - X@beta
grad = -transpose(X)@error
beta = beta - lr * grad
# 종료조건을 일정 학습횟수로 변경한 점만 빼고 앞에서 배운
# 경사하강법 알고리즘과 동일하다. 요즘은 다들 학습횟수로 알고리즘을 설정함
- 학습률과 학습횟수를 적절하게 설정하여야만 원하는 계수 값을 찾을 수 있다.
- 학습률이 너무 작게 잡으면 수렴이 늦고, 크게 잡으면 불안정함
- 학습횟수가 너무 작으면 수렴이 안될 수 있음
경사하강법은 만능일까?
- 이론적으로 경사하강법은 미분가능하고 볼록(convex)한 함수에 대해 적절한 학습률과 학습횟수를 선택했을 때 수렴이 보장되어 있다.
- 특히 선형회귀의 경우 목적식이 회귀계수 $\beta$에 대해 볼록함수이기 때문에 알고리즘을 충분히 돌리면 수렴이 보장된다.
- 하지만 비선형의 경우 목적식이 볼록하지 않을 수 있으므로 수렴이 항상 보장되지는 않는다. 특히 딥러닝의 경우 목적식이 대부분 볼록함수가 아님
- 특히 딥러닝을 사용하는 경우 목적식은 대부분 볼록함수가 아니다.
Gradient Descent의 방법과 직관적 의미
gradient descent 방법은 steepest descent 방법이라고도 불리는데, 함숫값이 낮아지는 방향으로 독립 변수 값을 변형시켜가면서 최종적으로는 최소 함숫값을 갖도록 하는 독립 변수 값을 찾는 방법이다.
steepest descent 방법은 다음과 같이 비유되기도 한다
앞이 보이지 않는 안개가 낀 산을 내려올 때는 모든 방향으로 산을 더듬어가며 산의 높이가 가장 낮아지는 방향으로 한 발씩 내디뎌 갈 수 있다.
Gradient descent의 목적과 사용 이유
gradient descent는 함수의 최솟값을 찾는 문제에서 활용된다. 함수의 최소, 최댓값을 찾으려면 '미분 계수가 0인 지점을 찾으면 되지 않느냐?라고 물을 수 있는데, 미분 계수가 0인 지점을 찾는 방식이 아닌 gradient descent를 이용해 함수의 최소값을 찾는 주된 이유는
- 우리가 주로 실제 분석에서 맞닥뜨리게 되는 함수들은 닫힌 형태(closed form)가 아니거나 함수의 형태가 복잡해 (가령, 비선형 함수) 미분계수와 그 근을 계산하기 어려운 경우가 많고,
- 실제 미분계수를 계산하는 과정을 컴퓨터로 구현하는 것에 비해 gradient descent는 컴퓨터로 비교적 쉽게 구현할 수 있기 때문이다.
추가적으로,
- 데이터 양이 매우 큰 경우 gradient descent와 같으 iterative 한 방법을 통해 해를 구하면 계산량 측면에서 더 효율적으로 해를 구할 수 있다.
확률적 경사하강법
경사하강법의 단점을 보완해보자.
- 확률적 경사하강법(stochastic gradient descent)은 모든 데이터를 사용해서 업데이트하는 대신 데이터 한 개 또는 일부 활용하여 업데이트한다.
- 볼록이 아닌(non-convex) 목적식은 SGD를 통해 최적화할 수 있다.
- SGD라고 해서 만능은 아니지만 딥러닝의 경우 SGB가 경사하강법보다 실증적으로 더 낫다고 검증되었다.
- 일부 데이터만 써서 업데이트하는 것을 mini batch라고 부르는데, 딥러닝에서의 SGD는 대부분 mini batch SGD를 뜻한다.
- SGD는 데이터의 일부를 가지고 파라미터를 업데이트하기 때문에 연산자원을 좀 더 효율적으로 활용하는데 도움이 된다.
- 일부만 사용하기에 그레이언트 벡터와 같을 순 없지만 확률 상 거의 유사하게 찾아진다.
- 전체 데이터 (X, y)를 쓰지 않고 미니배치 ($X_{(b)}, y_{(b)}$)를 써서 업데이트하므로 연산량이 b/n로 감소한다.
- 아래와 같이 미니배치를 이용하게 되면 모양이 바뀌지만 방향은 비슷하므로 가까운 값으로 가면서, 극값이면서 최솟값이 아닐 때도 탈출할 수 있음(가장 중요한 부분)
- SGD는 볼록이 아닌 목적식에서도 사용 가능하므로 경사하강법보다 머신러닝 학습에 더 효율적이다.
- 그중에서도 가장 중요한 부분은 딥러닝의 경우 일반적인 경사하강법처럼 모든 데이터를 업로드하면 메모리가 부족하여 Out-of-memory가 발생한다.
- 그래서 확률적 경사하강법의 미니 배치로 쪼개면 빠르게 및 학습이 가능해진다.
(Python 1-1강) Basic computer clas for newbies
Operation System, 운영체제
우리의 프로그램이 동작할 수 있는 구동 환경
File system, 파일 시스템
OS에서 파일을 저장하는 트리구조 저장 체계
파일의 기본 체계 - 파일 vs 디렉토리
디렉토리(Directory)
- 폴더 또는 디렉토리라 불림
- 파일과 다른 디렉토리를 포함할 수 있음
파일(File)
- 컴퓨터에서 정보를 저장하는 논리적인 단위
- 파일은 파일명과 확장자로 식별됨 (Ex) hello.py)
- 실행, 쓰기, 읽기 등을 할 수 있음
절대 경로와 상대 경로
경로 - 컴퓨터 파일의 고유한 위치, 트리구조상 노드의 연결
- 절대 경로 : 루트 디렉토리부터 파일 위치까지의 경로
- C:\user\docs...
- 상대 경로 : 현재 있는 디렉토리부터 타깃 파일까지의 경로
- ../../grant
터미널
mouse가 아닌 키보드로 명령을 입력하여 프로그램을 실행
우리는 주로 편의를 위해 GUI를 쓰지만, CLI로 터미널을 이용하여 프로그램을 실행할 수도 있다.
Windows - CMD window, Windows Terminal
- cmder도 권장(https://cmder.net/)
Mac, Linux - Terminal
Console = Terminal = CMD창, 모두 같은 의미
(Python 1-2강) 파이썬 개요
Python의 시작
- 1991년 귀도 반 로섬이 발표
- 플랫폼(운영체제) 독립적인 인터프리터 언어
- 객체 지향, 동적 타이핑 언어
- 객체 지향 : 실행 순서가 아닌 단위 모듈(객체) 중심으로 프로그램을 작성
- 동적 타이핑 언어 : 프로그램이 실행하는 시점에 프로그램이 사용해야 할 데이터에 대한 타입을 결정함
- 이것이 파이썬이 프로그래밍을 처음 하더라도 익히기 쉬운 이유
- 처음 C언어로 구현되었음
- 컴퓨터 성능이 비약적으로 발전하면서 인터프리터가 느리다는 단점이 있음에도 불구하고 사용할 수 있게 되었다.
- 하지만 기본적으론 컴파일러, 인터프리터 모두 OS에 맞춰서 기계어로 변형이 된 것 같지만, 우리 눈에 컴파일러는 한 번 거치게 보이고 인터프리터는 간단하게 바로 되는 것처럼 보일 뿐이다.
(Python 2-1강) Variables
변수
- 가장 기초적인 프로그래밍 문법 개념
- 데이터(값)를 저장하기 위한 메모리 공간의 프로그래밍상 이름
- 변수는 메모리 주소를 가지고 있고, 변수에 들어가는 값은 메모리 주소에 할당되는 것
※ [참고] : 컴퓨터는 왜 이진수를 쓰나?
- 컴퓨터는 실리콘이라는 재료로 만든 반도체로 구성됨
- 반도체는 특정 자극을 줬을 때 전기를 통할 수 있게 하는 물질
- 도체와 부도체에 반해 반도체는 전류의 흐름의 제어가 가능
- 전류가 흐를 때 1, 흐르지 않을 때 0으로만 숫자를 표현할 수 있음
- 이진수 한자리를 bit라 칭하고 8개의 bit는 1byte
리스트
- 리스트는 다양한 Data Type을 한 개의 리스트에 넣을 수 있다
- 리스트 변수에는 리스트 주소 값이 저장됨
a = [5, 4, 3, 2, 1]
b = [1, 2, 3, 4, 5]
b = a
# b라는 변수에 a라는 주소값을 할당해준 것
print(b)
# [5, 4, 3, 2, 1]
a.sort()
print(b)
# [1, 2, 3, 4, 5]
# 굉장히 매력적인 현상이지, a의 메모리 주소를 참조하기에
# a를 sort해줘도 b가 같은 값을 가리키는 것
패킹과 언패킹
- 패킹 : 한 변수에 여러 개의 데이터를 넣는 것
- 언패킹 : 한 변수의 데이터를 각각의 변수로 반환
t = [1, 2, 3] # 1,2,3을 변수 t에 패킹
a, b, c = t # t에 있는 값 1,2,3을 변수 a,b,c에 언패킹
print(t, a, b, c)
# [1, 2, 3] 1 2 3
※ [참고] 1차원에서는 copy가 먹지만, 2차원에서는 먹지 않기 때문에 deepcopy를 써주어야 한다.
(Python 2-2강) Function and Console I/O
함수의 개요
- 어떤 일을 수행하는 코드의 덩어리
# 사각형의 넓이를 구하는 함수
def calculate_rectangle_area(x, y) :
return x*y # 가로, 세로를 곱해서 반환
- 반복적인 수행을 1회만 작성 후 호출
- 코드를 논리적인 단위로 분리
- 코드 = 하나의 보고서
- 캡슐화 : 인터페이스만 알면 타인의 코드 사용
함수 수행 순서
- 함수 부분을 제외한 메인 프로그램부터 시작
- 함수를 우선 메모리에 올려놓고 시작함 → 그래서 함수는 제일 상단에 적어주는 게 좋다
- 함수 호출 시 함수 부분을 수행 후 되돌아옴
- 함수 사이에는 두줄 씩 띄우는 습성이 있음
parameter vs argument
- parameter : 함수의 입력 값 인터페이스
# parameter : x
def f(x) :
return 2*x+7
- argument : 실제 Parameter에 대입된 값
# argument : 2
print(f(2))
print formatting
print('My name is {0} and {1:10.5f} years old.".format(age, name))
# 0, 1이 순서임, 1뒤의 10.5f는 첫 번째 값을 10칸으로 표현하고(padding)
# 소수점 5자리까지라는 뜻
# >10s로 오른쪽 정렬을 수행할 수 있음
print("Product: %(name)10s, Price per unit: %(price)10.5f." %{"name":"Apple", "price":5.243}
# dictionary를 이용해서 formatting도 가능ddd
f-string
python3.6 이후 PEP498에 근거한 formatting 기법
print(f'{name:20}') # 20칸을 비우고 왼쪽정렬이 default
print(f'{name:*<20}') # 20칸 비우고, 왼쪽 정렬, 남은거 *로 채움
print(f'{name:*^20}') # 중앙정렬하고, 나머지는 *로 채움
(Python 3-1강) Python Data Structure
튜플
- 값의 변경이 불가능한 리스트
- 프로그램이 작동하는 동안 변경되지 않은 데이터의 저장
- 학번, 이름, 우편번호 등
- 사용자의 실수에 의한 에러를 사전에 방지
- 프로그램이 작동하는 동안 변경되지 않은 데이터의 저장
- 하나의 원소의 경우에는 (1)로만 쓰면 일반 정수로 인식이 된다. (1, )로 입력해주어야 함
집합
- 값을 순서 없이 저장, 중복 불허하는 자료형
- update : 한 번에 여러 개의 값을 추가하는 명령어
- discard : 삭제하는 명령어
- clear : 모든 원소 삭제하는 명령어
collections
deque
- rotate가 된다.
- appendleft, extendleft
- 기존 list보다 효율적인 자료구조를 제공
- % timeit이라는 함수를 쓰면 이 함수에 걸리는 시간을 표시해줌
defaultdict
- Dict type의 값에 기본 값을 지정, 신규 값 생성 시 사용하는 방법
- 선언 안 해줘도 정해진 타입으로 선언해줌
from collections import defaultdict
d = defaultdict(object) # Default dictionary를 생성
d = defaultdict(lambda : 0) # Default 값을 0으로 설정함
print(d['first'])
def default_value():
return 0
from collections import defaultdict
d = defaultdict(default_value) # 함수 대입
d['first'] # 0
namedtuple
- Tuple 형태로 Data 구조체를 저장하는 방법
- 저장되는 data의 variable을 사전에 지정해서 저장함
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
print(p[0]+p[1])
x, y = p
print(x, y) # 11, 12
print(p.x + p.y) # 33
print(Point(x=11, y=22)) # Point(11, 22)
(Python 3-2강) Pythonic code
[i+j for i in case_1 for j in case_2]의 경우
result = []
for i in case_1 :
for j in case_2 :
result.append(i+j)
# 와 같은데
# 2차원 리스트를 만들고 싶을 경우
[[i+j for i in case_1] for j in case_2]
for j in case_2 :
line = []
for i in case_1 :
line.append(i+j)
# 와 같다고 합니다.
- zip : 두 개의 list의 값을 병렬적으로 추출함
generator
- iterable object를 특수한 형태로 사용해주는 함수
- element가 사용되는 시점에 값을 메모리에 반환
- yield를 사용해 한번에 하나의 element만 반환함
def generator_list(value) :
result = []
for i in range(value) :
yield i
# memory 상에만 두고 할당은 안해뒀음
# for 문이 돌 때만 출력되고, 그렇기에 메모리를 많이 잡아먹지 않는다
for a in generator_list(50):
print(a) # 이때만 메모리 사용
gen_ex = (n*n for n in range(500)
# 위와 같이 큰 리스트를 생성할 때 generator로 두면 메모리를 잡아먹지 않고
# 필요할 때마다 불러쓸 수 있음
# 큰 데이터 쓸 때 참고하자
# 파일 데이터를 처리할 때도 generator를 쓰자
list(gen_ex) # 이렇게 사용해주면 된다.
가변인자 (variable-length)
- 개수가 정해지지 않은 변수를 함수의 parameter로 사용하는 법
- Keyword arguments와 함께, argument 추가가 가능
- Asterisk(*) 기호를 사용하여 함수의 parameter를 표시함
- 입력된 값은 tuple type으로 사용할 수 있음
- 가변인자는 오직 한 개만 맨 마지막 parameter 위치에 사용 가능
- 일반적으로 *args를 변수명으로 사용
- 기존 parameter 이후에 나오는 값을 tuple로 저장함
def asterisk_test(a, b, *args) :
return a+b+sum(args)
print(asterisk_test(1, 2, 3, 4, 5)
# 3,4,5가 tuple type으로 전달되는 것
- 키워드 가변인자(Keyword variable-length)
- Parameter 이름을 따로 지정하지 않고 입력하는 방법
- asterisk(*) 두 개를 사용하여 함수의 parameter를 표시함
- 입력된 값은 dict type으로 사용할 수 있음
- 가변인자는 오직 한 개만 기존 가변인자 다음에 사용
def kwargs_test_1(**kwargs) :
print(kwargs)
kwargs_test_1(first=3, second=4, third=5)
# {'first' : 3, 'second' : 4, 'third' : 5}
# 가변인자의 순서를 지켜줘야함
def kwargs_test_3(one, two=2, *args, **kwargs) :
print(one+two+sum(args))
print(kwargs)
kwargs_test_3(3, 4, 5, 6, 7, 8, 9, first=3, second=4, third=5)
# one=3, two=4
# args = (5, 6, 7, 8, 9)
# kwargs = {'first' : 3, 'second' : 4, 'third' : 5}
- asterisk *
- 곱셈에 주로 사용
- unpacking에도 사용
def asterisk_test(a, *args) :
print(a, *args)
print(a, args)
print(type(args)
test = (2, 3, 4, 5, 6)
asterisk_test(1, *test)
# unpacking이기에 args에는 2, 3, 4, 5, 6 총 5개의 변수가 들어간다
# 그래서 결과는
# 1 2 3 4 5 6 - *args로 unpacking 해줬기에 하나씩 나타남
# 1 (2, 3, 4, 5, 6) - args는 tuple 타입
asterisk_test(1, test)
# 이 경우는 튜플 test가 args로 들어갔기에
# 1 (2, 3, 4, 5, 6)
# 1 ((2, 3, 4, 5, 6),)
# 이라는 결과를 끄집어내줌
print("1", "2", "3", "4")
# 이 경우 4개가 출력
print(["1", "2", "3", "4"])
# 이 경우 1개가 출력
print(*["1", "2", "3", "4"])
# 이 때 마찬가지로 4개가 출력된다.
ex = ([1, 2], [3, 4], [5, 6])
for value in zip(*ex) :
print(sum(value))
# 직접 해보자
피어세션
- 경사하강법에 대해 토의하는 날이었는데, 다들 어제 궁금증이 해소되어서 질문이 없었다.
- 피어세션이 피어씁니다 발표자와 PPT 제작자를 선정했다
- 한 분이 참여가 불가하여 PPT를 맡으셨고, 나머지 인원 중 네이버 사다리를 통해 결정
- 각자 잘 나온 사진과 자신을 표현하는 태그, 팀 사진 등으로 PPT를 구성하였다
- 개요에서 언급했던 굉장히 우리를 곤란하게 만들었던 과제 4번에 대한 토론을 이어갔다.
- 오늘 있었던 컬리 면접에 대해 이야기 나누면서 진로 이야기도 한 스푼..!
과제
야구게임을 구현하는 과제였는데, 요구 함수도 굉장히 많고 출력 내용도 일치하여야 해서 되게 꼼꼼한 작업이 필요한 과제였다. Stopiteration이라는 처음 보는 Error 때문에 고생을 좀 했는데 함수 구현에는 문제가 없지만 출력이 정답과 맞지 않아서 발생한 Error라고 예측한다.
또한 while 구문을 통해 계속 반복하다가 조건에 맞춰 함수를 종료해주어야 하는데 break나 exit으로 하다 보니 원하는 대로 종료되지 않아서 헤매기도 했다. 결국 return으로 함수를 종료시켜주었고, 다른 분들의 의견을 들어보니 flag로 많이들 해결하시는 것 같다. 앞으로 더 어려워지면 쪼끔은 곤란할지도..? 하지만 화이팅 !!!
[AI Tech]Daily Report
Naver AI Tech BoostCamp 2기 캠퍼 허정훈 2021.08.03 - 2021.12.27 https://bit.ly/3oC70G9
www.notion.so
'Coding > BoostCamp' 카테고리의 다른 글
[BoostCamp] Week1_Day5. 한 주의 마무리 (2) (0) | 2021.08.09 |
---|---|
[BoostCamp] Week1_Day5. 한 주의 마무리 (1) (0) | 2021.08.08 |
[BoostCamp] Week1_Day4. 길잡이, 마스터와의 만남 (0) | 2021.08.06 |
[BoostCamp] Week1_Day3. 예상치 못한 인연의 시작 (4) | 2021.08.05 |
[BoostCamp] Week1_Day1. 긴 여정의 서막 (3) | 2021.08.03 |