728x90
반응형

What I did today


  1. 머신러닝 실시간 강의를 들었다. 실강 때는 라이브러리 설치가 넘 빡세서 시작도 못했던지라 녹화 영상으로 겨우…ㅎ
  2. 머신러닝 3주차 완강
  3. 타임어택
  4. 사이드 프로젝트 회의

Feeling


난 무엇을 공부하든 ‘설명할 수 있는가’를 기준으로 삼고 공부한다. 물론 여건상 기준으로 삼는다는 것과 실제 학습 수준 사이에 의미 차이를 두는 경우가 다반사긴 하다. 하지만 다행히도 이번 머신러닝 기간 동안은 이전에 이미 미뤄둔 것들을 제외한다면 4주차 과정에 주말을 끼고도 5일이라는 시간을 받은지라 꽤나 여유로운 편이다. 내용이 어렵긴 하지만, 뭐 그렇다고 코딩과 파이썬을 동의어로 보던 시절 처음으로 더 넓은 세계를 보여준 웹종이나 본격적으로 url을 가지고 통신을 조금씩 만지기 시작한 장고가 체감 난이도에서 뒤떨어지는 건 아니니까.

심지어 꽤 흥미롭기까지 하다. 흥미와 재능이 다른 영역이기도 하고, 전공자나 현직자가 보면 코웃음 칠 정도의 내용에 조금 흥미를 느낀다고 적성을 논하거나 우쭐해질 생각은 전혀 없지만, 어쨌든 앞서 언급한대로 현재 진도를 나간 3주차까지는 이해한 범위까지 설명할 수 있을 정도로 공부해 두었다.

하지만 4주차를 남겨두고 고민이 많다. 아무리 봐도 프로젝트에 실질적으로 도움이 되는 지식은 원격강의보다는 실시간 강의에서 배운 내용일 거 같아서 4주차를 나중에 듣는다 하더라도 그 시간을 아직도 헷갈리는 게 많은 장고를 더 보충하거나 튜터님꼐서 권장하진 않으셨지만 나만의 데이터셋으로 모델을 학습시켜보는 데 쓰는 것도 나쁘지 않을 것 같다. 내일 오전까지 고민을 끝마치고 시간 배분을 해둬야 할 듯하다. 그 때까진 머신러닝 3주차 요약정리도 미뤄야겠다.

ChitChat


원격 강의를 담당하신 튜터님께서 말씀하셨듯 어려운 수학 이론들이 많이 배제된 강의라 그런지 꽤 재미를 느끼고 있다. 기초적인 내용이라 골 아픈 내용이 적어서 그런 것도 있을 것이다. 근데 사실 생각해 보면 머신러닝 내용 자체에 대한 흥미라기보다는, 접해본 적이 없어 낯설고 어렵게 느껴지는 이론이 진도를 나가면서 막혀있던 게 뚫리듯 한개씩 이해되기 시작하는 느낌이 흥미를 유발하는 것 같다.

그리고 딥러닝의 역사 부분에서 튜터님이 재밌을 거라길래 에이 아무리 그래도 재미있다고 명확하게 느낄 것까지야… 라는 생각을 가지고 들었는데 놀랍게도 진짜 재밌었다. 가령 선형 회귀로 풀리지 않는 문제들이 발생하자 선형 회귀로 풀 수 없다는 것은 곧 비선형이라면 풀 수 있는 문제들이 존재한다는 발상으로 이어지는 게 인상깊었다. 이런 발상의 전환… 과학에서 뜬금없이 느껴지는 긍정적인 자기 계발 분야의 냄새 같은 것… 코딩을 하다 오류가 날 때도 비슷하게 생각하기로 했다. 풀 수 없는 문제는 없고, 다만 풀이가 조금 잘못되었을 뿐이니 다른 풀이를 찾으려 끊임없이 시도해 보자고.

과적합 현상같은 것도 간단한 계산밖에 하지 못하던 기계들이 더 어려운 문제를 풀기 위해 더 많은 지식을 탐구하면서 오히려 정답에서 멀어지는 모습이 꼭 이미 뛰어넘어버리긴 했지만 과거 기계가 목표했을 고지능을 가진 인간의 모습과 꼭 닮아있다고 느꼈다. 인간도 단순하게 생각하면 단순해지고 고심하면 심오해지는 문제에 대해 후자를 택하는 경향이 짙으니까. 논란의 여지가 있겠지만 가령 철학에도 그런 면모가 어느정도 있고. 기계가 인간을 뛰어넘어봤자 인간이 세운 논리 체계 내에서의 정답을 찾아내는 것이기 떄문에 이런 일이 발생하는 걸까, 아니면 학습 데이터가 결국 인간으로부터 기인하기 때문일까 이런 저런 생각이 들었다. 이쪽 분야를 잘 아는 사람이 보면 저게 뭔 핀트가 벗어난 이야기지, 전혀 그런 이유 아닌데 생각할 수도 있지만 이쪽 분야와 담 쌓고 지낸 사람의 상상력과 지식으로는 이런 궁금증들이 생겨났었다. 여튼 재밌었다고.

타임어택 작성 코드


# 사람 한명씩 자르기
for k, res in enumerate(result) :
    cropped = tmp_img[int(res[1]) : int(res[3]), int(res[0]) : int(res[2])]
    cv2.imwrite(f'people{k}.png', cropped)

#동일한 기능 수행하는 코드
for k in range(len(result)) :
    cropped = tmp_img[int(result[k][1]) : int(result[k][3]), int(result[k][0]) : int(result[k][2])]

 

Today I Learned


  1. pipi install -r requirements.txt : 하도 라이브러리 설치에 오류가 많아서 걍 내가 requirements.txt를 생성해서 내용 복붙하고 진행하니까 겨우 됐다. 아니 아무런 오류메시지도 없이 걍 쌩으로 설치가 안 되는 건 무슨 경우람…^^
  2. 사진을 불러와 인식시키는 코드
    • yolov5s.py 파일이 생성되어야 한다.
    • exp는 몇 번 실행 횟수에 따라 디렉토리가 만들어지는 것이기 때문에 신경쓰지 않아도 됨.
  3. 인식한 사진의 좌표를 찾아 해당 영역에 네모를 그려주는 코드
    • results.xyxy[0]의 출력
      • 라이브러리에서 결과가 tensor형으로 나오게 하는 걸 .xyxy로 하라고 정해둠. 각각 결과만 보면 뜻을 알기 힘드니까 pandas 사용한다.
    • results.xyxy[0][0][0].item()의 출력
      • 인덱싱하고 item을 꺼내와야 하는 이유 : 우리는 정수 형태의 숫자만 사용할 수 있기 때문에 인덱싱과 item() 과정을 거치지 않은 tensor는 사용할 수 없다.
      • ‘정수’ 형태가 필요하기 때문에 후에 int()를 통해 변환 과정까지 거쳐야 한다.
    • results.pandas() : pnadas 데이터 프레임 형태로 바꾼 걸 보기 편하게 만듦.
      • 4가지 좌표(xmin / ymin / xmax / ymax)로 이루어져 있다.
      • 좌표값을 써야만 그림을 그리기도 하고 자르기도 하고 할 수 있다.
      • 좌표를 쓰려면 .item()으로 뽑아내야 한다.
      • confidence는 확률로, 네모 박스 안이 person일 확률, 즉 사람일 확률이 0.879861(→대충 88%쯤)이라는 것이다.
    • 그 중 첫번째 거에만 네모 박스를 그려서 result.png로 저장하는 코드가 아래 코드
      • tmp_img = cv2.imread('zidane.jpg') : argument로 들어가는 이미지를 읽어와서 tmp_img에 저장. 이때 읽어오는 이미지는 코드가 쓰이고 있는 .py 파일과 같은 위치에 있는 사진을 읽어오는 것이므로 runs같은 디렉토리에 있는 사진은 읽어올 수 없다.
      • cv2.rectangle : tmp_img에 네모를 그려준다. 인자로 좌표를 넣어줄 때 min → max 순서로 넣는다.
      • cv2.imwrite('result.png', tmp_img) : 네모까지 그려 준 tmp_img를 result.png로 저장한다.
    • model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) # install dependencies : 모델을 로드하는 코드
    • imgs = cv2.imread('zidane.jpg') : 사진을 읽어서 변수 imgs에 저장
    • results = model(imgs) : 불러[로드해] 온 모델에 이미지를 넣은 걸 results로 받는다.
    • result = results.pandas().xyxy[0].to_numpy() : pandas 데이터 프레임을 to_numpy()를 이용해 numpy 배열로 바꾼다.
    • result = [item for item in result if item[6] == 'person'] : 6번째 아이템이 person인 경우에만 result에서 뽑아서 리스트로 만들어준다. 그러면 해당 리스트에는 person인 것만 남는다.
    • 사진에서 person에 해당하는 부분만 잘라줄 것!
    • tmp_img = cv2.imread('zidane.jpg') : zidane.jpg 이미지를 읽어와서 tmp_img에 넣는다.
    • print(tmp_img.shape)
      • (720, 1280, 3)을 출력한다.
      • 세로가 720px, 가로가 1280px, 색상 인지가 RGB라는 뜻
    • cropped = tmp_img[int(result[0][1]) : int(result[0][3]), int(result[0][0]) : int(result[0][2])]
      • tmp_img에서 해당 부분만 가져가겠다!
      • .rectangle()에서 xmin → ymin → xmax → ymax 순으로 적은 것과 달리 **ymin → ymax → xmin → xmax 순**으로 적었다. (외워야 함! 모르면 구글링!)
      • 정수로만 받을 수 있어서 변환해주는 건 동일하다.
      • 이미지를 crop할 때 좌표는 이미지마다 일일이 다 작성해 주어야 한다.
    • print(cropped.shape)
      • (675, 406, 3)을 출력한다.
      • 세로가 675px, 가로가 406px, 색상 인지가 RGB라는 뜻
    • cv2.imwrite('result2.png', cropped) : cropped한 걸 result2.png 파일로 저장 사진 crop 코드
    •  💡 지금은 하나만 했지만 리스트를 돌면서 사람들을 다 저장해줄 수도 있고, 넥타이로 바꿔서 넥타이를 저장해줄 수도 있다
반응형

'Programming > TIL and WIL' 카테고리의 다른 글

221016 TIL - ImproperlyConfigured  (0) 2022.10.18
221015 TIL - 머신러닝 네모 그려주는 좌표  (0) 2022.10.18
221012 Today I Learned (TIL)  (0) 2022.10.13
221011 Today I Learned (TIL)  (0) 2022.10.11
221010 Weekly I Learned (WIL)  (0) 2022.10.11

+ Recent posts