1. 강의

1) 교재

 

 

통계 이해, 빅데이터 분석 4권

전반적으로 정말 통계와 코드에 대해서 잘 설명하고 있는 교재이다. 책에 있는 거 머리에 집어넣느라 고생 좀 했는데...

그만큼 정말 많은 정보가 들어가 있다.

 

단점을 꼽자면, 코딩에 익숙한 나도 통계 쪽 라이브러리를 쓰니까 정신을 잘 못 차리고 있었는데 그 부분에 대한 강의가 뒤쪽에 배치되어 초반에 엄청 구글 검색을 많이 했다..ㅠ

 

2) 강사
강사분들이 A반, B반으로 나누어지기 때문에 이렇다 저렇다 할 수는 없고 복불복이다..!

그래도 통계 시험을 잘 보고 싶다면 교수님들이 질문하는 것들을 잘 적어두고, 예제들을 깔끔하게 정리해보길!!

 

졸리고 모르겠어도 강사님이 말하시는 거 일단 적고 나중에 차근차근 공부하면 '아 그때 이게 그말이었어?' 라고

이해하게 될 꺼에요^^

 

[시험 대비 Tip]을 주자면

전략적으로 시험에 나올 수 있는 예제인지 아닌지, 이 예제를 시험에 낼 꺼면 어떻게 input이 주어질지

시험 전날에 잠깐 살펴본 것으로도 큰 도움이 됐다.

 

물론, 시험 문제 짚어주시는 부분은 당연히 다 알아야겠죠?!ㅎㅎ

 

좀 더 강의 준비를 잘하고 싶다면

우선, 타자가 느린 사람들은 코드를 따라치는 것도 힘들어하고, 타자가 빨라도 코드가 뭘 의미하는지 잘 모르니까

속도가 좀 느려지는 감이 없지 않아 있는 것 같았다. (타자 연습은 좀 열심히 해오시길..!)

 

'Do it! 데이터 분석을 위한 판다스 입문', '파이썬 머신러닝 판다스 데이터 분석' 책에 통계 라이브러리에 대한 기초 설명

나는 읽어보면서 다음날 수업에 관련된 코드를 예습했다.
(책 사기 아까우면 이 책으로 공부해서 블로그에 올린 사람들 포스팅을 참고하는 것도 큰 도움이 된다!)

 

2. 과제 

매일 강의하면서 교재에 있는 실습 코드를 따라치는데, 그 실습 코드나, 그 실습 코드를 조금 응용한 문제들을 내주신다.

(교재에 다 있는 문제들이니까 수업 시간에 잘 작성해놓으세요!)

 

그리고 종합 실습 문제가 2개 나오는데, 답이 없고, 내가 어떻게 분석하고 보고서를 작성하느냐에 따라 다른 것 같다.

분석은 논리적인 구조를 만족시키는 근거와 주장으로 이루어지면 되는 것 같다.

 

[과제 Tip]을 주자면

사전조사가 필요한 경우도 있고, 데이터 전처리 같은 부분은 어파티 다들 해야하는 부분이잖아요? 

근데 여러분은 시간이 없을거란 말이죠? 그럼 어떻게 해요? 개인 과제지만 분..어..ㅂ (이후 생략) :)

 

3. 프로젝트

자, 가위바위보를 통해서 여러분들의 프로젝트 주제가 정해졌겠죠??

 

일단 받으면 데이터를 못 보게 하고 이것저것 예상해보고 계획을 하게 하는데,

사실 데이터 받고 나서는 생각한 것과 너무 달라서 다시 계획을 엎어야하고 그래요.. 그래도 시간 낭비라고 생각하지 마시고 꼭 집중해서 해보세요. (나중에 회사에서는 그런 경험이 도움이 될 테니까!)

 

데이터를 받고 정신이 없을 텐데, 우선 분업을 하세요.

ppt를 만들고, 거기에 넣을 정보를 분석해줄 사람, 그리고 이것과 상관없이 프로젝트를 큰 관점에서 계속 뜯어볼 사람 등등

 

수업 시간에 계속 발표를 시키기 때문에 이 발표를 어쨌든 하기 위해 시간에 맞춰서 분석을 해내는 것도 여러분의 능력이니까

(이 경험을 통해서 순발력과 통찰력을 얻을 수 있기를ㅎㅎ)

 

데이터를 받은 주말에는 데이터 전처리를 끝내세요. 그 다음에 하게 될 내용이 책에 있는데 ppt도 미리 해놓으면 좋은데 아마도 시간이 부족해서 쓰-읍.. 그리고 다들 힘들었으니까 바람도 좀 쐬고 오시는 것을 추천합니다 :)

 

 

공부하면서 진짜 스트레스도 많이 받을 거에요.

여기 뽑히신 분들이라면 그래도 어디가서 못 한다는 소리는 못 들어본 사람들일텐데

'내가 이렇게 무능력한가' 이런 생각도 들꺼에요!

근데 아마 우리가 회사에 처음 입사하면 그렇게 느끼지 않을까요?ㅎㅎ

 

그런 상황에 직면했을 때 어떻게 행동하느냐에 따라

아카데미를 끝내고 나갈 때 웃을 수 있을지, 후회가 남을지는 

나 자신과의 싸움인 것 같습니다.

 

생각나는대로 적어봤는데, 부족하지만 도움이 되셨으면 좋겠습니다.

이후 청년 아카데미 교육생들, 화이팅입니다!

 

P.S. 혹시나 궁금해하실 분들을 위해

통계 과정에서 [저의 하루 루틴]은 아래와 같습니다.

아침: 오늘 있을 수업 예습(모르는 코딩 문법 찾기, 이론 읽어보기)

오전: 강의(쉬는 시간에 오늘 나올 과제 작성, 스트레칭)

점심: 식사 및 산책(무조건!)

오후: 강의(쉬는 시간에 오늘 나올 과제 작성, 스트레칭)

저녁: 식사, (과제 남았을 시) 과제 작성, 당일 수업 복습 및 모르는 것 서로 물어보고 알려주기,
        (실습 과제 나왔다면) 실습 과제 분석

 

저녁 같죠?ㅎㅎ 아침에 집들어가는거에요><

 

1. 음료수 얼려먹기

: 단순하게 0인 부분을 채우고, 채워진 0 부분이 몇 개인지 출력하면 되는 문제이다.

'''
input:
4 5 
00110
00011
11111
00000
output: 3

input:
5 7
1010101
0101010
1111000
0100111
0110000
output: 8

input:
4 5
10001
00000
00000
10001
output: 1
'''

1) BFS

from collections import deque
dpos = [(0, 1), (-1, 0), (0, -1), (1, 0)]

def __main__():
    N, M = map(int, input().split())

    ice_tray = [0 for _ in range(N)]
    for i in range(N):
        ice_tray[i] = list(map(int, input()))
    
    ''' another way
    ice_tray = []
    for i in range(N):
        ice_tray.append(list(map(int, input())))
    '''

    visit = [[0 for col in range(M)] for row in range(N)]
    cnt = 0
    que = deque()

    for i in range(N):
        for j in range(M):
            if visit[i][j] or ice_tray[i][j]:
                continue
            que.append((i, j))
            visit[i][j]=1
            cnt += 1
            while que:
                x, y = que.popleft()
                for dx,dy in dpos:
                    nx, ny = x + dx, y + dy
                    if nx < 0 or nx >= N or ny < 0 or ny >= M or visit[nx][ny]:
                        continue
                    visit[nx][ny] = 1

                    if ice_tray[nx][ny] == 0:
                      que.append((nx,ny))

    return  print("output >>", cnt) 

__main__()

나의 실수> 우선 input에서 input().split()을 사용하면 배열에 제대로 채워지지 않는다. (이건 왜 안 되는지 모르겠다..)

 

2) DFS

dpos = [(0,1),(1,0),(0,-1),(-1,0)]

def DFS(x, y):
    global N, M, ice_tray, visit

    for dx, dy in dpos:
        nx, ny = x + dx, y + dy
        if nx < 0 or nx >= N or ny < 0 or ny >= M or visit[nx][ny] == 1:
            continue

        visit[nx][ny] = 1
        if ice_tray[nx][ny] == 0:
            DFS(nx, ny)

전역변수로 사용하기 위해서 global 키워드를 사용했다.

def __main__():
    global N, M, ice_tray, visit

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

    ice_tray = [0 for _ in range(N)]
    for row in range(N):
        ice_tray[row] = list(map(int, input()))

    visit = [[0 for _ in range(M)] for _ in range(N)]

    cnt = 0
    for i in range(N):
        for j in range(M):
            if ice_tray[i][j] == 1 or visit[i][j] == 1:
                continue
            visit[i][j] = 1
            DFS(i,j)
            cnt += 1
    print("output >> ", cnt)
    return 0

__main__()

 

2. 미로 탈출
: 미로에서 탈출 가능한 최단 경로의 길이를 출력하면 된다.

''' 
input:
5 6
101010
111111
000001
111111
111111
output: 10

input:
5 10 
1001100011
1001110100
1111010111
1010010101
1110111101
output: 20
'''

1) BFS

: BFS는 너비 우선 탐색이기 때문에 찾은 값이 최소 거리일 수 밖에 없다.

from collections import deque
dpos = [(0, 1), (-1, 0), (0, -1), (1, 0)]

def BFS(x,y,r):
  global N, M, maze, visit
  visit[x][y]=1
  que = deque()
  que.append((x,y,r))
  while que:
      x,y,r = que.popleft()
      for dx,dy in dpos:
        nx, ny, nr = x + dx,y + dy, r+1
        if nx < 0 or nx >= N or ny < 0 or ny >= M or visit[nx][ny]:
          continue
        if nx == N-1 and ny == M-1:
          return nr

        visit[nx][ny] = 1
        if maze[nx][ny] == 1:
          que.append((nx, ny, nr))
def __main__():
    global N, M, maze, visit

    N, M = map(int, input().split())
    maze = [0 for _ in range(N)]
    for i in range(N):
        maze[i] = list(map(int, input()))
    visit = [[0 for col in range(M)] for row in range(N)]

    return print("output >>", BFS(0, 0, 1))
  
__main__()

2) DFS

: DFS는 깊이 우선 탐색이므로 출구에 도착했을 때 계산한 경로들 중에 제일 작은 값을 찾아서 출력해야한다.

dpos = [(0, 1), (-1, 0), (0, -1), (1, 0)]

def DFS(x,y,cnt):
  global N, M, mincnt
  if x == N-1 and y == M-1:
    if mincnt > cnt:
      mincnt = cnt
    return cnt

  for dx, dy in dpos:
    nx, ny = x + dx, y + dy
    if nx < 0 or nx >= N or y < 0 or ny >= M or arr[nx][ny] == 0 or visit[nx][ny] == 1:
      continue
    
    if arr[nx][ny] == 1:
      visit[nx][ny] = 1
      DFS(nx, ny, cnt+1)
      visit[nx][ny] = 0
def __main__():
    global N, M, mincnt, arr, visit

    N, M = map(int, input().split())
    mincnt = 201 * 201
    arr = []
    for i in range(N):
        arr.append(list(map(int, input())))

    visit = [[0 for col in range(M)] for row in range(N)]
    visit[0][0] = 1

    DFS(0, 0, 1)

    return print("output >>", mincnt)
  
__main__()

 

BFS와 DFS로 문제를 풀면서 부족했던 점은 조건을 기입할 때 visit과 arr을 사용하는 것에 혼동하는 경우가 있는 것 같다.

주의해야 할 것 같다!

 

github.com/katherine4191/This-is-a-coding-test/tree/master/CH5%20BFS%26DFS

 

katherine4191/This-is-a-coding-test

Contribute to katherine4191/This-is-a-coding-test development by creating an account on GitHub.

github.com

 

1. selection sort 선택 정렬

: 가장 작은 것을 선택해 차례대로 맨 앞의 데이터와 바꾸는 정렬 방법

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_idx = i
        for j in range(i+1,n):
            if arr[min_idx] > arr[j]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
        #print("sorting ... ",arr)
    return arr
''' output
sorting ...  [0, 5, 9, 7, 3, 1, 6, 2, 4, 8]
sorting ...  [0, 1, 9, 7, 3, 5, 6, 2, 4, 8]
sorting ...  [0, 1, 2, 7, 3, 5, 6, 9, 4, 8]
sorting ...  [0, 1, 2, 3, 7, 5, 6, 9, 4, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 9, 7, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 9, 7, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 9, 7, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''

 

2. Insertion sort 삽입 정렬

: 특정한 값을 적절한 위치에 삽입하는 정렬 방법(그 위치 앞까지는 이미 정렬되어 있음)

def insertion_sort(arr):
    n = len(arr)
    for i in range(1,n):
        for j in range(i-1, -1, -1):
            if arr[j] > arr[j+1]: # 해당 데이터의 위치 자동 갱신 가능
                arr[j], arr[j+1] = arr[j+1], arr[j]
            else: 
                break
        #print("sorting ... ",arr)          
    return arr 
''' output
sorting ...  [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
sorting ...  [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
sorting ...  [0, 5, 7, 9, 3, 1, 6, 2, 4, 8]
sorting ...  [0, 3, 5, 7, 9, 1, 6, 2, 4, 8]
sorting ...  [0, 1, 3, 5, 7, 9, 6, 2, 4, 8]
sorting ...  [0, 1, 3, 5, 6, 7, 9, 2, 4, 8]
sorting ...  [0, 1, 2, 3, 5, 6, 7, 9, 4, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
sorting ...  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''

나의 실수> 

j for문에서 j와 i를 사용하여 값을 비교했는데 이때 i로 인해 업데이트되는 값을 따라가지 못했는데 j+1을 통해 자동으로 값이 업데이트 되는 것을 알 수 있었다. 

 

3. quick sort 퀵 정렬

: pivot을 사용하여 왼쪽부터 pivot보다 큰 데이터를 찾고, 오른쪽부터 pivot보다 작은 데이터를 찾아 큰 데이터와 작은 데이터를 찾아 위치를 서로 교환하는 정렬 방법

: 작은 데이터와 큰 데이터를 찾았을 때 index가 엇갈린 경우에는 pivot과 찾은 작은 데이터(right index)와 교체한다

def quick_sort(pivot, end, arr):
    if pivot >= end:
        return    
    
    left, right = pivot + 1, end
    
    while left <= right:
        while left <= end and arr[pivot] >= arr[left]:
            left += 1
        while right > pivot and arr[pivot] <= arr[right]:
            right -= 1

        if left > right: # 두 값이 엇갈린 경우 작은 데이터(right)와 pivot 교체
            arr[pivot], arr[right] = arr[right], arr[pivot]
            #print("sorting ... "arr)
        else:
            arr[left], arr[right] = arr[right], arr[left]

    # 현재는 arr[right]에 pivot 값이 존재, pivot은 배열의 앞 부분을 의미
    quick_sort(pivot, right - 1, arr) 
    quick_sort(right + 1, end, arr)
    return arr
''' pivot이 바뀌는 과정
sorting ... [0, 1, 2, 4, 3, 5, 6, 9, 7, 8]
sorting ... [0, 1, 2, 4, 3, 5, 6, 9, 7, 8]
sorting ... [0, 1, 2, 3, 4, 5, 6, 9, 7, 8]
sorting ... [0, 1, 2, 3, 4, 5, 6, 9, 7, 8]
sorting ... [0, 1, 2, 3, 4, 5, 6, 8, 7, 9]
sorting ... [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sorting ... [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''

나의 실수> while left <= right:을 생각하지 못했다.

또 배열을 slicing해서 넘기는 바보 같은 생각을 했다... merge할 거 아니면 start와 end idx로 재귀에서 arr을 수정하면 되는데, idx잘 계산해놓고 arr[:right-1], arr[right+1:] 이런 걸 넘기다니 정말 내가 왜 이렇게 짰었는지 도통 모를 일이다.

 

4. counting sort 계수 정렬

: 별도의 리스트를 선언하고 그 안에 정렬에 대한 정보를 담아 정렬하는 방법

def counting_sort(arr):
    count_arr = [0 for _ in range(max(arr)+1)]

    for val in arr:
        count_arr[val] += 1
    
    arr = []
    for i in range(len(count_arr)):
        while count_arr[i]:
            arr.append(i)
            count_arr[i] -= 1
            
    return arr

 

main 함수

def main():
    unsorted = [5,7,9,0,3,1,6,2,4,8]
    print("selection_sort",selection_sort(unsorted))
    
    unsorted = [7,5,9,0,3,1,6,2,4,8]
    print("insertion_sort", insertion_sort(unsorted))

    unsorted = [7,5,9,0,3,1,6,2,4,8]
    print("quick_sort", quick_sort(0, len(unsorted)-1, unsorted))
    
    unsorted = [7,5,9,0,3,1,6,2,9,1,4,8,0,5,2]
    print("counting_sort", counting_sort(unsorted))

main()
''' output
selection_sort [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
insertion_sort [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
quick_sort [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
counting_sort [0, 0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9]
'''
  선택 정렬 삽입 정렬 퀵 정렬 계수 정렬
시간 복잡도 O(N^2) O(N^2) O(logN) O(N+K)

 

Ellipsis 객체는 원래 ndarray의 indexing과 slicing을 도와주는 객체이다.

사이트에 적힌 원문을 번역해보면,

모든 차원을 인덱싱하기 위해 선택 튜플에 필요한 개체 수로 확장한다는 말인데.. 일단 보자!

numpy.org/doc/stable/reference/arrays.indexing.html

 

Indexing — NumPy v1.19 Manual

Indexing ndarrays can be indexed using the standard Python x[obj] syntax, where x is the array and obj the selection. There are three kinds of indexing available: field access, basic slicing, advanced indexing. Which one occurs depends on obj. Note In Pyth

numpy.org

1) 단독으로 사용했을 때 arr == arr[...]
   : 왜냐하면 Ellipsis 객체로 모든 차원을 선택했기 때문이다.

2) '...' vs ':'의 차이
   : 아직 이해를 못한 것 같다...

 

3) 2D Array

 

4)  3D Array

   : '...'는 index에서 딱 한 번만 사용할 수 있다. 여러 Ellipsis를 사용하면 error가 난다.

 

'ML&AI > 관련 python, lib 문법' 카테고리의 다른 글

numpy.ndarray.astype  (0) 2021.01.27
np.linspace()  (0) 2021.01.27
np.random.rand()  (0) 2021.01.27

Numpy 배열 ndarray는 dtype으로 저장되는데, 이 dtype은 np.array()로 ndarray를 생성할 때 지정하거나 astype() method로 변경할 수 있다.

 

ndarray.astype(dtype, order='K', casting='unsafe', subok=True, copy=True)

: ndarray의 dtype을 변경하는 함수

import numpy as np 

a = np.array([1, 2, 3], dtype=np.int64) 
print(a.dtype) # [1, 2, 3]
print(a) # int64

a = a.astype(np.float32) # 꼭 재할당을 해줘야한다
print(a.dtype) # float32
print(a) # [1. 2. 3.]

 

* dtype의 유형

int8, int16, int32, int64
unit8, unit16, unit32, unit64
float16, float32, float128
complex64, complex128, complex256
bool, unicode, object

 

'ML&AI > 관련 python, lib 문법' 카테고리의 다른 글

Ellipsis 객체, '...' in Python  (0) 2021.01.27
np.linspace()  (0) 2021.01.27
np.random.rand()  (0) 2021.01.27

np.linspace(startstopnum=50endpoint=Trueretstep=Falsedtype=Noneaxis=0)

: start를 배열의 시작값, stop을 배열의 끝값으로 하여 start와 stop 사이를 num개의 일정한 간격으로 1차원 배열로 반환

np.linspace(2.0, 3.0, num=5)
# array([2.  , 2.25, 2.5 , 2.75, 3.  ])

 

np.linspace(2.0, 3.0, num=5, endpoint=False)
# array([2. ,  2.2,  2.4,  2.6,  2.8])

endpoint가 True이면 stop이 마지막 sample이 되고, False이면 포함되지 않는다. default = True

 

np.linspace(2.0, 3.0, num=5, retstep=True)
# (array([2.  ,  2.25,  2.5 ,  2.75,  3.  ]), 0.25)

retstep가 True이면 (samples , step:sample 사이 간격)을 반환하고, False이면  step이 포함되지 않는다. default = False

 

numpy.org/doc/stable/reference/generated/numpy.linspace.htmlnumpy.org/doc/stable/reference/generated/numpy.linspace.html

 

numpy.linspace — NumPy v1.19 Manual

Return evenly spaced numbers over a specified interval. Returns num evenly spaced samples, calculated over the interval [start, stop]. The endpoint of the interval can optionally be excluded. Changed in version 1.16.0: Non-scalar start and stop are now sup

numpy.org

 

'ML&AI > 관련 python, lib 문법' 카테고리의 다른 글

Ellipsis 객체, '...' in Python  (0) 2021.01.27
numpy.ndarray.astype  (0) 2021.01.27
np.random.rand()  (0) 2021.01.27

+ Recent posts