반응형

작년 11월 27일 건강검진을 받았다.

어주 몹쓸 정도는 아니었지만 결과가 썩 좋지는 않았다.

대표적으로 보면 다음과 같다.

 

  • 감마GTP : 정상 범위 16 ~ 73, 측정 값 175
  • 총콜레스테롤 : 정상 범위 120 ~ 220, 측정값 279 
  • LDL : 정상 범위 0 ~ 130, 측정값 188 
  • Trigliceride(중성지방) : 정상 범위 50 ~ 130 측정값 148
  • 공복 혈당 : 정상 범위 70 ~ 110, 측정 값 126
  • 그밖에 궤양의 흔적이 보이는 위염

 

그동안 한 10여년 이상 건강검진 결과가 이 수치에서 앞서거니 뒤서거니 하면서 유지되고 있었다.

그런데 요즘 집사람 건강도 좋지 않고 슬슬 나이도 먹어가니 조금은 관리라는 것을 해볼 필요가

있을 것 같아 나름 시도를 해보았다.

 

운동

 

일단 운동은 2019년도 한 1년간 열심히 했다. 뭐 내 기준에서의 열심히라서 별로 한 것은 없지만…

실내 자전거 사서 1년 중 한 3주 정도를 제외하면 매일 1시간씩 실내 자전거를 돌렸다. 물론 주 목적은

건강을 위한 운동이라기보다는 넷플릭스 시청이었지만…^^;;

 

그래도 그 덕분인지 작년 건강 검진의 일부 수치는 2018년도에 받은 건강검진 결과에 비해 결과가 좋은

편이었다. 전체적으로 큰 변화가 없었던 것이 문제였지…

 

사실 2019년도에 그렇게 열심히 타다가 2019년 말부터 2020년도 초까지 고도화 프로젝트가 있어서

제대로 운동을 못하면서 2020년은 거의 운동을 안하고 지냈다. 아마 이때도 열심히 했더라면 결과는

더 좋지 않았을까?

 

그리고 작년 검진 이후 다시 운동을 시작했다.처음 시작은 그 전과 같이 실내 자전거만 했는데 중간에 몇가지

맨손 운동을 포함했다. 우선 스쿼트 40개를 추가했고 그렇게 한 달 정도 하다가 다시 플랭크를 30초 이상

추가, 다시 최근에 아령을 이용한 운동 몇가지를 시작했다.

 

그래서 하루에 풀코스로 하면 자전거타기 1시간, 스쿼트 40개, 플랭크 30~90초, 아령 30개씩 3세트 정도를 

하고, 다만 가끔 피곤하면 자전거만 타기도 했지만 그래도 일주일에 3번 이상은 풀코스로 했다.

 

1kg짜리로 하다가 뭔가 부족해서 새로 산 2Kg짜리 아령과 평소에는 옷걸이로 쓰다가 퇴근 후 운동기구로 변신하는 트랜스포머 실내 자전거^^

 

식단

 

운동만큼 중요한 것은 먹는 것이다. 하지만 사실 먹는쪽으로는 크게 바꾼 것이 없다. 물론 작지만 중요한 변화는

있었다.

 

우선 과자류를 거의 안먹었다. 그리고 아침 식사는 주로 무가당 요거트 + 무설탕 시리얼이나 집에서 새순

샐러드와 두부를 싸가서 먹고, 삶은 계란 정도에 가끔 샌드위치를 먹었다.

 

점심은 가장 큰 변화를 주었는데 우선 다행인 것이 현재 일하고 있는 곳의 구내 식당에서는 점심 식사 때마다

생야채를 제공해주어서 원하는 만큼 먹을 수 있다는 것이다. 게다가 100% 현미밥도 나오는데 최근에는 아예

밥을 거의 안먹고 있다. 말하자면 생야채와 반찬만 먹는 것이다. 아래 사진은 실제 내가 먹는 점심이다.

 

첫 번째 사진은 비빔밥이 나왔던 날이라서 야채의 양이 조금 적은데 어쨌든 사진상의 밥이나 면 종류는 일체

먹지 않는다. 하지만 그밖의 반찬들 중 몸에 안좋을만한 것들은 딱히 거르지 않는다. 예를들면 치킨이라든지

튀김류, 사진상의 메밀전병 같은 것들은 양껏 먹는다. 말하자면 탄수화물만 최대한 배제를 하는 것인데

사실 반찬에도 탄수화물이 적지 않기 때문에 탄수화물을 완전히 배제하진 못한다.

 

말하자면 나름 건강과 입맛 사이에서 적당히 타협을 한 것이다.

 

그리고 저녁 식사는 그전과 다를 바가 없지만 일단 밥 양은 조금 줄였고 반찬은 온 가족의 건강을 생각해 최근에 야채와 생선 위주로 반잔을 준비해서 먹고 있따.

 

물론 가끔 특식도 먹는다. 생일이나 기념일에 먹는 케이크, 가끔 단 것이 너무 땡겨서 사먹는 크림빵, 밥 먹고

무심결에 손이가는 약간의 과자들…하지만 이런 음식들도 그 전에 비하면 엄청나게 양을 줄인 것이다.

대략 따져도 80% 이상은 줄인 듯싶다.

 

왼쪽 사진의 뻘건 것은 곤약비빔면 시커먼 것은 치킨강정. 오른쪽 사진 주요 반찬은 편육 무침과 메밀전병 대체로 이런 식단에서 밥과 면을 제외하고는 다 먹어치운다~

영양제 및 건강 보조 식품

 

원래 약발이 안받는 체질이라 사실 영양제같은 것을 먹는 걸 별로 좋아하지 않는데 일단 한번 먹어보기로 했다.

우선 간수치가 높은터라 간에 좋다는 헛개 추출물 영양제를 대략 한 달 먹었고, 비타민 C는 하루에 1500mg

정도를 지속적으로 복용하고 있다. 그리고 비타민 D 수치가 낮게 나와 비타민 D 1000iu를 이틀에 한 번 꼴로 

먹고 있고, 그밖에는 유산균 정도? 대략 이정도의 영양제를 먹었다.

 

결과

 

일단 작년 11월 27일 건강 검진을 받고 지난 3월 29일 재검 삼아 피검사를 받기 까지 대략 4개월동안 위에 

적은대로 운동과 식단을 유지를 했다.

 

우선 제일 큰 변화는 몸무게다. 건강 검진을 받을 당시의 몸무게가 대략 89Kg 정도였는데 4개월이 지난 후

몸무게는 약 79Kg으로 10kg 정도가 줄었다.

 

그리고 피검사 결과는 다음과 같다.

 

항목 2020년 11월 27일 결과  2021년 3월 29일 결과 정상 범위
비타민 D 15 36.9 30 ~ 100
감마GTP 175 70 16 ~ 73
총콜레스테롤 279 238 120 ~ 220
LDL 188 146 0 ~ 130
Trigliceride(중성지방) 148 199 50 ~ 130
공복 혈당 126 114 70 ~ 110

 

일단 가장 눈에 띄게 좋아진 것은 간 수치인 감마 GTP인데 얼만전 명의에서 간에 대해 나오는 것을 보니

간은 몸무게만 줄여도 상당히 좋아진다고 하더라. 그밖에는 큰 변화는 없지만 조금씩 좋아졌는데 중성지방이

오히려 높아졌다.

 

아마도 식단 관리를 좀 더 철저히 했더라면 이보다 훨씬 더 좋아지지 않았을까 생각한다. 하지만 맛있는 음식을

포기한다는 것이 어디 그리 쉬운 일인가…ㅠ.ㅠ

 

나는 예전부터 뭘하든 그냥 중간정도는 했다. 아주 빼어나게 잘하는 것도 없고 그렇다고 지지리 못하는 것도 

없고…그러니 건강도 그냥 이정도 무난하게 유지하고 먹고싶은 음식 적당히 먹어가면서 살면 되지 않을까^^;;

 

아무튼 운동은 여전히 열심히 하고 있으니까 도움은 되겠지~

 

정리

 

아주 힘들게 관리를 해야 하는 상황에 이르기 전에 미리 조심은 해야 겠지만 그렇다고 삶의 즐거운 순간들을 

무작정 날려버리고 싶진 않다. 하지만 그러려면 주기적으로 내몸의 상태를 잘 확인하는 일이 꼭 필요할 것 

같다. 지금 이 상태로도 크게 불편한 것은 없으니 당분간 지금의 생활을 유지하면서 가끔 피검사 받으면서

잘 체크를 해봐야겠다.

'일상사' 카테고리의 다른 글

적당히 건강한 정도로는 모자란가?  (0) 2021.04.17
때늦은 2020년 계획  (1) 2020.03.25
그네도 갔고~대청소나 해볼까?  (0) 2017.03.19
그저 한 발 앞으로...  (0) 2017.02.28
블로그 스킨 바꿨다~  (0) 2017.01.06
2016년 결산 및 2017년 계획  (0) 2017.01.01
반응형

늘상 그래왔듯이…내 머릿속에는 온갖 잡다한 관심과 호기심들이 종횡무진 날아다닌다.

덕분에 뭔가 하나를 진득하니 진행할 수가 없다…ㅠ.ㅠ

 

핸즈온 머신러닝 2판을 일기 시작한 것이 언제인지 기억도 안나고, 1장을 읽고 연습 문제 위주로 공부를

해보고자 하면서 1장의 연습문제를 정리해 블로그에 올린 것도 이미 2020년 11월 그러니까…4개월 

하고도 열흘이 지났다…남들 같았으면 책을 네댓 권은 마스터했을 시간이다…ㅠ.ㅠ

 

물론 그렇다고 논 것은 아니지만 이래서야 되겠는가 하는 자괴감이 든다…ㅠ.ㅠ

 

게다가 더더욱 놀라운 것은 나름 열심히 보느라고 2장은 3번 정도 반복해가면서 읽었는데도 불구하고…

연습문제를 풀려고 보니…뭔소린지 하나도 모르겠더라는…그냥 풀기가 어려운 정도가 아니고 아예

어디부터 시작을 해야 하는지를 모르겠는 황당한 상황…ㅠ.ㅠ

 

결국 그 이후 다시 수차례 훑어보고 나서야 2장에서 이야기하고자 하는 것이 무엇인지를 이해할 수 있었다.

그리고 그 전까지 이 부분을 제대로 이해하지 않고 그저 모델을 만들고 학습을 시키고 테스트를 하는 과정만

생각하고 있던 내가 얼마나 어리석었는지를 깨달았다…ㅠ.ㅠ (오늘의 글은 눈물바다로구나…ㅠ.ㅠ)

 

그래서 일단 2장의 내용을 간략하게 정리해두고 좀 더 기초로 돌아가서 데이터를 다루는 법, Python 및

관련 패키지들의 API에 대해 조금 더 기초를 다지기로 하였다.

 

더불어 핸즈온 머신러닝 2판 학습은 잠시 미뤄두고 우선 몇 권의 다른 책들을 먼저 읽어보기로 하였다.

아래는 올해 목표로 잡은 책들 목록이다.

 

  • 모두의 데이터 과학 with 파이썬
  • 파이썬을 활용한 머신러닝 쿡북
  • 머신러닝 탐구생활
  • 캐글 가이드

 

일단 이렇게 데이터 조작에 대해 조금 더 학습을 진행하고 다시 본격적으로 머신러닝에 대해 공부를 진행할

계획이다. 여기에 교재로 쓸 책은 다음과 같다.

 

  • 핸즈온 머신러닝 2판
  • 밑바닥부터 시작하는 딥러닝 1
  • 밑바닥부터 시작하는 딥러닝 2
  • 밑바닥부터 시작하는 딥러닝 3

 

일단 여기까지만 해도 올 한 해는 훌쩍 가버릴듯싶다.

 

그럼 일단 핸즈온 머신러닝 2판 2장의 내용을 간략하게 정리해보자~

 

머신러닝 프로젝트 진행 프로세스

 

  • 데이터 준비 : 다운로드 및 저장

. 어떤 데이터를 다운로드 받느냐에 따라 다르지만 대체로 웹에서 다운로드 받는 경우가 많을 것이며,

로컬에 저장된 파일로부터 읽어올 수도 있고, 또 머신러닝 관련 패키지에서 제공하는 경우들도 있다.

. 관련 라이브러리 및 API

import urllib
import ssl

# 아래 오류 벌생으로 ssl import
# URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)>
ssl._create_default_https_context = ssl._create_unverified_context
urllib.request

 

  • 적절한 데이터 타입으로 변환 (판다스의 DataFrame 등)

. 다운로드 받아 저장한 파일에 들어있는 데이터들은 실제 사용하기 위해 적절한 형식으로 바꾸어 주어야 

한다. numpy의 ndarray나 pandas의 DataFrame으로 바꾸면 데이터를 가공하기가 쉬워진다.

. 관련 라이브러리 및 API

 

import pandas as pd 

# csv 파일을 읽어 DataFrame 타입으로 리턴한다. 
pd.read_csv(csv_path)

 

  • 샘플 데이터를 통해 데이터셋의 상태 확인

. 누락된 데이터는 없는지?

. 각 특성의 데이터 타입 확인 (숫자형, 문자형, 범주형 등)

. 각 특성간의 스케일 차이 확인 (추후 스케일 조정 수행)

. 수치형 데이터의 분포 확인 (추후 가능한한 종모양의 분포로 조정)

. 관련 라이브러리 및 API

 

# housing은 DataFrame 타입의 객체이며 info() 함수를 실행하면 Non-Null Count 컬럼으로
# null 데이터가 있는지 여부를 확인할 수 있다. 또한 Dtype 컬럼으로 각 컬럼의 데이터 타입을
# 확인할 수 있다.
housing.info()

# 수치형 데이터의 경우 describe() 함수를 이용하여 각종 통계적 값을 확인할 수 있다.
housing.describe()

# matplotlib의 hist() 함수를 이용하여 히스토그램을 그리면 데이터의 형태를 시각적으로 
# 확인할 수 있다.
%matplotlib inline
import matplotlib.pyplot as plt
# Pandas DataFrame의 hist() 함수는  matplotlib.pyplot.hist()를 호출한다.
housing.hist(bins=50, figsize=(20,15)) 
plt.show()

 

  • 훈련 세트와 테스트 세트로 구분

. 모델을 결정하고 훈련을 하기 전에 미리 훈련 세트와 테스트 세트를 분리하여 테스트 세트는 완전히 샌드박스로 만든다. 

. 훈련 세트와 테스트 세트는 대략 80 : 20의 비율로 나눈다.

. 테스트 세트가 계속 변경되어 전체 데이터 세트가 모두 한 번씩 테스트 세트에 포함되는 것을 막아야 한다.

. 관련 라이브러리 및 API

 

from sklearn.model_selection import train_test_split

# scikit-learn의 train_test_split을 이용하여 훈련 세트와 테스트 세트를 나눈다. 
train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)

 

  • 데이터 샘플링

. 계층적 샘플링 : 모집단과 같은 분포를 갖도록 데이터 샘플링

. 너무 많은 계층으로 나뉘어서는 안되면 각 계층은 충분히 커야 함

. 훈련세트와 테스트 세트를 나눌 때는 이러한 계층적 샘플링이 되도록 나눔

 

from sklearn.model_selection import StratifiedShuffleSplit

# scikit-learn의 StratifiedShuffleSplit을 이용하여 계층적 샘플링을 수행한다.
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_index, test_index in split.split(housing, housing["income_cat"]):
    strat_train_set = housing.loc[train_index]
    strat_test_set = housing.loc[test_index]

 

  • 데이터 시각화

. 훈련 세트를 이용하여 데이터를 시각화 함으로써 데이터에 대해 조금 더 깊이 파악하는 과정

. 산점도를 이용하여 특성간의 상관관계 조사

. 이상 형태를 보이는 데이터(특성) 구간을 확인

. 특성들의 조합(상관관계 분석)을 통해 의미 있는 특성을 새로이 발견

. 관련 라이브러리 및 API

 

%matplotlib inline
import matplotlib.pyplot as plt

# 시각화를 위해서는 matplotlib 패키지를 잘 숙지하도록 하자!

# Pandas DataFrame의 corr() 함수를 이용하면 특성간의 상관관계를 확인할 수 있다.
corr_matrix = housing.corr()

 

  • 데이터 정제

. 학습을 하기 위한 데이터의 준비는 가능한한 자동화를 하는 것이 좋음

. 누락된 특성 값 처리 : 누락된 값이 있는 특성을 모두 버리거나, 값이 누락된 특성이 있는 샘플들을 모두 버리거나, 누락된 값을 대표값으로 채우기 (평균, 중간값 등). 누락된 특성에 대한 처리는 나중에 추가된 데이터에서 어떤 특성에서 누락된 값이 나올지 모르므로 모든 수치형 특성에 적용하는 것이 좋음.

. 범주형 특성 정리

. 특성 스케일링 : 특성들의 스케일이 유사하도록 조정한다. 목표값에 대한 스케일링은 불필요하다.

    > min-max 스케일링(정규화) : 데이터에서 최솟값을 뺀 후 최댓값과 최솟값의 차이로 나눔.

       0~1사이의 범위에 들도록 함.

       MinMaxScaler

    > 표준화 : 평균을 뺀 후 표준편차로 나누어 결과 분포의 분산이 1이 되도록 함.

       상한과 하한이 없어 어떤 알고리즘에서는 문제가 될 수 있음.

       이상치에 영향을 덜받음.

       StandardScaler

    > 스케일링은 훈련 세트에 대해서만 fit() 메서드를 적용해야 함. transform() 

     메서드는 훈련 및 테스트 세트 모두 적용.

. 관련 라이브러리 및 API

 

# 숫자형 특성들만을 대상으로 누락된 값을 각 컬럼의 특정 값으로 채움
from sklearn.impute import SimpleImputer 

# 범주형 문자열 데이터를 수치형으로 바꿈
from sklearn.preprocessing import OrdinalEncoder

# 범주형 문자열 데이터를 One-Hot_Encoding 형식으로 변환
from sklearn.preprocessing import OneHotEncoder

# 데이터를 표준화 시켜주는 변환기
from sklearn.preprocessing import StandardScaler

 

  • 데이터 샘플링을 통해 변경된 샘플들을 테스트 세트에 추가한다. 이러한 과정들을 추후 파이프라인에 넣을수 있도록 추정기 또는 변환기를 만든다.

. 관련 라이브러리 및 API

 

# fit() 함수와 transform() 함수를 구현하여 변환기를 만들 수 있다.
# TransformerMixin을 상속하면 fit_transform() 함수가 자동 생성된다.
# BaseEstimator를 상속하면 get_params() 함수와 set_params() 함수가
# 자동 생성된다.
from sklearn.base import BaseEstimator, TransformerMixin

 

  • 만들어진 추정기와 변환기를 파이프라인에 넣어 자동화 한다.

. scikit-learn의 PipeLime 이용

. 컬럼 단위로 파이프라인을 적용하고자 할 때는 scikit-learn의 ColumnTransformer를 이용

. 관련 라이브러리 및 API

 

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('addtibs_adder', CombinedAttributesAdder()),
    ('std_scaler', StandardScaler()),
])

housing_num_tr = num_pipeline.fit_transform(housing_num)

 

  • 최종적으로 만들어진 훈련 데이터 세트를 이용하여 훈련 진행
  • 훈련 결과에 따른 보정

. 과소적합의 경우 더 강력한 모델을 선택하거나 훈련 알고리즘에 더 좋은 특성을 주입하거나 모델의 규제를 감소

. 교차 검증을 사용한 평가

. 관련 라이브러리 및 API

 

# RMSE 측정
from sklearn.metrics import mean_squared_error

housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
lin_rmse

# 교차 검증 수행
from sklearn.model_selection import cross_val_score

scores = cross_val_score(tree_reg, housing_prepared, housing_labels, scoring="neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)

 

  • 모델 튜닝

. 그리드 서치 또는 랜덤 서치를 이용하여 하이퍼 파라미터 조정

from sklearn.model_selection import GridSearchCV
...
from sklearn.model_selection import RandomizedSearchCV

 

정리

 

서두에서도 말했듯이 현재의 나는 너무나 기초가 부족한 상황이다. 이 상태에서 진도를 나간다는 것은 말 

그대로 사상누각일 뿐…

 

현재 상황에서 내가 할 수 있는 일이라고는 머신러닝 공부를 중단하던가(사실 하고싶은 것들이 너무 많아

뭔가 하나를 포기해야 할 상황이긴 하다. 지금은 다른 것을 보류하고 잇는 상태지만 우선순위가 바뀌어도

크게 문제될 것은 없다). 아니면 부족한 기초… 즉, 파이썬 기초, 그리고 데이터를 다루는 법 등을 차근차근

배워나가는 것이다.

 

일단 밑도끝도 없이 인강도 많이 구입해놓았고 또 책들도 선정을 해놓았으니 올 한해는 기초를 다지는 것으로

목표를 삼아야겠다.

 

그래서 핸즈온 머신러닝은 당분간 봉인이다…ㅠ.ㅠ

 

 

반응형

애플은 제품은 참 마음에 드는데 하는 짓은 얄밉기 그지없다.

마이크로소프트같은 경우 아무리 새로운 윈도우가 나오더라도 구닥다리 컴퓨터에 설치는

되었다. 다만 느리다거나 중요 부품의 호환성에 문제가 있을지라도…

 

그런데 이놈에 애플은…폰이든 PC든 선을 딱 그어버린다…-.-

그동안 잘 써오던 2012, Late 맥미니는 더이상 상위 OS를 업데이트 할 수 없게 되었다.

메모리 16Gb, SSD 1Tb로 아직도 쌩쌩하게 잘 돌아가는데…최신 버전의 OS인 빅서를 사용할 수 없는 

것이다…ㅠ.ㅠ

 

사실 그냥 일반적인 용도로만 사용한다면 크게 문제가 되지 않는데…iOS를 개발하다 보면 개발툴인 

Xcode도 업그레이드를 해야 하는데 이 Xcode도 특정 OS 이상에서만 업그레이드가 되어 끝내 새로운 

Mac PC를 살수밖에 없다…

 

결국 가성비가 가장 좋은 Mac mini를 구입했고 요즘 핫한 M1 프로세서가 붙은 놈으로 구입했다.

 

 

역시 애플답게 아주 깔끔하다. 정말 구성품이 몇 개 되지도 않는데 이렇게 꽉찬 느낌을 주도록 포장하는 것도

애플의 주된 장기 중 하나다…-.- 실질적인 제품이라고는 본체, 전원 케이블 하나씩일 뿐인데…이토록 풍성해

보인다니…-.-

 

M1 칩의 가장 큰 특징 중 하나는 뭐니뭐니해도 ML용 16코어 뉴럴 엔진이 포함되었다는 점일 것이다. 해서 

아마도 M1 맥미니를 구입한 대부분의 사용자가 머신러닝 혹은 딥러닝에 대해 알든 모르든 Tensorflow를 

설치해보려 할 것이다. 나역시 마찬가지이고…

 

그래서 그런지 M1 Mac mini를 검색해보면 온통 ML 수행에 대한 벤치마킹 정보와 Tensorflow 설치 방법에

대한 내용들이다. 그럼에도 불구하고 메인프로세서의 아키텍처가 바뀜으로 인해 아직은 많은 시행착오가 있는 

것 같다.

 

그래도 비교적 쉽게 설치를 했기에 그 과정을 간단하게 정리해본다.

 

주의 : M1 칩의 네이티브 환경에서 작업을 하고자 한다면 터미널 실행 시 터미널의 정보 가져오기 팝업 창에서

Rosetta로 실행하기 항목의 체크박스를 꺼야 한다. 이 옵션을 키게 되면 네이티브환경이 아닌 intel 기반 

실행을 위한 Rosetta2 환경에서 실행된다.

 

 

첫 번째 시행착오

 

사실 나는 Colab을 사용할 예정이고 Colab Pro까지 고려를 하고 있기 때문에 굳이 로컬 머신에 ML 환경을

구축할 필요는 없었다. 다만 개발자라면 흔히 갖게되는 특유의 호기심으로 이것저것 설치를 해보게 되었다.

 

시작은 당연히 Python이다. 

그런데…애플 M1용 Tensorflow가 Python 3.8에서만 작동을 한다는 사실을 모르고 덜컥 3.9.1을

설치해버렸다. 이미 설치한 Python을 삭제하는 과정이 여간 번거로운 것이 아니라서 Python 가상 환경에서

다시 시작해보기로 했다.

 

기존에도 Virtualenv나 Anaconda같은 환경은 잘 쓰지 않았다. 아무래도 Python을 쓸 일도 많지 않았고

게다가 혼자 작업을 하다보니 굳이 번거롭게 가상 환경을 이용할 필요가 없었던 것이다. 물론 귀찮기도 했고…

하지만 이번에 사용해보니 정말로 편하고 패키지 설치 등에 도움이 많이 되었다.

 

두 번째 시행착오

 

가상 환경은 그나마 익숙했던 Virtualenv를 선택했다. 그런데 이 것이 또 한 번의 실수였다. 이 환경에서는

패키지를 pip로 설치를 하게 되는데 ML의 핵심적인 패키지인 scikit-learn이 제대로 설치되지 않았다.

관련 패키지인 scipy 역시 설치되지 않았다.

 

Python을 이용한 데이터 분석이나 ML 관련 책의 대부분이 scikit-learn을 사용하고 있기 때문에 필수로

설치해야 하는 패키지인데 설치가 되지 않으니 답답했다.

 

ML 환경 구성하기

 

그러다가 ML 관련 Python 라이브러리 패키지 대부분이 Anaconda 배포한 중 하나인 minforge에서는

모두 네이티브 버전으로 설치가 된다는 내용을 알게 되었다. 그리고 결정적으로 ML 환경 구성에 대한 내용이

가장 심플하게 정리된 아래 사이트를 찾았다.

 

TensorFlow 2.4 on Apple Silicon M1 : installation under Conda environment | LaptrinhX

 

우선 miniforge를 설치한 후 기본적인 패키지 설치는 아래 4줄로 모두 끝난다.

 

miniforge 설치 : brew install miniforge


conda create —name tf24

conda activate tf24

conda install -y python==3.8.6

conda install -y pandas matplotlib scikit-learn jupyterlab

 

여기까지 설치하면 conda 가상환경에서 jupyter lab을 실행하여 핸즈온 머신러닝 2판의 예제들이 잘

실행되는 것을 확인할 수 있다.

 

Tensorflow 설치하기

 

이제 드디어 대망의 Tensorflow 설치다.

위에 링크한 사이트에서는 4번에 걸쳐 pip install을 수행한다. 그런데 M1용 Tensorflow github

가면 아래 한줄로 Tensorflow 설치가 가능하다고 나온다.

 

/bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/apple/tensorflow_macos/master/scripts/download_and_install.sh)”

 

간단하게 위의 명령줄을 복붙해서 실행하였고 다행이 설치가 잘 끝났다. Jupyter lab에서 MNIST 예제를

돌리니 잘 실행되었다. 이제 다 끝인가 했지만…

 

다시 핸즈온 머신러닝2판의 예제를 돌려보니 잘 실행이 되다가 SimpleImputer의 fit() 함수를 실행하는 순간

Jupyter lab의 커널이 죽어서 다시 실행한다는 메시지가 출력되었다.

 

혹시나 설치 과정에서 뭔가 잘못되었을까 하고 가상 환경을 몇번을 날리고 다시 처음부터 설치해봐도 마지막에

동일한 위치에서 항상 커널이 죽었다. 그러다가 문득 Tensorflow를 설치하기 전까지는 이상이 없는데 설치

후에 문제가 발생하는 것을 알아챘다.

 

설치 방법이 정리된 사이트를 다시 찬찬히 살펴보았다. 그러다가 눈에 띄는 내용이 보였다. conda install을 

통해 pandas를 설치할 때 의존성 패키지로 이미 numpy가 설치 되었는데 위 사이트의 Tensorflow 설치

명령 4개 중 두 번째에 다른 버전의 numpy를 설치하는 것을 볼 수 있었다.

 

# Install all the packages provided by Apple but TensorFlow

pip install —upgrade —no-dependencies —force numpy-1.18.5-cp38-cp38-macosx_11_0_arm64.whl grpcio-1.33.2-cp38-cp38-macosx11_0arm64.whl h5py-2.10.0-cp38-cp38-macosx11_0arm64.whl tensorflowaddons-0.11.2+mlcompute-cp38-cp38-macosx_11_0arm64.whl

 

공식 사이트에 있던 설치 명령으로는 이 모든 것이 다 설치가 되니 4개의 명령으로 각각 설치를 진행해보기로

했다. 그러려면 아래 주소에서 패키지 파일들을 먼저 다운로드 해야 한다.

 

https://github.com/apple/tensorflow_macos/releases

 

가장 위의 블럭에 하단에 보면 Assets라는 링크가 있는데 클릭해보면 다운로드 가능한 파일 목록이 펼쳐진다.

총 7개가 있는데 그 중에 5번째 있는  tensorflow_macos-0.1alpha2.tar.gz 파일을 다운로드 받아

압축을 풀면 필요한 파일들이 모두 들어있다.

 

이제 압축을 푼 위치에서 4줄의 명령어를 차례로 실행해주면 된다. 단 두 번째 명령에서는 numpy 항목을 

빼고 실행해준다. 설치과정에 오류가 발생을 하는데 아직까지는 큰 문제는 없는 것 같다(영상을 찍으면서

다시 설치해보니 별다른 오류가 없다).

 

이렇게 설치하고 나면 드디어 Tensorflow와 scimitar-learn이 모두 정상적으로 작동을 한다.

 

영상

전체 설치 과정을 영상으로 찍어보았다.

 

 

정리

 

그래도 내 수준에 비하면 그리 어렵지 않게 설치를 마무리 하였다. 하지만 돼지목에 진주라고나 할까…

아직 Tensorflow를 제대로 다룰 줄도 모르니 뭐…샘플 코드를 돌려보긴 했지만 이게 CPU로 실행되는지

GPU로 실행되는지도 아직 잘 모르는 상태다…ㅠ.ㅠ

 

그래도 이제 공부를 시작했으니 언젠가는 알게 될 것이고 또 M1 칩의 아키텍처에 맞는 배포본들도 계속

나오게 되면 보다 수월하게 공부를 할 수 있지 않을까 싶다.

 

반응형

도로헤도로

 

공통 점수

스토리 : ★★★★★

연출 : ★★★★★

작화 : ★★★★★

 

특별 점수

병맛 : ★★★★★

고어 : ★★★

 

어느날 살해 당한 후 도마뱀 머리를 한 채 깨어난 카이만과 최강의 마법사이지만 어떤 이유에선지 정체를 

숨기고 평범한 인간인 양 살아가는 니카이도가 카이만을 죽이고 도마뱀 머리로 만든 마법사를 찾아 

좌충우돌하는 병맛 충만 액션 하드고어 스릴러~

 

세상은 마법사가 사는 세계와 평범한 인간이 사는 세계로 나뉘어 있고 마법사들은 문을 만들어 인간 세계로

가서 인간들을 대상으로 마법 연습을 한다. 한마디로 인간들은 호구 모르모트…

 

범인을 찾기 위한 과정에서의 등장 인물, 사건, 액션들이 매우 흥미진진함~

특히나 하나같이 병맛 발랄한 캐릭터들을 보는 재미가 쏠쏠~

고어는 뭐…캐릭터 얼굴 가죽이 벗겨지거나 중요 인물의 마법 능력이 사람을 산채로 토막내는 것 정도가 

있는데 표현을 단순하게 해서 그리 그로테스크하지는 않음

 

최근 십 수년간 본 애니 중에 가장 재밌게 봤음

 


바이올렛 에버가든

 

공통 점수

스토리 : ★★★★☆

연출 : ★★★☆

작화 : ★★★★★

 

특별 점수

병맛 : ★★

감성자극 : ★★★★

 

워낙에 명작으로 이름난 애니지만 나는 쉽게 접근하지 못했음.

일단 초반 진행이 지루해서 1화 보고서 킵 했다가 거의 1년이 다되서 다시 보기 시작한 후 급속 정주행…

 

작화가 너무 깔끔하고 예쁜 것이 가장 마음에 드는 애니.

 

감정이 없는 전쟁 병기로 자란 소녀가 자신을 돌봐주던 소령의 마지막 한마디…’사랑해’ 라는 말의 의미를

알기 위해 자동 수기 인형(편지 대필 서비스의 대필 작가)으로 일을 하면서 딸을 잃은 아버지, 어린 자식을

홀로 두고 죽어야 하는 어머니, 전장에서 죽어가는 병사의 사연들을 접하며 인간의 감정을 알아간다는 

이야기…

 

각각의 사연들은 정말 뻔한 신파인줄 알면서도 코끝이 짱해지는 감동을 줌.

 

그런데 이렇게 예쁜 그림체에 감성 충만한 애니에 왜 병맛 2점이 들어갔느냐…

아무리 만화지만 초등생 정도의 여리여리한 소녀가 절대 무적의 전쟁 병기라는게 도저히 납득이 안감…

그리고 후반부로 갈수록 주인공(바이올렛 에버가든)이 쓰는 편지는 사람들의 심금을 울리는데 여전히

표정은 ‘감정? 먹는거야?’라는…물론 점차 눈물이 많아지긴 하지만…

 

암튼 재밌지만 자칫 지루해질 수 있는 애니~ 

 


기생수

 

공통 점수

스토리 : ★★★★★

연출 : ★★★★

작화 : ★★★☆

 

특별 점수

트렌드 : ★★★★★

고어 : ★★★★

 

요즘같은 코로나 시기에 꼭 봐야 하는 만화

사실 원작은 꽤 오래된 만화(나무위키 참조 1990년 연재 시작)…언제인지 기억은 안나지만 만화책으로는

모두 읽었던 내용…그런데 너무 오래되서 대충대충 스토리가 기억은 나는데 결말이 기억이 안남…-.-

 

기원을 모르는 정체불명의 기생 생명체가 인간을 숙주로 삼기 시작함. 뇌를 지배하게 되면 사람은 죽고 

기생수가 사람의 육체를 지배하며 몸을 자유자재로 변형하는 강력한 살상 무기가 됨.

 

일부 기생수들은 뇌를 지배하지 못하고 신체의 일부나 동물에게 기생하게 됨. 주인공의 경우 오른손에

기생하게 되고 기생이 아닌 공생 관계가 되어 난관을 헤쳐나가는 이야기.

 

그림체는 그닥…그리다 만 것 같기도 하고…

 

감염된 인간이 변하는 모습이나 그에 당하는 인간 상황이 조금 고어함.

그림체나 주인공의 상황 등이 조금 병맛스럽기는 하지만 현재 코로나로 인한 세상 꼬라지가 더 병맛 같으므로

병맛 점수는 안줬음.

 

결국 수많은 악질 중에 최고의 악질은 인간이라는 교훈…

하지만 1990년에 처음 발간된 만화이면서도 인간에게 해악을 끼치지만 엄연히 ‘존재’하는 것들과 어떻게 

공생해야 할지에 대한 의문을 제기한다는데 있어서 현 시점에서 시사하는 바가 큼.

 

 

반응형

이제부터는 본격적으로 Firmata를 분석해보고 사용해보도록 하자.

나의 개인적인 취향 상 분석을 먼저 면밀하게 한 후 사용을 하는 것 보다는 실제 동작하는 모습을

보면서 연관된 코드를 뜯어보는 것이 수월하기에 이번 포스팅 역시 그러한 방식으로 진행을 하겠다.

 

Firmata의 전체적인 구성은 호스트 PC 쪽의 Firmata Client와 아두이노쪽의 Firmata 스케치로 구성되어

있다. 물론 아두이노쪽에서 범용 Firmata 스케치가 아닌 Firmata 라이브러리를 사용한다면 구성이 조금

달라지겠지만 이 시리즈에서는 범용 Firmata 스케치를 사용한다는 전제로 포스팅을 하고 있다.

 

이러한 전제 하에 지난 번 포스팅의 가장 마지막에 실행했던 digital_output.py 소스를 가지고 간단하게

Firmata의 흐름과 관련 소스를 살펴보도록 하겠다.

 

다만 모든 소스를 세세하게 분석하는데는 많은 시간과 지식이 필요하므로 이번 포스팅에서는 우선 프로토콜이

어떻게 구현되는 지에 초점을 맞춰 살펴보도록 하자.

 

Firmata Client - pymata4

 

이전 포스팅에서도 언급한 바와 같이 Firmata Client는 다양한 언어로 구현이 가능하다. 그리고 이 시리즈

에서는 Python으로 된 Client를 사용하고 있으며 그 중에서도 자료가 가장 잘 정리되어있는 pymata4를

대상으로 한다.

 

pymata4의 핵심 소스는 3개의 파일로 구성이 되어있다.

 

  • pin_data.py : 아두이노의 pin mode를 설정하기 위한 각종 속성이 정의되어 있다.

  • private_constants.py : Firmata 프로토콜을 정의하는 여러가지 상수가 정의되어 있다.

  • pymata4.py : 가장 핵심적인 소스로 사용자들인 호출하여 사용할 API들이 구현되어있다.

 

단순히 Firmata를 이용하기 위해서는 pymata4.py에 있는 API를 어떻게 호출하는 지만 알면 된다. 이제

예제 코드인 digital_output.py로부터 시작하여 차근차근 알아보자.

 

digital_output.py 코드는 매우 단순하다 (코드에 집중하기 위해 원래 있던 주석은 모두 삭제하였다).

사전 이해를 위해 간단하게 코드에 주석을 붙였다. 

import sys
import time

from pymata4 import pymata4

# 사용할 디지털 핀 번호 설정. 기본 예제 코드에서는 6번을 사용한다.
DIGITAL_PIN = 6  # arduino pin number

# blink라는 함수를 구현하였다. 실제로 Firmata를 구동시키는 함수이다.
def blink(my_board, pin):
    # 가장 먼저 PIN 모드를 설정한다. 파라미터로 전달받은 핀(6번 핀)을 출력 모드로 설정한다. 
    my_board.set_pin_mode_digital_output(pin)

    # 1초 간격으로 6번 핀에 HIGH(1), LOW(0) 신호를 4회 반복하여 보낸다.
    # 이 6번 핀에 LED를 연결하여 1초 간격으로 LED가 켜지고 꺼지는 것을 4회 반복한다.
    # 직전 포스팅의 마지막 영상 참조.
    for x in range(4):
        print('ON')
	# 아두이노 보드의 6번 핀에 HIGH(1) 신호를 보낸다. LED가 연결된 경우 LED가 켜진다.
        my_board.digital_write(pin, 1)
        time.sleep(1)
        print('OFF')
	# 아두이노 보드의 6번 핀에 LOW(0) 신호를 보낸다. LED가 연결된 경우 LED가 꺼진다.
        my_board.digital_write(pin, 0)
        time.sleep(1)
    # 아두이노와의 연결을 끊는다.
    my_board.shutdown()

# 아두이노 보드의 인스턴스를 생성한다.
board = pymata4.Pymata4()
try:
    # blink 함수를 호출한다. 위에서 생성된 아두이노 보드 인스턴스와 사용할 핀 번호를 
    # 파라미터로 전달한다.
    blink(board, DIGITAL_PIN)
except KeyboardInterrupt:
    board.shutdown()
    sys.exit(0)

 

이제 위의 코드를 차근차근 살펴보자.


보드(아두이노) 인스턴스 생성하기

pymata4의 편리한 점 중 하나는 아두이노를 자동으로 찾아준다는 것이다. 아두이노와 호스트 PC간에 

정상적으로 연결만 되어있으면 단지 생성자 함수인 Pymata4()를 호출하는 것만으로 자동으로 

아두이노 보드를 찾아준다.

 

보드를 찾는 과정은 다음과 같은 로그로 확인할 수 있다.

 


/Volumes/Storage2/Firmata/FirmataTest/venv/bin/python /Volumes/Storage2/Firmata/FirmataTest/digital_write.py

pymata4: Version 1.10

 

Copyright (c) 2020 Alan Yorinks All Rights Reserved.

 

Opening all potential serial ports...

/dev/cu.wchusbserial1a1230

 

Waiting 4 seconds(arduino_wait) for Arduino devices to reset...

 

Searching for an Arduino configured with an arduino_instance = 1

Arduino compatible device found and connected to /dev/cu.wchusbserial1a1230

 

Retrieving Arduino Firmware ID...

Arduino Firmware ID: 1.1 FirmataExpress.ino

 

Retrieving analog map...

Auto-discovery complete. Found 22 Digital Pins and 8 Analog Pins


 

물론 명시적으로 필요한 파라미터를 전달하여 보드의 인스턴스를 생성할 수도 있다. 전달 가능한 파라미터는

다음과 같다(= 기호의 좌측은 파라미터 이름, 우측은 파라미터의 기본 값이다. Python은 파라미터 이름을 

사용하면 파라미터 순서와 관계없이 파라미터를 전달할 수 있으며 파라미터를 전달하지 않으면 = 우측의

기본 값이 사용된다).

 

  • com_port=None : 아두이노와 연결된 호스트PC의 포트. 위의 예에서는 /dev/cu.wchusbserial1a1230이다(매킨토시 PC에서 연결한 경우임).

  • baud_rate=115200 : 시리얼 통신 전송 속도

  • arduino_instance_id=1 : 아두이노 보드의 인스턴스 ID

  • arduino_wait=4 : 아두이노 리셋까지의 대기 시간

  • sleep_tune=0.000001 : 튜닝을 위한 파라미터로 일반적으로 수정하지 않는 것이 좋다.

  • shutdown_on_exception=True : RuntimeError Exception이나 KeyboardInterrupt exception이 발생한 경우 shutdown 함수를 호출할지의 여부

  • ip_address=None : StandardFirmataWifi 스케치를 사용하는 경우 Wi-Fi 기기의 IP 주소

  • ip_port=None : StandardFirmataWifi 스케치를 사용하는 경우 Wi-Fi 기기의 포트 번호. 보통 3030 사용

 

이와 같은 많은 파라미터들이 있으나 아무런 파라미터를 전달하지 않더라도 pymata4가 자동으로 연결된 

보드를 찾아 주는 것이다.

 

이 생성자 함수는 pymata4에서 사용할 전역 변수들을 초기화 하고 실제로 보드가 연결된 시리얼 포트를

찾는 것까지 상당히 긴 코드로 구현이 되어있어 자세한 설명은 생략하도록 하겠다. 다만 특별한 경우가 

아니라면  board = pymata4.Pymata4() 코드 한 줄로 아두이노를 연결하여 사용할 수 있다는 것만

알아두도록 하자.


blink 함수 분석 - 핀 모드 설정

Firmata를 이용하여 호스트 PC에서 아두이노의 핀을 이용하기 위해서는 먼저 아두이노 핀 모드를 설정해

주어야 한다. 그래서 가장 먼저 호출되는 API가 my_board.set_pin_mode_digital_output(pin)

이다. API 함수 이름으로 짐작할 수 있듯이 파라미터로 전달되는 pin(여기서는 6번 핀)을 디지털 출력으로 

설정하겠다는 의미이다. 그 과정을 조금 더 자세하게 살펴보자.

 

pymata4.py에서 set_pin_mode_digital_output 함수는 매우 단순하게 구현되어있다. 단지 전달

받은 파라미터인 pin에 private_constants.py에 정의된 상수인 OUPUT을 파라미터로 추가하여 private

함수인 _set_pin_mode 함수를 호출하는 것이 다이다. 전체 코드는 아래와 같다(원래의 주석은 삭제

했다).

 

def set_pin_mode_digital_output(self, pin_number):
        self._set_pin_mode(pin_number, PrivateConstants.OUTPUT)

 

_set_pin_mode 함수는 공통 함수이기 때문에 좀 더 복잡하게 구현이 되어있다. 하지만 우리는 Digital 

핀을 OUTPUT으로 사용할 것이므로 관련 부분만 집중해서 보도록 하자.

 

우선 전체 코드는 다음과 같다. 원래의 주석은 삭제를 하고 간단게 관련된 부분에만 별도의 주석을 달았다.

 

# Python에서 class의 멤버 함수들은 반드시 첫 번째 파라미터가 self여야 한다.
# 하지만 함수를 호출할 때는 self는 생략한다. 따라서 앞서 set_pin_mode_digital_output
# 함수에서 전달한 파라미터는 pin_number와 pin_state 2개이다. 나머지 2개의 파라미터는
# 전달받지 않았으므로 기본 값이 사용된다. 즉, callback은 None, differential은 1이다.
    def _set_pin_mode(self, pin_number, pin_state, callback=None,
                      differential=1):
# callback 파라미터는 전달받지 않았고 따라서 기본 값인 None을 사용하므로 아래 if문은
# 실행되지 않는다(None은 다른 언어의 null로 생각하면 된다).
        if callback:
            if pin_state == PrivateConstants.INPUT:
                self.digital_pins[pin_number].cb = callback
            elif pin_state == PrivateConstants.PULLUP:
                self.digital_pins[pin_number].cb = callback
                self.digital_pins[pin_number].pull_up = True
            elif pin_state == PrivateConstants.ANALOG:
                self.analog_pins[pin_number].cb = callback
                self.analog_pins[pin_number].differential = differential
            else:
                print('{} {}'.format('set_pin_mode: callback ignored for '
                                     'pin state:', pin_state))
#################################################################

# pin_state는 PrivateConstants.OUTPUT 값을 전달받았으므로 Pin_mode 역시
# PrivateConstants.OUTPUT 이다.
        pin_mode = pin_state

# pin_mode가 PrivateConstants.OUTPUT 이므로 아래 if문도 실행되지 않는다.
        if pin_mode == PrivateConstants.ANALOG:
            pin_number = pin_number + self.first_analog_pin
#################################################################

# _send_command 함수를 호출하여 아두이노로 통신하기 전에 마지막으로 Firmata 
# 프로토콜을 구현한다.
        command = [PrivateConstants.SET_PIN_MODE, pin_number, pin_mode]
        self._send_command(command)

# pin_mode가 PrivateConstants.OUTPUT 이므로 아래 if에서는 else절로 들어가
# 아무것도 실행하지 않고 끝낸다.
        if pin_state == PrivateConstants.INPUT or pin_state == PrivateConstants.PULLUP:
            self.enable_digital_reporting(pin_number)
        else:
            pass

 

 

위 소스 코드를 보면 대부분의 코드들은 파라미터 조건에 의해 실행되지 않거나 별다른 실행 없이 넘어가고

가장 핵심적인 부분인 Firmata 프로토콜을 구성하여 아두이노로 보내는 2줄만이 실행된다.

 

command = [PrivateConstants.SET_PIN_MODE, pin_number, pin_mode]
self._send_command(command)

 

Firmata 프로토콜 정의 문서(protocol/protocol.md at master · firmata/protocol · GitHub)

에서 보면 Message Type에 set pin mode(I/O) 라는 항목이 있고 이 항목은 다음과 같이 구성된다.

 

command MIDI channel
first byte second byte
0xF4   pin # (0~127) pin mode

 

 

그럼 이제 private_constants.py 파일을 열어 이 과정에서 사용된 2개의 상수인 OUTPUT과  SET_PIN_MODE

어떻게 정의되어 있는지 살펴보자.

 

SET_PIN_MODE = 0xF4  # set a pin to INPUT/OUTPUT/PWM/etc
...
OUTPUT = 0x01  # pin set as output

 

프로토콜로 정의된 것과 동일하게 command에 해당하는 SET_PIN_MODE0xF4 라는 값이 설정되어

있다. 나머지 2개의 파라미터는 범위 내에서 유동적으로 지정할 수 있으며 second byte에 해당하는 

OUTPUT은 카테고리 성격으로 자주 사용되는 값이므로 별도로 상수로 지정해 놓은 것이다.

 

마지막 단계의 _send_command함수도 단순한데, 전달받은 파라미터(프로토콜 포맷)를 byte 배열로 

바꾸어 serial port에 write(전송)하는 것이 끝이다. 전체 코드는 다음과 같다.

 

def _send_command(self, command):
        # 전달받은 파라미터(Firmata의 프로토콜 규격에 맞춘 데이터)를 바이트 배열로 바꾼다.
        send_message = bytes(command)

	# ip_address 전역변수가 지정되지 않은 경우 if 절 내의 내용을 실행한다.
        # 앞서 pymata4의 생성자 파라미터 설명에서 보았듯이 ip_address는 
        # StandardFirmataWifi라는 스케치에서만 사용되므로 여기서는 지정되지 않아
        # if 절이 실행되는 것이다.
        if not self.ip_address:
            try:
		# serial port에 write한다.
                result = self.serial_port.write(send_message)
            except SerialException:
                if self.shutdown_on_exception:
                    self.shutdown()
                raise RuntimeError('write fail in _send_command')
            return result
        else:
            self.sock.sendall(send_message)

 

정리

 

코드와 함께 정리하다보니 포스팅이 너무 길어진데다가 blink 함수에서 호출되는 digital_write API는 조금

복잡한 내용을 담고 있어서 다음 포스팅으로 넘기는 것이 좋을 것 같다.

 

다시 한번 강조하지만 전체 소스를 세세하게 파헤치는 것이 목표가 아니라 Firmata라는 프로토콜과 관련

라이브러리들이 어떤 흐름을 가지고 작동하는지를 아는 것이 목적인 만큼 관련 부분만 주목해서 파악하면

될 것 같다. 하지만 소프트웨어라는 것이 어찌보면 상당히 유기적이기도 한 만큼 생략으로 인해 혼란 스러운

부분도 많을 것이다. 이러한 부분들은 추후 기회를 봐서 더 상세히 다뤄보도록 하겠다.

 

그럼 다음 포스팅에서 digital_write API에 대한 내용으로 이어가겠다.

 

반응형

 

Firmata는 2가지 방식으로 사용이 가능하다.

 

그 한 가지 방법은 아두이노의 스케치에서 Firmata 라이브러리를 include한 후 라이브러리의 API를

활용하는방법이고, 다른 한 가지는 아두이노에는 범용 스케치를 업로드하고 모든 코딩을 클라이언트

쪽에서 하는 방법이다.

 

우선 두 번째 방법인 범용 Firmata 스케치를 아두이노에 업로드한 후 클라이언트에서만 코딩을 하는 방법을

알아보도록 하겠다. 이 방법은 아두이노 스케치의 C 프로그래밍에 익숙하지 않은 개발자들이 클라이언트

(호스트 PC)에서 본인에게 익숙한 언어로 개발을 할 수 있다는 장점이 있다.

 

본격적으로 Firmata의 소스 코드를 알아보기 전에 우선 간단하게 개발 환경을 먼저 정리하고 진행하고자

한다. 다만 이 글에서는 매킨토시 환경 하에서 Python Client를 선택하여 진행하는 만큼 Windows 사용자나

Python이 아닌 다른 언어를 사용하시는 분들은 다른 곳을 참조하셔서 환경을 구성하는 것이 좋을 것 같다.

 

환경 구성하기1 - 아두이노에 FirmataExpress 설치하기

 

Firmata 기반의 개발을 하기 위해서는 클라이언트(호스트 PC)에서는 Firmata Client 라이브러리를 설치

하여야 하며 아두이노에는 범용 Firmata 스케치를 업로드하는 것으로 끝난다.

 

누누이 말하듯이 Firmata Client 라이브러리는 다양한 언어로 구현이 되어있다. 각자에게 익숙한 언어로 된

라이브러리를 선택하면 되지만 역시 가장 심플하게 구현되어있는 것은 Python으로 구현된 라이브러리이다.

나역시 Java와 iOS의 Obj-c가 주로 사용하는 개발 언어이지만 코드를 분석하고 구현하는데는 오히려

Python이 더 접근하기 쉬웠고 소스 파일 구성도 매우 단순하여 부담이 없었다.

 

일반적으로 Python 라이브러리 중에는 pyFirmata, 아두이노 범용 스케치로는 StandardFirmata를 많이 

이용하는데 나는 자료가 좀 더 상세하게 정리되어있는 pymata4와 여기에 더 적합하다는 FirmataExpress를

사용하였다.

 

아두이노에서 기본적으로 제공하는 범용 Firmat 스케치 예제들이다.

 

사용하게 될 FirmataExpress는 기본 예제에 포함되어있지 않으므로 아두이노 스케치 IDE의 라이브러리 

관리 메뉴로 들어가 검색한 후 설치해야 한다(나는 이미 설치한 후라서 Installed로 표시되고 있다).

 

1. 툴 > 라이브러리 관리... 메뉴를 선택한다.

 

 

2. 라이브러리 매니저 창에서 Firmata로 검색을 한 후 FirmataExpress를 찾아 설치를 진행한다.

 

 

3. 설치가 완료되면 파일 > 예제 > 사용자 지정 라이브러리의 예제 항목에서 FirmataExpress를 찾을 수 있다.

 

 

라이브러리가 설치된 후 파일 > 예제 > 사용자 지정 라이브러리의 예제 항목에서 FirmataExpress를 찾아

열고 아두이노에 업로드하면 아두이쪽의 준비는 끝이다.

 

환경 구성하기 2 - Python 개발환경 구성하기

 

다음은 클라이언트 쪽인데…일단 Python의 설치 및 환경설정에 대한 내용은 그 자체만으로 한 번의 포스팅으로

끝날 내용이 아니므로 여기서는 생략을 하겠다. 일단 PC에 Python이 설치되어 있다는 전제하에 진행을 하겠다.

이 부분이 어려운 경우 앞서 말한대로 각자에게 익숙한 언어로 구현된 라이브러리를 이용하면 된다.

 

일단 나는 PyCharm을 이용하여 학습을 진행하였다. PyCharm에서 Virtualenv로 프로젝트를 생성하여 코딩

하는 법에 대해서만 간략하게 설명하도록 하겠다 (현재 맥미니를 사용 중이라 매킨토시 기준으로 작성한다).

 

1. Pycharm의 File 메뉴를 선택한 후 New Project를 선택한다.

 

2. Create Project 창에서 제일 처음 Location은 그냥 두고 Project Interpriter… 항목에서 New environment using Virtualenv를 선택한다. Location 항목에 프로젝트를 생성할 경로를 입력하고 Base Interpreter는 시스템에 설치된 Python 중 하나를 선택한다.

 

3. 프로젝트를 생성할 시의 옵션으로 기존 프로젝트에 붙여넣을지, 새 창으로 열지, 현재 윈도우에서 열지를 물어보는 창. New Window로 선택하면 무난함.

 

4. 프로젝트가 생성되면 아래와 같이 창이 열린다.

 

5. Firmata를 사용하기 위해 필요한 라이브러리를 추가하기 위해 Preferences... 메뉴를 연다.

 

6. Project <프로젝트 이름> 항목을 선택한 후 Project Interpreter를 선택한다. 기본으로 설치된 pip와 setup tool 라이브러리가 보인다. 필요한 라이브러리를 추가하기 위해 하단 좌측의 + 버튼을 클릭한다.

 

7. + 버튼을 누르면 열리는 Available Packages 창에서 pymata4로 검색을 한다. 검색된 목록에서 pymata4를 선택하고 좌측 하단의 Install Package 버튼을 클릭하여 설치한다. 설치 시 의존성에 필요한 패키지를 모두 설치한다.

 

8. 설치를 하고 난 후 아래 화면과 같이 pymata4와 pyserial 2개의 패키지가 추가로 설치된 것을 확인할 수 있다. Firmata가 기본적으로 Serial 통신을 하기 때문에 의존 패키지로 pyserial이 함께 설치된다.

 

9. 이제 다시 프로젝트 화면으로 돌아가 프로젝트 이름에 마우스 우클릭을 하여 New > Python File을 선택하여 소스 코드를 입력할 Python 파일을 만든다.

 

10. 파일명을 입력하고 OK 버튼을 클릭하여 파일을 생성한다.

 

11. 일단 빠른 테스트를 위해 생성된 Python 파일에는 pymata4의 예제 중 digital_output.py 파일을 그대로 카피하여 붙여넣기 하였다.

 

12. 코딩된 Python 파일을 실행하기 위하여 Run 메뉴의 Run…항목을 클릭한다.

 

13. 코드가 실행되면서 아래의 영상과 같이 LED에 1초 간격으로 4번 불이 들어오고 프로그램이 종료된다. 하단의 Run 창에는 아래 화면과 같이 로그가 찍힌다. Auto-discovery complete. Found 22 Digital Pins and 8 Analog Pins까지는 pymata4 라이브러리에서 찍는 로그로 아두이노가 연결된 serial 포트를 찾고 아두이노 및 아두이노에 업로드된 Firmata에 대한 정보를 가져오는 내용이 출력된다.



 

 

정리

 

오늘은 간단하게 개발 환경 구성과 간단한 예제를 하나 돌려보았다.

 

본문에서 설명한 것과 같이 아두이노는 FirmataExpress 스케치를 업로드한 이후 더이상 할 것이 없다. 

이제부터 모든 아두이노 제어는 호스트 PC에서 Python(물론 지원하는 타 언어를 이용해도 됨) 언어로

코딩하여 진행하게 된다.

 

다음 포스팅부터 pymata4와 FirmataExpress를 하나하나 뜯어보면서 어떻게 동작하는지에 대해 

살펴보도록 하자.

 

반응형

 

 

지난 시간 Firmata에 대해 포스팅한 후 많은 분들이 관심을 가져주시고 또한 의문을 제기해주셨다.

그중에 가장 중요한 것이 바로 다음의 두 가지였다.

 

  1.  왜 Firmata를 사용하는가?

  2. 왜 라즈베리파이와 아두이노를 연동하여 사용하는가?

 

이런 질문을 받고 나니 확실히 어떤 목적으로, 어떤 이점이 있기에 Firmata를 사용하고 라즈베리파이와

아두이노를 연동하려고 했는지 다시 한번 고민해보게 되었다. 아무리 작고 개인적인 프로젝트라 하더라도

역시나 대충, 어물쩡, 설렁설렁 하면 안되겠다고 새삼 깨달았다. 오늘은 위 두 질문에 대한 답을 찾는

것으로 시작을 해보고자 한다.

 

왜 Firmata를 사용하는가?

 

어찌보면 이 질문의 답은 명확하다. 대략 세 가지 정도로 추려보자면

 

1. 검증받은 프로토콜의 사용

지난 시간에도 언급했듯이 디지털 기기간에 통신을 하기 위해서는 프로토콜이라는 규약을 만들고 지킬 

필요가 있다. 하지만 프로토콜을 설계하고 구현한다는 것이 그리 만만한 작업은 아니다. 때문에 이미

검증된 MIDI Message Format을 이용하여 안정적으로 구현된 프로토콜을 사용할 수 있다는 것은

큰 이점이 될 것이다.

 

2. 다양한 기기 및 언어 이용

프로토콜이 명확하게 정의되어있기 때문에 이 프로토콜 구현만 제대로 한다면 어떤 언어로든 아두이노를

제어할 수 있다. Firmata Protocol git 페이지에 가보면 다양한 언어로 구현된 Firmata 클라이언트

링크를 볼 수 있다. 또한 시리얼 통신만 가능하다면 PC 뿐만 아니라 모바일 기기에서도 아두이노를 제어할 수

있다.

 

3. 사용의 용이성

Firmata Client 프로그램들은 이 프로토콜을 손쉽게 이용할 수 있도록 API가 잘 구현되어있다. 따라서

적절한 API를 가져다 쓰기만 한다면 웬만한 아두이노 컨트롤은 손쉽게 수행할 수 있다. 게다가 아두이노에는

Firmata 라이브러리만 올려두면 추가적인 프로그래밍이나 스케치 업로드등을 할 필요도 없어 오직 호스트

PC(혹은 모바일 기기)에서만 개발자에게 익숙한 클라이언트로 프로그래밍하여 제어할 수 있다.

 

이렇게 Firmata는 아두이노를 활용하는데 많은 이점을 주는 라이브러리라고 할 수 있다.

 

왜 라즈베리파이와 아두이노를 연동하여 사용하는가?

 

이 질문은 사실 많은 고민을 하게 만들었다. 라즈베리파이도 이미 충분한 수의 GPIO 핀이 있는데 굳이

아두이노를 연결해서 사용하는 이유는 무엇일까? 라즈베리파이와 아두이노 연동, 시리얼 통신 등으로

검색을 해보면 많은 자료들이 검색되지만 정작 왜 연동을 하는지 그 목적에 대해 설명한 자료는 거의

없다. 그저 기술적인 호기심 때문만은 아닐텐데…

 

하지만 내 개인 프로젝트에 국한했을 때는 이러한 구성에 의문을 가질 수 있지만 일반적인 상황에서, 또는

아두이노를 중심에 둔다면 이러한 구성이 충분히 합리적이라는 것을 알 수 있다.

 

1. 원격 센서 제어

호스트에서 원격으로 어떤 센서로 측정된 값을 가져와 연산을 하여 처리한다고 했을 때 당연히 원격 센서는

아두이노를 사용하는 것이 가격적인 측면에서 합리적일 것이다. 라즈베리파이는 호스트로서 수신된 데이터를

연산하기만 하면 된다.

 

2. 하드웨어적인 차이

원격이 아닌 같은 모듈 내에서 사용을 하더라도 라즈베리파이와 아두이노의 하드웨어적인 차이에 의해 함께

연동하여 사용할 수 있을 것이다. 가장 큰 차이라면 역시나 GPIO인데 아두이노에는 라즈베리파이에 없는

Analog PIN이 별도로 있으며, 작동 전압도 라즈베리파이가 3.3v 인 반면 아두이노의 경우 3.3v와 5v용을

선택하여 사용할 수 있고, 핀당 사용 가능한 전류도 라즈베리파이가 16mA인 반면 아두이노는 40mA까지

사용할 수 있다. 이러한 특성상 비록 라즈베리파이에 40여개의 GPIO가 있지만 아두이노를 연동해서 사용

하는 것이 더 나은 경우도 있을 것이다.

 

하드웨어에 대한 정보들은 간단하게 아래 내용을 참고하면 될 것이다.

 

The operating voltage of the GPIO pins is 3.3v with a maximum current draw of 16mA. This means that we can safely power one or two LEDs (Light Emitting Diodes) from a single GPIO pin, via a resistor. But for anything requiring more current, a DC motor for example, we will need to use external components to ensure that we do not damage the GPIO. 

-

출처 : https://www.tomshardware.com/reviews/raspberry-pi-gpio-pinout,6122.html

 

아두이노 우노의 사양

 

위의 내용을 감안해 본다면 분명히 라즈베리파이와 아두이노를 연동하여 사용해야 하는 것이 더 유용한 경우도 

있을 것이다. 

 

Firmata의 한계

 

하지만 100% 좋은 것이 어디 있으랴.

내 구미에 맞게 커스터마이징해야 하는 경우라면 Firmata는 결코 답이 아니다. 사실 모든 라이브러리나 

프레임워크가 다 동전의 양면이 아니던가? 쉽고 편하게 사용하기 위해 적용은 하지만 정작 중요하게 

커스터마이징해야 할 때 상당히 곤란한 상황에 직면하는 경우가 적지 않다.

 

지난 포스팅에서도 언급했듯이 나역시 PCA9685 PWM 서보모터 드라이버를 Firmata 상에서 사용하려고

했으나 이와 관련된 프로토콜은 정의되어있지 않기 때문에 대안을 찾기 위해 열심히 소스 코드를 뜯어보고 

있다…ㅠ.ㅠ 해결책에 한걸음 다가갔나 싶으면 비트 연산들이 줄줄이 나와 java 프로그래밍을 위주로 해온

나에게는 결코 쉽지 않은 작업이다…ㅠ.ㅠ

 

이 부분은 글을 이어 나가면서 극복해보도록 하겠다. 

 

정리

 

원래 이번 포스팅부터 코드 분석을 들어갈 예정이었으나 위의 질문들은 프로젝트를 수행하는데 있어서 분명

중요한 시사점이 있기 때문에 집고 넘어가는 것이 좋겠다고 생각했다. 그리고 이 글을 정리하기 위해 적잖이

검색을 하고 자료를 찾아보았지만 위와같은 근본적인 질문에 대한 명쾌한 답변은 찾기가 쉽지 않았다.

 

결국 몇몇 글들과 나름의 지식을 기반으로 글을 적기는 했지만 아직도 객관적인고 명확한 근거는 모자라지 

않나 하는 아쉬움이 있다. 이 부분은 앞으로의 숙제가 될 것 같다.

 

이제 예정한대로 다음 포스팅 부터는 Firmata Client와 라이브러리 그리고 예제 코드를 통해 Firmata에 

대해 조금 더 구체적으로 알아보도록 하겠다.

반응형

로봇을 제작하면서 전자부의 구성은 라즈베리파이 + 아두이노를 사용하기로 계획했다.

일단 사양과 활용도가 높은 라즈베리파이로 각종 데이터 분석과 추후 AI를 위한기능들을 구현하고

실제 구동부의 동작은 아두이노로 제어를 하는 구조다. 물론 요즘 새로 출시된 아두이노들은 웬만한

ML 처리는 가능하지만 아무래도 활용도라든지 관리 차원에서는 라즈베리파이가 조금 더 접근하기

쉬운 것은 사실이다.

 

게다가 일반적인 아두이노 호환 컨트롤러들은 워낙에 저가여서 모터나 센서 등을 조합해서 다양한

구동부를 만들고 이것을 라즈베리파이와 연동한다면 다양한 형태의 로봇이나 차량 혹은 드론을

만들 수 있을 것이라 생각했다. 그래서 프로젝트 이름도 MORS(MOdular Robot System)이라고

지었다.

 

계획은 세웠으니 이제 구현만 하면 되는데…라즈베리파이와 아두이노를 어떻게 연결하는 것이 좋을까?

아직 한번도 해본 적이 없는 구성이라 일단 열심히 검색을 해보았다.

 

일단 가장 기본적으로 알 수 있는 방법은 우리가 PC에서 아두이노 스케치를 개발하듯이 라즈베리파이를

호스트 PC로 만들고 거기서 스케치를 코딩하고 아두이노에 업로드하여 동작하도록 하는 것이다. 하지만

이 방식으로는 아두이노의 PIN에 대해 라즈베리파이가 직접 컨트롤 할 수 없다는 문제가 있다. 즉, 라즈베리

파이가 사용자의 신호를 받았을 때 그 신호를 실시간으로 아두이노에게 전달해야 하는데 이 방식으로는

그것이 불가능하다. 

 

사실상 라즈베리파이와 아두이노가 따로 노는 상황

 

그렇다면 라즈베리파이와 아두이노의 역할을 아예 분리하는 방식을 생각해볼 수도 있다. 라즈베리파이는

부하가 큰 데이터나 ML 처리의 연산만 담당하고 아두이노는 모터나 센서등의 동작을 담당하는 식이다.

하지만 이렇게 되면 사용자가 라즈베리파이와 아두이노를 이원화 하여 컨트롤해야 하고 또 다수의 아두이노

기반 구동부를 연결하는 경우 구조가 매우 복잡해진다(사실 첫 번째 경우와 동일한 케이스인데 다만

아두이노쪽에 사용자와 통신할 수 있는 모듈(ESP, 블루투스, nRF 등)을 추가하여 아두이노를 별도로

제어한다는 점이 다를 뿐이다).

 

쌍둥이를 키우는(?) 입장이랄까?

 

그러다 찾아낸 것이 바로 Firmata이다. 앞으로 얼마간 이 Firmata에 대해 알아보고자 한다.

 

바로 이거지~

 

이 글은 비록 개발자로 일하고 있지만 태생이 문돌이인 블로그 주인의 글이니 보다 정확한 자료를 원하시는

분들은 아래 링크로 이동하여 참고하시면 되겠다. 다만 영어의 압박은 감수하셔야…

 

Firmata 문서 Git : GitHub - firmata/protocol: Documentation of the Firmata protocol.

 

Firmata는 프로토콜이다.

 

프로토콜은 잘 아시다시피 하나의 규약이다. 통신을 할 때 지켜야 할 약속으로 우리가 가장 잘 알고있는

프로토콜은 바로 워키토키를 이용하여 통신을 할 때 자신이 할 말을 마쳤으니 상대방이 말하라고 하는

의미의 “오버”를 들 수 있겠다.

 

하지만 디지털 장치로 그 영역을 옮겨오면 그렇게 단순하지는 않다. 위의 예도 사람의 입장에서 적으니

단순하게 보일 뿐 실제 워키토키가 처리하는 것은 디지털화 된 음성 데이터를 두 대의 워키토키 사이에

전달하기 위해 채널을 확인해야 하고 데이터의 순서나 손실 여부를 체크해야 한다. 이 역시 중요한 부분만

언급했을 뿐 실제로는 더 많은 내용이 오고 갈 것이다.

 

아주 간단한 프로토콜

 

이렇게 디지털 기기에서 양자간에 데이터를 주고받기 위한 규칙을 프로토콜이라고 한다. 우리가 잘

아는 TCP/IP, SMTP, HTTP, FTP 등이 모두 프로토콜이며 각각의 목적에 따라 그 규칙이 모두 다르다.

지금 공부하고자 하는 Firmata 역시 이러한 프로토콜이며 Firmata의 목적은 호스트 컴퓨터와 마이크로

컨트롤러간에 직접 통신을 할 수 있도록 하기 위한 것이다.

 

Firmata는 midi message format을 기반으로 만들어졌다고 하는데 일단 midi message format이

무엇인지까지 파고드는 것은 범위가 너무 넓어지므로 관련 링크만 걸어두겠다.

 

Official MIDI Specifications : Specs

 

여기서 midi란 우리가 잘 알고 있는 디지털 악기가 맞다(Musical Instrument Digital Interface)

 

Firmata의 구성 - 소프트웨어 관점에서

 

Firmata는 호스트 PC쪽의 Firmata Client와 마이크로컨트롤러쪽의 Firmata 라이브러리로 구성

되어 있다. 

 

Firmata Client의 경우 웬만한 언어는 모두 사용 가능한데 대표적으로 Python, java, javascript로부터

iOS, Android까지 모두 사용 가능하다. 또한 각 언어로 구현된 클라이언트도 각각의 특성에 따라 여러

버전이 있어 필요에 따라 선택하여 사용 가능하다.

 

아두이노 라이브러리는 말 그대로 아두이노에서 사용 가능한 라이브러리 형태로 되어있으며 가장 기본적인

라이브러리는 아두이노 스케치의 예제에 포함이 되어있다. 파일 > 예제 > Firmata 항목으로 들어가면 

다양한 Firmata 목록을 볼 수 있는데 가장 기본적인 것은 StandardFirmata이다.

 

아두이노 스케치에서 Firmata 라이브러리 불러오기

 

아두이노에 Firmata 스케치를 업로드하고 클라이언트에서 API를 호출하면 Firmata 프로토콜을 통해

아두이노의 해당 API가 호출되는 식이다(자세한 것은 다음에 소스 분석을 통해 알아보겠다).

 

Firmata의 구성 - 프로토콜 관점에서

 

앞서도 이야기 했듯이 프로토콜이란 통신을 위해 지켜야 할 일종의 약속이다. 즉 FirmataClient에서

약속된 형태의 데이터를 전달해야 아두이노의 Firmara 라이브러리에서 데이터를 받아들이고 처리할 수

있다. 이러한 약속들은 아래 문서에 정의되어 있다.

 

Firmata protocol : protocol/protocol.md at master · firmata/protocol · GitHub

 

 

문돌이들의 경우 몇몇 개념이 헷갈릴 수 있으나 이 약속을 지키기 위한 대부분의 처리는 이미 API로 모두

구현이 되어있으며 다양한 샘플도 존재하니 그저 API를 호출해서 사용하면 된다. 조금 더 이해의 폭을

넓히자면 이 약속이라는 것이 그저 API 호출 시 넘겨주어야 할 파라미터를 정의하는 것이라 생각하면

조금 더 이해가 쉬울 것이다.

 

예를들어 위 링크된 문서의 Message Type 중 set digital pin value라는 항목을 살펴보자

테이블을 보면 우선 command 항목은 0xF5이다. 즉, 아두이노의 특정 디지털 핀에 값을 전달하기 

위해서는 0xF5라는 값으로 시작하는 데이터를 보내야 한다. 다음 열은 비어있고 세 번째 열에

1~127 사이의 핀 번호를 입력해야 하고 마지막으로 1 또는 0으로 해당 핀에 전달할 값을 지정해야

한다. 만일 9번 핀에 디지털 신호를 보내기 위해서는 0xF5, 9, 1 또는 0xF5, 9, 0으로 구성된 3개의

데이터를 보내면 되는데 command에 해당하는 값들은 상수로 지정하여 API에서 처리를 해주므로

실제 API를 호출할 때는 command를 제외한 9, 1 또는 9, 0만을 파라미터로 하여 다음과 같이

보내면 된다.

 

digital_pin_write(pin, 1) 
digital_pin_write(pin, 0)

 

이 중에서 특히 중요한 것이 Sysex Message Format인데 이 부분은 다음 포스팅에서 다뤄보기로 하겠다.

 

정리

 

사실 Firmata에 대해 굳이 이렇게까지 알지 않아도 대충 예제를 보면서 구현하는 것은 그리 어렵지 않다.

그런데 로봇을 만들면서 서보모터를 컨트롤하는데 I2C 기반으로 통신을 하는 PCA9685 PWM 서보모터

드라이버를 사용하려고 보니 아두이노에서 전용 라이브러리를 사용해야 하고 Firmata에서는 이러한 특정

라아브러리에 대한 message format까지 모두 지정해놓은 것은 아니라서 현재로서는 사용이 어렵다.

결국 어떻게 커스터마이징 좀 안될까 하고 조금 더 파고들어가 보기로 한 것이다.

 

물론 다른 방법으로는 I2C에 대한 message format은 정의가 되어있으므로 관련 API를 이용해서 제어하는

방법도 있을 것 같은데 그 또한 그리 만만하지는 않을 것 같아서 우선은 Firmata쪽을 보기로 하였다. 만일

이 시도가 실패한다면 아마도 I2C를 이용한 PCA9685 제어에 도전하게 될지도 모르겠다.

 

다음 포스팅에서는 Sysex Message Format에 대해 알아보고 본격적으로 API와 샘플코드에 대한 분석을

진행해보고자 한다. 

 

#블로그/로봇개발

반응형

얼른 로봇 프로그래밍 작업을 하고 마무리 지어야 하는데…덩치가 크다보니 어디 놓고 작업할 공간이 없어 

지지부진이다. 이렇게 2020년의 최대 목표를 달성하지 못하고 2021년을 맞이했다…ㅠ.ㅠ

 

그렇다고 아무것도 안한 것은 아니지만 뭔가 마무리를 하지 못했다는 것은 그 자체로 매우 찜짐한 일임은 

분명하다.

 

그럼 그동안 무엇을 했느냐?

 

물론 1차적으로는 내 업무와 관련된 여러가지 공부를 하였다. 본업이 프로그래머다보니 공부를 안할 수가 

없다. 문제는 얼마나 현재 직무와 관련성이 있느냐인데…업무 관련성보다는 내 개인적인 선호도를 위주로

공부를 하다보니 이게 영~ 쓸모가 있는 공부인지 잘 모르겠다…ㅠ.ㅠ 그래도 올해는 직무 관련이 있는 분야도

하나 넣었다.

 

다음으로는 3D 모델링 독학이다.

이미 로봇 개발 당시 Fusion 360을 나름 독학하여 열심히 모델링하고 출력하고 해서 외형은 다 완성을 

해놓았지만 여전히 목마른 부분이 있는 것은 어쩔 수가 없다. 그래서 올해부터는 무료라서 가장 매리트가 있는

블렌더를 추가로 공부하기 시작했다. 그리고 이 3D 모델링이 오늘 이야기하고자 하는 중요 주제이다.

 

마지막으로 그림 연습이다.

사실 이건 해야하나 말아야 하나 아직도 고민이다. 그저 시간을 까먹는 일이 될지, 아니면 내꿈을 이루기 위한

중요한 한 수가 될지…간간이 언급한 것 같은데 나의 최종 목표는 스토리를 갖는 메카닉을 만드는 것이다.

가장 쉽게 예를 들자면 선라이즈와 반다이를 합친 것 같은 작품활동…물론 개인으로서 그런 작업을 한다는 

것이 불가능에 가까워 보이지만, 자만일지 오만일지, 잡을 수 없는 먼 곳에 있는 꿈은 아닌 듯하다^^

 

어쨌든 위의 3가지는 올해의 집중 목표이기도 하다. 하지만 워낙 성격이 다른 분야가 뒤섞이다보니 한가지에

집중을 하지 못하는 문제가 있다. 독학으로 익히자면 수없이 많은 시간을 투자해도 모자랄 판인데 여러 분야를

적은 시간만을 투자하면서 진행하기는 매우 어려울 것으로 보인다. 하지만 어려울 뿐 불가능은 아니라는 생각으로

열심히 부대껴볼 생각이다.

 

로봇의 미학

 

현재 진행 중인 4족 보행 로봇 MORS 프로젝트를 시작할 때도 언급을 했지만 내가 만들고자 하는 로봇, 내가

생각하는 로봇에서 제일 중요한 요소는 ‘아름다움’이다. 아름다움이라 해도 매우 주관적인 관념이니 내가 

생각하는 기준을 좀더 구체적으로 말하자면 ArtStation이나 Pinterest에서 로봇을 검색하면 나오는 화려한

컨셉아트에서 보여지는 그러한 로봇이다. 하지만 또 한편으로는 로봇은 statue가 아니다. 로봇은 움직여야 

한다.

 

결국 내가 만들고 싶은 것은 아름다우면서도 실제 움직이는 로봇을 만들고 싶은 것이다.

 

사실 이미 전문 로봇 제조 업체나 완구업체에서 만드는 로봇들도 다자인이 많이 세련되어져서 갖고싶은 생각이

들게 하지만 나는 역시 나만의 컨셉으로 나만의 스토리를 가진 로봇을 만들고 싶은 것이다.

 

여러가지 로봇 컨셉아트

 

Hard Surface 모델링

 

사실 정확한 의미는 모르겠다. 다만 이름 그대로 정적이고 단단한 물체, 인공적인 것들 중 기계류나 건축물에 

속하는 것들을 모델링하는 것이라 보여진다. 물론 좀 더 모델링적으로 접근하면 버텍스나 엣지에 대한 여러

제약들이 언급되기는 하지만 내 지식 밖이니…-.-

 

Pinterest에서 Hard Surface Modeling으로 검색을 하면 엄청난 이미지들이 나오는데 대체로 금속성의 

사이버틱한 형태를 가진 이미지들이 검색된다. 로봇이나 우주선 모델링에 딱 좋을만한 그런 이미지들…

결국 욕심이 생길 수밖에 없다.

 

그런데 앞서 말했듯이 모델링의 관점에서 보자면 버텍스나 엣지에 대한 제약들이 들어가는데 현재 주로 사용

중인 Fusion 360은 버텍스나 엣지보다는 프로파일이나 솔리드 오브젝트를 중심으로 모델링을 하기 때문에

세밀한 Hard Surface Modeling은 쉽지 않아보인다. 물론 내가 아직 익히지 못한 Surface Modelig을 

이용한다면 더 나은 작업을 할 수는 있을 것 같고 또 유튜브에서 Fusion 360 Hard Surface Modeling을

검색해보면 꽤 많은 작품들의 제작 과정 영상이 검색되는데 말하자면 명필은 붓을 가리지 않는다고, 결국

중요한 것은 나의 실력이지 툴이 아니라는 결론에 이르렀다. 그래서 조금 더 Fusion 360에 집중해보기로 

했다.

 

하지만 Blender의 경우 기본적으로 버텍스(점), 엣지(선), 페이스(면)을 자유자재로 변형하면서 모델링을 하는 

툴이다보니 좀 더 다양한 형태를 만들 수 있을 것 같긴 하나 다룰 수 있는 포인터가 많은만큼 모양이 틀어진 

경우 손이 상당히 많이 가는 것 같아 이 역시 쉽지는 않아보인다. 그래도 보험 들어놓는다는 차원에서 Blender

또한 공부는 해볼 생각이다.

 

돈만 많다면…3DS Max를 써볼텐데…ㅠ.ㅠ

 

Hard Surface Modeling

 

3D 프린팅을 위한 Hard Surface 모델링 실험

 

하지만 또한가지 난관이 있다.

모델링이 잘 되었어도 결국은 3D 프린터를 이용해 출력을 해야 하는데 SLA나 DLP 프린터가 아니라면 사실상

모델링한 디테일을 모두 살리기가 어렵다는 것이다. 그렇다고 유지비가 비싼 SLA/DLP 프린터를 사는 것도

그리 만만한 일은 아니다. 결국 어느정도 모델링이 FDM 프린터에서도 디테일을 어느정도 살리면서 보기 좋게

출력이 되는지 실험을 하기로 했다.

 

일단 모델링 대상은 내가 제일 많이 사용하고 있는 N20 계열의 소형 DC 모터의 케이스이다. 

 

그냥 모터만 덩그러니 구동부에 고정시키기 보다는 보다 시각적인 효과를 주면 좋을 것 같아 크기도 작고 많이

사용하는 N20 모터에 덧씌울 케이스를 만들어보기로 한 것이다.

 

우선 모델링은 Fusion 360으로 아래와 같이 하였다. 당연히 Pinterest에서 검색되는 이미지들과는 다르게 

투박하고 촌스러운 모델링이 되었다…ㅠ.ㅠ

 

 

문제는 출력 이후다. 그래도 나름 FDM 프린터의 특성을 감안하여 가능한한 너무 얇아지는 부분이 없도록

신경써서 모델링(그래서 더더욱 샤프한 맛이 없어졌다)을 했고 출력 품질도 적층 높이 0.12mm로 출력을

했는데도 불구하고 형체를 구분하기 쉽지 않은 부분, 조금만 힘을 줘도 부서지는 부분들이 많았다. 게다가

크기가 작다보니 퍼티질이나 사포질은 감히 엄두도 내지 못하는 상태였다. 

 

그런 문제를 상쇄하기 위해 일단 건담마커를 이용해 도색을 하였는데 아무래도 후가공 없이 도색을 하다보니 

도색 후의 상태 역시 메롱일수밖에 없다…ㅠ.ㅠ

 

 

 

 

정리

 

비록 미숙한 모델링에 미숙한 프린팅 설정이지만 그래도 가능성은 보였다. 크기가 작은만큼 디테일을 좀 

줄이고 결합되는 다른 부품과의 연결을 통해서 디테일을 살린다면 Fusion 360으로 모델링한 후 FDM으로

출력해도 제법 준수한 부품을 출력할 수 있을 것 같다.

 

사실 이 글을 쓰기 전에 SLA/DLP 프린터로 출력하면 확실히 더 나을 것 같아 몇군데 견젹을 의뢰했었는데

총 5개의 부품으로 이루어진 모델링 파일 2세트를 출력하는데 작게는 44,000원에서 많게는 440,000원 까지

조금은 부담스러운 견적이 나와 그냥 포기했다(그렇다고 저 가격들이 불합리하다는 것은 아니다).

 

아무튼 수정 방향을 잡았으니 계속 학습과 실험을 이어 나가야 겠다.

그나저나 내 4족 보행 로봇은 언제 완성하나…ㅠ.ㅠ

 

#블로그/로봇개발

'Study > 3D 모델링' 카테고리의 다른 글

3D 프린팅을 위한 Hard Surface Modeling  (0) 2021.01.13
반응형

 

하다가 잘 안된다고 머신 러닝 Reboot라는 타이틀까지 붙여놓고 다시 관심을 가져보려고 했는데…

역시나 또 우선순위가 밀려 하다가 흐지부지…ㅠ.ㅠ

 

원래 공부 못하는 애들 특징이 책의 앞부분만 빽빽한 메모가 들어차있고 뒷부분은 새책인 거…-.-

역시 나는 공부 못하는 애들류인가보다…ㅠ.ㅠ

 

그래도 포기하지 않고 끈기있게 달려드는 것이 가상하지 않는가^^;;;

 

머신러닝 Reboot라는 타이틀로 경사 하강법을 정리하던 중이었는데 다시 빠꾸~

핸즈온 머신러닝 (2판)을 처음부터 차근차근 밟아나가야겠다.

전체 내용을 정리하기 보다는 각 챕터의 뒤에 나오는 연습문제를 정리하는 방식으로 학습을 진행해보고자 

한다. 물론 답은 부록에 있는 내용이 아니라 책 본문에 있는 내용을 직접 찾아서 정리를 할 것이다.

 

사실 올해는 로봇 만드는 것만 목표로 했고 인공지능 학습은 내년에 다시 본격적으로 시작하려고 했는데

요즘 너무 시간 활용을 못하는 것 같아 조금 일찍 시작하기로 했다. 일단 이런 식으로 책을 한 권 한 권

독파해나가야겠다.

 

1장 한눈에 보는 머신러닝 연습문제 정리

 

아래 연습문제의 답은 제가 직접 정리한 답으로 정답을 확인하려면 책의 부록을 확인하세요~

 

1. 머신러닝을 어떻게 정의할 수 있나요?

더보기

책에서의 정의 - 데이터를 이용하여 학습하도록 컴퓨터를 프로그래밍하는 과학(또는 예술)

아서 새뮤얼 - 명시적인 프로그래밍 없이 컴퓨터가 학습하는 능력을 갖추게 하는 연구 분야.

톰 미첼 - 어떤 작업 T에 대한 컴퓨터 프로그램의 성능을 P로 측정했을 때 경험 E로 인해 성능이 향상됐다면, 이 컴퓨터 프로그램은 작업 T와 성능 측정 P에 대해 경험 E로 학습한 것이다.

 

톰 미첼의 정의가 가장 복잡한데 한마디로 (컴퓨터 프로그램이) 경험을 통해 성능이 향상되었다면 이것이 곧 인공지능이라는 소리로 알아들으면 될 것 같다. 

 

여기서 중요한 것은 경험인데…사람이라면 단순한 지식 뿐만 아니라 행동과 감각을 통해서 많은 경험을 하게 되지만 컴퓨터는 (아직까지는) 거의 데이터에 의존한 경험이다. 때문에 인간의 행동과 감각을 모방한 센서의 역할이 중요하다고 생각된다. 

 

2. 머신러닝이 도움을 줄 수 있는 문제 유형 네가지를 말해보세요.

더보기
  •  기존 솔루션으로는 많은 수동 조정과 규칙이 필요한 문제

  •  전통적인 방식으로는 해결 방법이 없는 복잡한 문제

  •  유동적인(변화가 심한) 환경

  •  복잡한 문제와 대량의 데이터에서 통찰 얻기

 

3. 레이블된 훈련 세트란 무엇인가요?

더보기

지도학습에 사용되는 레이블(원하는 답)이 포함된 훈련용 데이터 세트. 스팸 필터에서 ‘스팸’이라고 표시된 데이터 세트나 중고차 가격 수치를 예측하는 시스템에서 ‘중고차 가격’이 표시된 데이터 세트 등

 

4. 가장 널리 사용되는 지도 학습 작업 두 가지는 무엇인가요?

더보기
  •  분류 (말 그대로 분류)

  •  회귀 (특정 값을 예측)

 

5. 보편적인 비지도 학습 작업 네 가지는 무엇인가요?

더보기
  •  군집

  •  시각화와 차원 축소

  •  이상치 탐지 (책의 정답에는 이상치 탐지가 빠져있고 시각화, 차원 축소가 각각 1가지씩으로 간주 됨)

  •  연관 규칙 학습

 

6. 사전 정보가 없는 여러 지형에서 로봇을 걸어가게 하려면 어떤 종류의 머신러닝 알고리즘을 사용할 수 있나요?

더보기

강화학습

 

7. 고객을 여럭 그룹으로 분할하려면 어떤 알고리즘을 사용해야 하나요?

더보기

군집 알고리즘 (책의 추가 답변으로는 그룹 정보가 있는 경우 분류 알고리즘을 이용해서 처리할 수 도 있음)

 

8. 스팸 감지 문제는 지도 학습과 비지도 학습 중 어떤 문제로 볼 수 있나요?

더보기

앞서 본 것과 같이 스팸 필터는 레이블된 훈련 세트가 필요하므로 지도 학습에 속함

 

9. 온라인학습 시스템이란 무엇인가요?

더보기

데이터를 순차적으로 한 개씩 또는 미니배치라 부르는 작은 묶음 단위로 주입하여 시스템을 훈련시키는 방법. 매 학습 단계가 빠르고 비용이 적게 들어 새로운 데이터가 도착해도 바로 학습을 진행할 수 있음.

연속적으로 데이터를 받고 바른 변화에 스스로 적응해야 하는 시스템이나 자원이 제한적인 경우에 적합.

 

10. 외부 메모리 학습이 무엇인가요?

더보기

컴퓨터 한 대의 메인 메모리에 들어갈 수 없을 정도로 큰 데이터 세트를 사용하는 경우 데이터의 일부를 읽어 들여 학습을 진행하는 방법을 전체 데이터가 모두 적용될 때까지 반복적으로 수행하는 방식. 보통 오프라인으로 수행되는 점진적 학습 방법 (기법 상으로는 온라인 학습에 속함)

 

11. 예측을 하기 위해 유사도 측정에 의존하는 학습 알고리즘은 무엇인가요?

더보기

사례 기반 학습 - 훈련 데이터를 기억하고 있다가 새로운 데이터를 훈련 데이터와 비교하여 분류

 

12. 모델 파라미터와 학습 알고리즘의 하이퍼파라미터 사이에는 어떤 차이가 있나요?

더보기
  •  모델 파라미터 - 학습알고리즘에 의해 결정되는 파라미터. 학습이 진행되는 동안 최적값을 찾아감

  •  하이퍼파라미터 - 학습알고리즘으로부터 영향을 받지 않는 파라미터. 사람이 결정함. 훈련 전에 미리 지정되고, 훈련하는 동안에는 상수로 처리 됨.

 

13. 모델 기반 알고리즘이 찾는 것은 무엇인가요? 성공을 위해 이 알고리즘이 사용하는 가장 일반적인 전력은 무엇인가요? 예측은 어떻게 만드나요?

더보기
  •  모델 기반 알고리즘이 찾는 것 : 최적의 모델 파라미터

  •  성공을 위해 이 알고리즘이 사용하는 가장 일반적인 전략 : 효용 함수의 사용

  •  예측은 어떻게 만드는가 : 결정된 모델에 훈련 데이터가 아닌 새로운 데이터를 입력

 

14. 머신러닝의 주요 도전 과제는 무엇인가요?

더보기
  •  충분하지 않은 양의 훈련 데이터

  •  대표성 없는 훈련 데이터

  •  낮은 품질의 데이터

  •  관련 없는 특성

  •  훈련 데이터의 과대적합

  •  훈련 데이터의 과소적합

 

15. 모델이 훈련 데이터에서의 성능은 좋지만 새로운 샘플에서의 일반화 성능이 나쁘다면 어떤 문제가 있는 건가요? 가능한 해결책 세 가지는 무엇인가요?

더보기

모델이 훈련데이터셋에서는 성능이 좋지만 새로운 샘플에서의 일반화 성능이 나쁜 것은 훈련데이터에 과대적합 되어있는 것이다. 가능한 해결책은 다음의 3가지 이다.

  •  파라미터 수가 적은 모델을 선택하거나 훈련 데이터의 특성 수를 줄이거나 모델에 제약을 가함

  •  훈련 데이터를 더 많이 모음

  •  훈련데이터에서 오류 데이터를 수정하거나 이상치를 제거함

 

16. 테스트 세트가 무엇이고 왜 사용해야 하나요?

더보기

훈련 세트로 학습된 모델을 테스트(평가)하기 위해 사용되는 데이터 세트이며 전체 데이터 세트를 훈련 세트와 테스트 세트로 나누어 사용한다. 

 

17. 검증 세트의 목적은 무엇인가요?

더보기

모델의 하이퍼파라미터가 테스트 세트에 최적화 되는 상황을 막기 위해 

 

18. 훈련-개발 세트가 무엇인가요? 언제 필요하고 어떻게 사용해야 하나요?

더보기

모델의 문제가 훈련세트에 과대적합 되어있는 것인지 데이터가 불일치하여 발생한 것인지를 판단하기 위해 훈련 세트로부터 떼어낸 또 다른 세트.

 

19. 테스트 세트를 사용해 하이퍼파라미터를 튜닝하면 어떤 문제가 생기나요?

더보기

모델과 하이퍼파라미터가 테스트 세트에 최적화되어 최적의 모델을 찾기가 어려워짐.

+ Recent posts