머신러닝 시스템의 종류는 굉장히 많으므로 다음을 기준으로 넓은 범주에서 분류하면 도움이 됩니다.
- 사람이 감독 하에 훈련하는 거신지 그렇지 않은 것인지(지도, 비지도, 준지도, 강화 학습)
- 실시간으로 점진적인 학습을 하는지 아닌지(온라인 학습과 배치학습)
- 단순하게 알고 있는 데이터 포인트와 새 데이터 포인트를 비교하는 것인지 아니면 훈련 데이터셋에서 과학자들처럼 패턴을 발견하여 예측 모델을 만드는지(사례 기반 학습과 모델 기반 학습)
이 범주들은 서로 배타적이지 않으며 원하는 대로 연결할 수 있습니다. 예를 들어 최첨단 스팸 필터가 심층 신경망 모델을 사용해 스팸과 스팸이 아닌 페일로부터 실시간으로 학습할 지도 모릅니다. 그렇다면 이 스스템은 온라인이고 모델 기반이며 지도 학습 시스템입니다.
이 범주들을 조금 더 차세히 들여다보겠습니다.
1.3.1 지도 학습과 비지도 학습
머신러닝 시스템을 '학습하는 동안의 감독 형태나 정보량'에 따라 분류할 수 있습니다. 지도 학습, 비지도 학습, 준지도 학습, 강화 학습 등 네 가지 주요 범주가 있습니다.
지도학습
지도 학습supervised learning에는 알고리즘에 주입하는 훈련 데이터에 레이블label이라는 원하는 답이 포함됩니다.
분류classification가 전형적인 지도 학습 작업이며, 스팸 필터가 좋은 예입니다. 스팸 필터는 많은 메일 샘플과 소속 정보(스팸인지 아닌지)로 훈련되어야 하며 어떻게 새 메일을 분류할지 학습해야 합니다.
또 다른 전형적인 작업은 예측 변수predictor variable라 부르는 특성feature(주행거리, 연식, 브랜드 등)을 사용해 중고차 가격 같은 타긱 수치를 예측하는 것입니다. 이런 종류의 작업을 휘귀regression라고 부릅니다. 시스템을 훈련시키려면 예측 변수와 레이블(중고차 가격)이 포함된 중고차 데이터가 많이 필요합니다.
NOTE 머신러닝에서 속성(attribute)은 데이터 타입(예를 들면 주행거리)을 말합니다. 특성은 문맥에 따라 여러 의미를 갖지만 일반적으로 속성과 값이 합쳐진 것을 의미합니다.(예를 들면 주행거리=15,000). 하지만 많은 사람이 속성과 특성을 구분하지 않고 사용합니다.
일부 희귀 알고리즘은 분류에 사용할 수도 있고 또 반대의 경우도 있습니다. 옐르 들어 분류에 널리 쓰이는 로지스틱 희귀는 클래스에 속할 확률을 출력합니다(예를 들면 스팸일 가능성 20%).
다음은 가장 중요한 지도 학습 알고리즘들입니다
- k-최근접 이웃k-Nearest Neighbors
- 선형 희귀(Linear Regression)
- 로지스틱 희귀(Logistic Regression)
- 서포트 벡터 머신(Support Vector Machines SVM)
- 결정트리(Decision Tree)와 랜덤 포레스트(Random Forests)
- 신경망(Neural networks)
비지도 학습
비지도 학습(unsupervised learning)에는 말 그대로 훈련 데이터에 레이블이 없습니다. 시스템이 아무런 도움 없이 학습해야 합니다.
다음은 가장 중요한 비지도 학습 알고리즘 입니다.
- 군집(Clustering)
- k-평균(k-Means)
- 계층 군집 분석(Hierarchical Cluster Analysis. HCA)
- 기댓값 최대화(Expectaion Maximization)
- 시각화(visualization)와 차원 축소(dimensionality reduction)
- 주성분 분석(Principal Component Analysis. PCA)
- 커널(kernel)PCA
- 지역적 선형 임베딩(Locally-Linear Embedding. LLE)
- t-SNE (t-distributed Stochastic Neighbor Embedding)
- 연관 규칙 학습(Association rule learning)
- 어프라이어리(Apriori)
- 이클렛(Eclat)
예를 들어 블로그 방문자에 대한 데이터가 많이 있다고 합시다. 비슷한 방문자들을 그룹으로 묶기 위해 군집 알고리즘을 적용하려 합니다. 하지만 방문자가 어떤 그룹에 속하는지 알고리즘에 알려줄 수 있는 데이터 포이트가 없습니다. 그래서 알고리즘이 스스로 방문자 사이의 연결고리를 찾습니다. 예를 들어 40%의 방문자가 만화책을 좋아하며 저녁때 블로그 글을 읽는 남성이, 20%는 주말에 방문하는 공상 과학을 좋아하는 젋은 사람임을 알게 될지도 모릅니다. 계층 군집(hierachical clustering)알고리즘을 사용하면 각 그룹을 더 작은 그룹으로 세분화할 수 있습니다. 그러면 각 그룹에 맞춰 블로그에 글을 쓰는데 도움이 될 것입니다.
시각화(visualization)알고리즘도 비지도 학습 알고리즘의 좋은 예입니다. 레이블이 없는 대규모의 데이터를 넣으면 도식화가 가능한 2D나 3D 표현을 만들어 줍니다. 이런 알고리즘은 가능한 한 구조를 그대로 유지하려 하므로(예를 들어 입력 공간에서 떨어져 있던 클러스트(cluster)는 시각화된 그래프에서 겹쳐지지 않게 유지됩니다) 데이터가 어떻게 조직되어 있는지 이해할 수 있고 예상하지 못한 패턴을 발견할 수도 있습니다.
비슷한 작업으로는 너무 많은 정보를잃지 않으면서 데이터를 간소화하려는 차원 축소(dimensionlity reduction)가 있습니다. 이렇게 하는 한가지 방법은 상관관계가 있는 여러 특성을 하나로 합치는 것입니다. 예를 들어 차의 주행거리가 연식과 매우 연관되어 있으므로 차원 축소 알고리즘으로 두 특성을 차의 마모 정도를 나타내는 하나의 특성으로 합칠 수 있습니다. 이를 특성 추출(feature extraction)이라고 합니다.
TIP (지도 학습 알고리즘 같은) 머신러닝 알고리즘에 데이터를 주입하기 전에 차원 축소 알고리즘을 사용하여 훈련 데이터의 차원을 줄이는 것이 유용할 때가 많습니다. 살행 속도가 훨씬 빨라지고 디스크와 메모리를 차지하는 공간도 줄고 경우에 따라 성능이 좋아지기도 합니다.
또 하나의 중요한 비지도 학습은 이상치 탐지(anomaly detection)입니다. 예를 들어 부정 거래를 막기 위해 이상한 신용카드 거래를 감지하고, 제조 결함을 잡아내고, 학습 알고리즘에 주입하기전에 데이터셋에서 이상한 값을 자동으로 제거하는 것 등입니다. 시스템은 정상 샘플로 훈련되고, 새로운 샘플이 정상 데이터인지 혹은 이상치인지 판단합니다.
널리 사용되는 또 다른 비지도 학습은 대량의 데이터에서 특성 간의 흥미로운 관계를 찾는 연관 규칙 학습(association rule learning)입니다. 예를 들어 여러분의 슈퍼마켓을 운영한다고 가정합시다. 판매 기록에 연관 규칙을 적용하면 바비규 소스와 감자를 구매한 사람이 스테이크도 구매하는 경향이 있다는 것을 찾을지도 모릅니다.
준지도 학습
어떤 알고리즘은 레이블이 일부만 있는 데이터도 다룰 수 있습니다. 보통은 레이블이 없는 데이터가 많고 레이블이 있는 데이터는 아주 조금입니다. 이를 준지도 학습(semisupervised learning)이라고 합니다.
구글 포토 호스팅 서비스가 좋은 예입니다. 이 서비스에 가족 사진을 모두 올리면 사람 A는 사진1, 5, 11에 있고, 사람 B는 사진 2, 5, 7에 있다고 자동으로 인식합니다. 이는 비지도학습(군집)입니다. 이제 시스템에 필요한 것은 이 사람들이 누구인가 하는 정보입니다. 사람마다 레이블이 하나씩만 주어지면 사진에 있는 모든 사람의 이름을 알 수 있고, 편리하게 사진을 찾을 수 있습니다.
대부분의 준지도 학습 알고리즘은 지도 학습과 비지도 학습의 조합으로 이루어져 있습니다. 예를 들어 심층 신뢰 신경망 deep belief network (DBN)은 여러 겹으로 쌓은 제한된 볼츠만머신 restricted Bolzmann machine(RBM)이라 불리는 비지도 학습에 기초합니다. RBM이 비지도 학습 장식으로 순차적으로 훈련된 다음 전체 시스템이 지도 학습 방식으로 세밀하게 조정됩니다.
강화 학습
강화 학습(Reinforcement learning)은 매우 다른 종류의 알고리즘입니다. 여기서느 학습하는 시스템을 에이전트라고 부르며 환경environment을 관찰해서 해동action을 실행하고 그 결과로 보상reward(또는 부정적인 보상에 해당하는 벌점 penalty)을 받습니다. 시간이 지나면서 가장 큰 보상을 얻기 위해 정책policy이라고 부르는 최상의 전략을 스스로 학습합니다. 정책은 주어진 상황에서 에이전트가 어떤 해동을 선택 할지 정의합니다.
예를 들어 보행 로봇을 만들기 위해 강화학습 알고리즘을 많이 사용합니다. 딥마인드DeepMind의 알파고AlphaGo프로그램도 강화 학습의 좋은 예입니다. 2017년 5월 바둑 세계챔피언인 커제선수를 이겨서 신문의 헤드라인을 장식했습니다. 알파고는 수백만 개으이 게임을 분석해서 승리에 대한 전략을 학습했으며 자기 자신과 많은 게임을 했습니다. 알파고가 세계챔피언과 게임할 때는 학습 기능을 끄고 그동한 학습했던 전략을 적용한 것입니다.
1.3.2 배치 학습과 온라인 학습
머신러닝 시스템을 분류하는 데 사용하는 다른 기준은 입력 데이터의 스트림stream으로 부터 점진적으로 학습하 수 있는지 여부입니다.
배치 학습
배치 학습(batch learning)에서는 시스템의 점진적으로 학습할 수 없습니다. 가용한 데이터를 모두 사용해 훈련시켜야 합니다. 일반적으로 이 방식은 시간과 자원을 많이 소모하므로 보통 오프라인에서 수행됩니다. 먼저 시스템을 훈련시키고 그 다음 제품 시스템에 적용하면 더 이상의 학습없이 실행 됩니다. 즉, 학습한 것을 단지 적용만 합니다. 이를 오프라인 학습offline learning이라고 합니다.
배치 학습 시스템이 (새로운 종류의 스팸 같은) 새로운 데이터에 대해 학습하려면(새로운 데이터뿐만 아니라 이전 데이터도 포함한) 전체 데이터를 사용하여 시스템의 새로운 버전을 첨부터 다시 훈련해야 합니다. 그런 다음 이전 시스템을 중지시키고 새시스템으로 교체합니다.
다행이 머신러닝 시스템을 훈련, 평가, 론칭하는 전체 과정이 쉽게 자동화 될 수 있어서 배치 학습 시스템도 변화에 적응할 수 있습니다. 데이터를 업데이트하고 시스템의 새 버전을 필요한 만큼 자주 훈련시키면 됩니다.
이런 방식이 간단하고 잘 작동하지만 전체 데이터셋을 사용해 훈련하는데 몇 시간이 소요될 수 있습니다. 보통 24시간마다 또느 매주 시스템을 훈련시킵니다. 시스템이 빠르게 변하는데이터에 적응해야 한다면(예를 들면 주식가격)더 능동적인 방법이 필요합니다.
또한 전체 데이터셋을 사용해 훈련한다면 많은 컴퓨팅 장원이 필요합니다(CPU, 메모리 공간, 디스크 공간, 디스크IO, 네트워크IO 등). 대량의 데이터를 가지고 있는데 매일 처음부터 새로 훈련시키도록 시스템을 자동화한다면 큰 비용이 발생할 것입니다. 데이터 양이 아주 많으면 배치 학습 알고리즘을 사용하는게 불가능할 수도 있습니다.
마지막으로, 자원이 제한된 시스템(예를 들면 스마트폰 또는 화상 탐사 로버rover)이 스스로 학습해야 할 때 많은 양의 훈련 데이터를 나르고 학습을 위해 매일 몇 시간씩 많은 자원을 사용하면 심각한 문제를 일으킵니다.
이런 경우에는 점진적으로 학습할 수 있는 알고리즘을 사용하는 편이 낫습니다.
온라인 학습
온라인 학습online learning에서는 데이터를 순차적으로 한 개씩 또는 미니배치mini-batch라 부르는 작은 단위로 주입하여 시스템을 훈련시킵니다. 매 학습 단계가 빠르고 비용이 적게 들어 시스템은 데이터가 도착하는 대로 즉시 학습할 수 있습니다.
온라인 학습은 연속적으로 데이터를 받고 빠른 변화에 스스로 적응해야 하는 시스템에 적합합니다. 컴퓨팅 자원이 제한된 경우에도 좋은 선택입니다. 온라인 학습 시스템이 새로운 데이터 샘플을 학습하면 학습이 끝난 데이터는 더 이상 필요하지 않으므로 버리면 됩니다. 이렇게 되면 많은 공간을 절약할 수 있습니다.
컴퓨터 한 대의 메인 메모리에 들어갈 수 없는 아주 큰 데이터셋을 학습하는 시스템에도 온라인 학습 알고리즘을 사용할 수 있습니다.(이를 외부 메모리out-of-core 학습이라고 합니다). 알고리즘이 데이터 일부를 읽어 들이고 훈련 단계를 수행합니다. 전체 데이터가 모두 적용될 때까지 이 과정을 반복합니다.
CAUTION 이 경우 전체 프로세스는 보통 오프라인으로 실행됩니다(즉, 실시간 시스템에서 수행되는 것이 아닙니다). 그래서 온라인 학습 이라 이름이 혼란을 줄 수 있습니다. 점진적 학습incremental learning이라고 생각하세요.
온라인 학습 시스템에서 중요한 파라미터 하나는 변화하는 데이터에 얼마나 빠르게 적응할 것인지 입니다. 이를 학습률learning rate이라고 합니다. 학습률을 높게 하면 시스템이 데이터에 빠르게 적응하지만 예전 데이터를 금방 잊어버릴 것입니다(최근에 나타난 스팸의 종류만 걸러낼 수 있는 스팸 필터를 원할 리는 없습니다). 반대로 학습률이 낮으면 시스템의 관성이 더 커져서 더 느리게 학습됩니다. 하지만 새로운 데이터에 있는 잡음이나 대표성 없는 데이터 포인트에 덜 민감해집니다.
온라인 학습에서 가장 큰 문제점은 시스템에 나쁜 데이터가 주입되었을 때 시스템 성능이 점진적으로 감소한다는 점입니다. 운영 중인 시스템이라면 고객이 눈치챌지 모릅니다. 예를 들어 로봇의 오작동 센서로부터, 혹은 검색 엔진을 속여 검색 결과 상위에 노출시키려는 누군가로부터 나쁜 데이터가 올 수 있습니다. 이런 위험을 줄이려면 시스템을 면밀히 모니터링하고 성능 감소가 감지되면 즉각 학습을 중지시켜야 합니다(가능하면 이전 운영 상태로 되돌립니다). 입력 데이터를 모니터링해서 비정상 데이터를 잡아낼 수도 있습니다(예를 들면 이상치 탐지 알고리즘을 사용해서).
1.3.3 사례 기반 학습과 모델 기반 학습
머신러닝 시스템은 어떻게 일반화되는가에 따라 분류할 수도 있습니다. 대부분의 머신러닝 작업은 예측을 만드는 것입니다. 이 말은 주어진 훈련 데이터로 학습하지만 훈련 데이터에서는 본적 없는 새로운 데이터로 일반화되어야 한다는 뜻입니다. 훈련 데이터에서 놀은 성능을 내를 것이 좋지만 그게 전부는 아닙니다. 진짜 목표는 새로운 샘플에 잘 작동하는 모델입니다.
일반화를 위한 두 가지 접근법은 사례 기반 학습과 모델 기반 학습입니다.
사례 기반 학습
아마도 가장 간단한 형태의 학습은 단순히 기억하는 것입니다. 스팸 필터를 이러한 방식으로 만들면 사용자가 스팸이라고 지정한 메일과 동일한 모든 메일을 스팸으로 분류합니다. 최악의 방법은 아니지만 최선도 아닙니다.
스팸 메일과 동일한 메일을 스팸이라고 지정하는 대신 스팸 메일과 매우 유사한 메일을 구분하도록 스팸 필터를 프로그램할 수 있습니다. 이렇게 하려면 두 메일 사이의 유사도similarity를 측정해야 합니다. 두 메일 사이의 매우 간단한 유사도 측정 방법은 공통으로 포함한 단어의 수를 세는 것입니다. 스팸 메일과 공통으로 가지고 있는 단어가 많으면 스팸으로 분류합니다.
이를 사례 기반 학습instance-based learning 이라고 합니다. 시스템이 사례를 기억함으로써 학습합니다. 그리고 유사도 측정을 사용해 새로운 데이터에 일반화합니다.
모델 기반 학습
샘플로부터 일반화시키는 다른 방법은 이 샘플들의 모델을 만들어 예측에 사용하는 것입니다. 이를 모델 기반 학습model-based learning이라고 합니다.
예를 들어 돈이 사람을 행복하게 만드는지 알아본다고 가정합시다. OECD 웹사이트에서 더 나은 삷의 지표Better Life Index데이터와 IMF 웹사이트에서 1인당 GDP통계를 내려받습니다. 두 데이터 테이블을 합치고 1인당 GDP로 정렬합니다. 일부 국가를 무작위로 골라서 그래프를 그려봅시다.
여기서 어떤 경향을 볼 수 있습니다! 데이터가 흩어져 있지만(즉, 어느 정도 무작위성이 있지만) 삶의 만족도는 국가의 1인당 GDP가 증가할 수록 거의 선형으로 같이 올라갑니다. 그러므로 1인당 GDP의 선형 함수로 삶의 만족도를 모델링해보겠습니다. 이 단계를 모델 선택model selection이라고 합니다. 1인당 GDP라는 특성 하나를 가진 삶의 만족도에 대한 선형 모델linear model입니다.
이 모델은 두 개의 모델 파라미터을 가집니다. 이 모델 파라미터를 조정하여 어떤 선형 함수를 표현하는 모델을 얻을 수 있습니다.
모델을 사용하기 전에 @와 @을 정의해야 합니다. 모델의 최상의 성능을 내도록 하는 값을 어떻게 알 수 있을 까요? 이 질문에 대답하려면 측정 지표를 정해야 합니다. 모델이 얼마나 좋은지 측정하는 효용 함수utility function(또는 적합도 함수fitness function)를 정의하거나 얼마나 나쁜지 측정하는 비용 함수cost function를 정의할 수 있습니다. 선형 희귀에서는 보통 선형 모델의 예측과 훈련 데이터 사이의 거리를 재는 비용 함수를 사용합니다. 이 거리를 최소화하는 것이 목표 입니다.
여기에서 선형 휘귀Linear Regression알고리즘이 등장합니다. 알고리즘에 훈련 데이터를 공급하면 데이터에 가장 잘 맞는 선형 모델의 파라이멑를 찾습니다. 이를 모델을 훈련training시킨다고 말합니다. 이 경우에는 알고리즘의 최적의 파라미터로 @=4.85와 @=4.91*10-5을 찾습니다.
이제 이 모델을 사용해 예측을 할 수 있습니다. 예를 들어 OECD 데이터에 없는 키프로스 Cyprus 사람들이 얼마나 행복한지 알아보려면 이 모델을 사용해 예측할 수 있습니다. 키프로스의 1인당 GDP를 보면 22,587달러이므로 이를 모델에 적용해 4.85 + 22,587*4.91*10-5 = 5.96과 같이 삷의 만족도를 계산합니다.
NOTE 사례 기반의 학습 알고리즘을 사용한다면 먼저 1인당 GDP가 키프로스와 가장 가까운 슬로베니아 Slovenia(20,732달러)를 찾습니다. OECD데이터 있는 슬로베니아의 삶의 만족도가 5.7로 예측합니다. 조금 더 확대해서 그 다음으로 가까운 두 나라를 더 고려하면 삶의 만족도가 5.1과 6.5인 포르투갈과 스페인이 있습니다. 이 세값을 평균하면 모델 기반의 예측과 매우 비슷한 5.77이 됩니다. 이 간단한 알고리즘을 k-최근접 이웃k-Nearest Neighbors 희귀라고 합니다(여기서 k = 3입니다).
이전 코드에서 선형 희귀모델을 k-최근접 이웃 희귀로 바꾸려면 아래 한줄을
model = sklearn.linear_model.LinearRegression() 다음과 같이 바꾸면 됩니다.
model = sklearn.neighbors.KNeighborsRegressor(n)neighbors=3)
모든 게 다 잘되면 모델은 좋은 예측을 내놓을 것입니다. 아니면 더 많은 특성(고용률, 건강, 대기오염 등)을 사용하거나, 좋은 훈련 데이터를 더 많이 모으거나, 더 강력한 모델(예를 들면 다항 휘귀모델)을 선택해야 할지 모릅니다.
지금까지의 작업을 요약해 보겠습니다.
- 데이터를 분석합니다.
- 모델을 선택합니다.
- 훈련 데이터로 모델을 훈련시킵니다(즉, 학습 알고리즘이 비용 함수를 최소화하는 모델 파라미터를 찾습니다).
- 마지막으로 새로운 데이터에 모델을 적용해 예측을 하고(이를 추론inference이라고 합니다). 이 모델이 잘 일반화 되길 기대합니다.
이것이 전형적인 머신러닝 프로젝트의 형태입니다. 2장에서 완전한 프로젝트를 진행하면서 직접 경험해볼 것 입니다.
지금까지 많은 부분을 다뤘습니다. 머신러닝이 무엇인지, 왜 유용한지, 머신러닝 시스템이 가장 일반적인 분류는 무엇인지, 그리고 전형적인 머신러닝 프로젝트의 작업 흐름이 어떤지 배웠습니다. 다음 절에서는 학습 과정에서 발생할 수 있는 문제와 정확한 예측을 방해하는 것들에 대해 알아보겠습니다.
2018년 7월 4일 수요일
2018년 7월 3일 화요일
1.2 왜 머신러닝을 사용하는가?
전통적인 프로그래밍 기법을 사용해 어떻게 스팸 필터를 만들 수 있을지 생각해 봅시다.
1. 먼저 스팸에 어떤 단어들이 주로 나타나는지 살펴봅니다. 그러면 '4U', '신용카드', '무료', '굉장한' 같은 단어나 구절이 제목에 많이 나타나는 경향이 있다는 것을 알 수 있습니다. 어쩌면 보낸이의 이름이나 메일 주소, 본문 등에서 다른 패턴을 감지할 수도 있습니다.
2. 발견한 각 패턴을 감지하는 알고리즘을 작성하여 프로그램이 이런 패턴을 발견했을 때 그 메일을 스팸으로 분류하게 합니다.
3. 프로그램을 테스트하고 충분한 성능이 나올 때까지 1단계와 2단계를 반복합니다.
전통적인 접근 방법에서는 문제가 단순하지 않아 규칙이 점점 길고 복잡해지므로 유지 보수하기 매우 힘들어집니다
반면 머신러닝 기법에 기반을 둔 스팸 필터는 일반 메일에 배해 스팸에 자주 나타나는 패턴을 감지하여 어떤 단어와 구절이 스팸 메일을 판단하는 데 좋은 기준인지 자동으로 학습합니다. 그러므로 프로그램이 훨씬 짧아지고 유지 보수하기 쉬우며 대부분 정확도가 더 높습니다.
더군다나 스팸 메일 발송자가 '4U'를 포함한 모든 메일이 차단된다는 것을 안다면 '4U' 대신 'For U'를 쓰기 시작할지도 모릅니다. 전통적인 프로그래밍 방식의 스팸 필터는 'For U' 메일을 구분하기 위해 수정이 필요합니다. 스팸 메일 발송자가 스팸 필터에 대항해 계속 단어를 바꾸면 영원히 새로운 규칙을 추가해야 합니다.
하지만 머신러닝 기반의 스팸 필터는 사용자가 스팸으로 지정한 메일에 유독 'For U'가 자주 나타나는 것을 자동으로 인식하고 별도의 작업을 하지 않아도 자동으로 이 단어를 스팸으로 분류합니다.
머신러닝이 유용한 또 다른 분야는 전통적인 방식으로는 너무 복잡하거나 알려진 알고리즘이 없는 문제입니다. 음성 인식speech recognition을 예로 들 수 있습니다. 'one'과 'two'두 단어를 구부하는 프로그램을 작성한다고 합시다. 단어 'tow'는 높은 피치pitch의 사운드('T')로 시작하므로 높은 피치의 사운드 강도를 측정하는 알고리즘을 하드코딩해서 'one'과 'two'를 구분할 수 도 있습니다. 당연히 이 방법은 소음이 있는 환경에서 수백만명이 말하는 여러 언어로 된 수천개의 단어를 구분하는 것으로 확장하기 어렵습니다. 각 단어를 녹음한 샘플을 사용해 스스로 학습하는 알고리즘을 작성하는 것이 현재 가장 좋은 솔루션입니다.
우리는 머신러닝을 통해 배울 수도 있습니다. 즉, 머신러닝 알고리즘이 학습한 것을 조사할 수 있습니다. 예를 들어 스팸 필터가 충분한 스팸 메일로 훈련되었다면 스팸을 예측하는데 가장 좋은 단어와 단어의 조합이 무엇인지 확인할 수 있습니다. 가끔 예상치 못한 연관 관계나 새로운 추세가 발견되기도 해서 해당 문제를 더 잘 이해하도록 도와줍니다.
머신러닝 기술을 적용해서 대용량의 데이터를 분석하면 겉으로는 보이지 않던 패턴을 발견할 수 있습니다. 이를 데이터 마이닝(data mining)이라고 합니다.
요약하면 머신러닝은 다음 분야에 뛰어납니다.
- 기존 솔루션으로는 많은 수동 조정과 규칙이 필요한 문제: 하나의 머신러닝 모델이 코드를 간단하고 더 잘 수행되도록 할 수 있습니다.
- 전통적인 방슥으로는 전혀 해결 방법이 없는 복잡한 문제: 가장 뛰어난 머신러닝 기법으로 해결 방법을 찾을 수 있습니다.
- 유동적인 환경: 머신러닝 시스템은 새로운 데이터에 적응할 수 있습니다.
- 복잡한 문제와 대량의 데이터에서 통찰 얻기
1. 먼저 스팸에 어떤 단어들이 주로 나타나는지 살펴봅니다. 그러면 '4U', '신용카드', '무료', '굉장한' 같은 단어나 구절이 제목에 많이 나타나는 경향이 있다는 것을 알 수 있습니다. 어쩌면 보낸이의 이름이나 메일 주소, 본문 등에서 다른 패턴을 감지할 수도 있습니다.
2. 발견한 각 패턴을 감지하는 알고리즘을 작성하여 프로그램이 이런 패턴을 발견했을 때 그 메일을 스팸으로 분류하게 합니다.
3. 프로그램을 테스트하고 충분한 성능이 나올 때까지 1단계와 2단계를 반복합니다.
전통적인 접근 방법에서는 문제가 단순하지 않아 규칙이 점점 길고 복잡해지므로 유지 보수하기 매우 힘들어집니다
반면 머신러닝 기법에 기반을 둔 스팸 필터는 일반 메일에 배해 스팸에 자주 나타나는 패턴을 감지하여 어떤 단어와 구절이 스팸 메일을 판단하는 데 좋은 기준인지 자동으로 학습합니다. 그러므로 프로그램이 훨씬 짧아지고 유지 보수하기 쉬우며 대부분 정확도가 더 높습니다.
더군다나 스팸 메일 발송자가 '4U'를 포함한 모든 메일이 차단된다는 것을 안다면 '4U' 대신 'For U'를 쓰기 시작할지도 모릅니다. 전통적인 프로그래밍 방식의 스팸 필터는 'For U' 메일을 구분하기 위해 수정이 필요합니다. 스팸 메일 발송자가 스팸 필터에 대항해 계속 단어를 바꾸면 영원히 새로운 규칙을 추가해야 합니다.
하지만 머신러닝 기반의 스팸 필터는 사용자가 스팸으로 지정한 메일에 유독 'For U'가 자주 나타나는 것을 자동으로 인식하고 별도의 작업을 하지 않아도 자동으로 이 단어를 스팸으로 분류합니다.
머신러닝이 유용한 또 다른 분야는 전통적인 방식으로는 너무 복잡하거나 알려진 알고리즘이 없는 문제입니다. 음성 인식speech recognition을 예로 들 수 있습니다. 'one'과 'two'두 단어를 구부하는 프로그램을 작성한다고 합시다. 단어 'tow'는 높은 피치pitch의 사운드('T')로 시작하므로 높은 피치의 사운드 강도를 측정하는 알고리즘을 하드코딩해서 'one'과 'two'를 구분할 수 도 있습니다. 당연히 이 방법은 소음이 있는 환경에서 수백만명이 말하는 여러 언어로 된 수천개의 단어를 구분하는 것으로 확장하기 어렵습니다. 각 단어를 녹음한 샘플을 사용해 스스로 학습하는 알고리즘을 작성하는 것이 현재 가장 좋은 솔루션입니다.
우리는 머신러닝을 통해 배울 수도 있습니다. 즉, 머신러닝 알고리즘이 학습한 것을 조사할 수 있습니다. 예를 들어 스팸 필터가 충분한 스팸 메일로 훈련되었다면 스팸을 예측하는데 가장 좋은 단어와 단어의 조합이 무엇인지 확인할 수 있습니다. 가끔 예상치 못한 연관 관계나 새로운 추세가 발견되기도 해서 해당 문제를 더 잘 이해하도록 도와줍니다.
머신러닝 기술을 적용해서 대용량의 데이터를 분석하면 겉으로는 보이지 않던 패턴을 발견할 수 있습니다. 이를 데이터 마이닝(data mining)이라고 합니다.
요약하면 머신러닝은 다음 분야에 뛰어납니다.
- 기존 솔루션으로는 많은 수동 조정과 규칙이 필요한 문제: 하나의 머신러닝 모델이 코드를 간단하고 더 잘 수행되도록 할 수 있습니다.
- 전통적인 방슥으로는 전혀 해결 방법이 없는 복잡한 문제: 가장 뛰어난 머신러닝 기법으로 해결 방법을 찾을 수 있습니다.
- 유동적인 환경: 머신러닝 시스템은 새로운 데이터에 적응할 수 있습니다.
- 복잡한 문제와 대량의 데이터에서 통찰 얻기
1.1 머신러닝이란?
일반적인 정의
[머신러닝은] 명식적인 프로그래밍 없이 컴퓨터가 학습하는 능력을 갖추게 하는 연구 분야다.
- 아서 사무엘Arthur Samuel, 1959
공학적인 정의
어떤 작업 T에 대한 컴퓨터 프로그램의 성능을 P로 측정했을 때 경험 E로 인해 성능이 향상됐다면, 이 컴퓨터 프로그램은 작업 T와 성능 측정 P에 대해 경험 E로 학습한 것이다.
- 톰 미첼 Tom Mitchell, 1997
ex) 스팸 필터 = (스팸 메일 + 일반 메일) 샘플
시스템이 학습하는 데 사용하는 샘플 -> 훈련 세트(training set)
훈련 데이터 -> 훈련 사례(training instance, 혹은 샘플)
작업 T = 새로운 메일 스팸인지 구분 경험 E는 훈련 데이터(training data) 성능 측정 P는 직접 정의 이 성능 측정을 정확도(accuracy)라고 부르며 분류 작업에 자주 사용
[머신러닝은] 명식적인 프로그래밍 없이 컴퓨터가 학습하는 능력을 갖추게 하는 연구 분야다.
- 아서 사무엘Arthur Samuel, 1959
공학적인 정의
어떤 작업 T에 대한 컴퓨터 프로그램의 성능을 P로 측정했을 때 경험 E로 인해 성능이 향상됐다면, 이 컴퓨터 프로그램은 작업 T와 성능 측정 P에 대해 경험 E로 학습한 것이다.
- 톰 미첼 Tom Mitchell, 1997
ex) 스팸 필터 = (스팸 메일 + 일반 메일) 샘플
시스템이 학습하는 데 사용하는 샘플 -> 훈련 세트(training set)
훈련 데이터 -> 훈련 사례(training instance, 혹은 샘플)
작업 T = 새로운 메일 스팸인지 구분 경험 E는 훈련 데이터(training data) 성능 측정 P는 직접 정의 이 성능 측정을 정확도(accuracy)라고 부르며 분류 작업에 자주 사용
CHAPTER 1 한눈에 보는 머신러닝
기존 주위 머신러닝
- 광학 문자 판독기 Optical Character Recognition(OCR)
- 스팸 필터 spam filter
추천과 음성 검색으로 발전
기계가 배운다는 것이 정학히 무엇을 의미?
머신러닝
- 지도학습
- 비지도학습
- 온라인 학습
- 배치 학습
- 사례 기반 학습
- 모델 기반 학습
전형적인 머신러닝 프로젝트의 작업 흐름에서 나타나는 주요 문제점과 머신러닝 시스템을 평가하고 튜닝하는 방법
데이터 과학자가 꼭 알아야 할 여러 가지 기초 개념과 용어를 소개
- 광학 문자 판독기 Optical Character Recognition(OCR)
- 스팸 필터 spam filter
추천과 음성 검색으로 발전
기계가 배운다는 것이 정학히 무엇을 의미?
머신러닝
- 지도학습
- 비지도학습
- 온라인 학습
- 배치 학습
- 사례 기반 학습
- 모델 기반 학습
전형적인 머신러닝 프로젝트의 작업 흐름에서 나타나는 주요 문제점과 머신러닝 시스템을 평가하고 튜닝하는 방법
데이터 과학자가 꼭 알아야 할 여러 가지 기초 개념과 용어를 소개
5. 올바른 자료구조 선택하기
파이썬에서 가장 빈번하게 사용하는 자료구조는 리스트, 튜플, 셋, 딕셔너리다. 이 네가지 구조는 모두 데이터의 컬렉션(collection)이다.
파이썬은 리스트를 배열처럼 취급한다. 리스트에서 아이템을 검색할 때 걸리는 시간은 선형적으로 증가하기 때문에, 검색이 가능한 대용량의 데이터를 저장하는 용도로는 실용성이 떨어진다.
투플은 변형이 불가능한 리스트로 한 번 생성되면 변형할 수 없다. 튜플 역시 검색에 걸리는 시간이 선형적으로 증가한다.
리스트나 튜플과 달리 셋에는 순서가 없고, 셋이 담고 있는 아이템은 인덱스가 없다. 셋에는 같은 아이템이 중복으로 저장될 수 없으며, 검색 시간은 준선형적인 O(log(N))으로 증가한다. 회원 명단을 조회하거나 중복 항목을 삭제하는 데 셋을 유용하게 사용할 수 있다(중복된 아이템이 들어 있는 리스트를 셋으로 변환하면 중복된 아이템을 모두 삭제한다).
mList = list(set(myList)) # myList에서 중복된 아이템들을 삭제한다.
리스트 데이터를 셋으로 변환해 더 빠르게 회원 명단을 조회해 보자. 예를 들어 bigList라는 리스트에는 정수 1 부터 1000만까지가 문자열로 변환되어 들어 있다고 하자.
bigList = [str(i) for i in range(10000000)]
"abc" in bigList # 0.2초가 걸린다
bigSet = set(bigList)
"abc" in bigSet #15~30마이크로초가 걸린다. 1만 배나 더 빠르다!
딕셔너리는 키(key)를 값(value)에 매핑한다. 숫자, 불, 문자열, 튜플처럼 해시화 할 수 있는 데이터 타입은 키가 될 수 있고, 같은 딕셔너리에 들어 있다 하더라도 키들은 서로 다른 데이터 타입에 속할 수 있다. 값의 데이터 형식에도 별도의 제약 사항은 없다. 딕셔너리의 검색 시간은 준선형적인 O(log(N))으로 증가한다. 키-값으로 검색해야 할 때 딕셔너리는 매우 유용하다.
튜플(키, 값)이 여러 개 있는 리스트에서 딕셔너리를 만들 수 있다. 그리고 내장된 클래스 생성자(constructor)인 enumerate(seq)를 사용해 seq안의 아이템 순분을 키로 지정한 딕셔너리를 만들 수 있다.
seq = ["alpha", "bravo", "charlie", "delta"]
dict(enumerate(seq))
>>>
{0: 'alpha', 1: 'bravo', 2: 'charlie', 3:'delta'}
딕셔너리를 만드는 또 다른 방법은 키 순서열(kseq)과 값 순서열(vseq)에 클래스 생성자인 zip(kseq, vseq)를 사용하는 것이다.
kseq = "abcd" # 문자열 또한 순서열이다.
vseq = ["alpha", "bravo", "charlie", "delta"]
dict(zip(kseq, vseq))
>>>
{'a': 'alpha', 'c': 'charlie', 'b': 'bravo', 'd': 'delta'}
파이썬에서 enumerate(seq)와 zip(kseq, vseq) 함수는 (자주 쓰는 range() 함수 또한) 리스트 제너레이터(generator)로 사용한다. 리스트 제너레이터는 이터레이터(iterator)인터페이스를 제공하는데, 이는 for 루프를 사용 가능하게 한다. 실제 리스트와 달리 리스트 제너레이터는 요청이 있을 때만 다음 아이템을 생산하는 지연 방식(lazy way)으로 작동한다. 제너레이터는 대용량의 리스트를 소화할 수 있으며, 심지어 '무한한'리스트도 허용한다. list() 함수를 사용해 제너레이터를 리스트로 명시적으로 변환할 수 있다.
파이썬은 리스트를 배열처럼 취급한다. 리스트에서 아이템을 검색할 때 걸리는 시간은 선형적으로 증가하기 때문에, 검색이 가능한 대용량의 데이터를 저장하는 용도로는 실용성이 떨어진다.
투플은 변형이 불가능한 리스트로 한 번 생성되면 변형할 수 없다. 튜플 역시 검색에 걸리는 시간이 선형적으로 증가한다.
리스트나 튜플과 달리 셋에는 순서가 없고, 셋이 담고 있는 아이템은 인덱스가 없다. 셋에는 같은 아이템이 중복으로 저장될 수 없으며, 검색 시간은 준선형적인 O(log(N))으로 증가한다. 회원 명단을 조회하거나 중복 항목을 삭제하는 데 셋을 유용하게 사용할 수 있다(중복된 아이템이 들어 있는 리스트를 셋으로 변환하면 중복된 아이템을 모두 삭제한다).
mList = list(set(myList)) # myList에서 중복된 아이템들을 삭제한다.
리스트 데이터를 셋으로 변환해 더 빠르게 회원 명단을 조회해 보자. 예를 들어 bigList라는 리스트에는 정수 1 부터 1000만까지가 문자열로 변환되어 들어 있다고 하자.
bigList = [str(i) for i in range(10000000)]
"abc" in bigList # 0.2초가 걸린다
bigSet = set(bigList)
"abc" in bigSet #15~30마이크로초가 걸린다. 1만 배나 더 빠르다!
딕셔너리는 키(key)를 값(value)에 매핑한다. 숫자, 불, 문자열, 튜플처럼 해시화 할 수 있는 데이터 타입은 키가 될 수 있고, 같은 딕셔너리에 들어 있다 하더라도 키들은 서로 다른 데이터 타입에 속할 수 있다. 값의 데이터 형식에도 별도의 제약 사항은 없다. 딕셔너리의 검색 시간은 준선형적인 O(log(N))으로 증가한다. 키-값으로 검색해야 할 때 딕셔너리는 매우 유용하다.
튜플(키, 값)이 여러 개 있는 리스트에서 딕셔너리를 만들 수 있다. 그리고 내장된 클래스 생성자(constructor)인 enumerate(seq)를 사용해 seq안의 아이템 순분을 키로 지정한 딕셔너리를 만들 수 있다.
seq = ["alpha", "bravo", "charlie", "delta"]
dict(enumerate(seq))
>>>
{0: 'alpha', 1: 'bravo', 2: 'charlie', 3:'delta'}
딕셔너리를 만드는 또 다른 방법은 키 순서열(kseq)과 값 순서열(vseq)에 클래스 생성자인 zip(kseq, vseq)를 사용하는 것이다.
kseq = "abcd" # 문자열 또한 순서열이다.
vseq = ["alpha", "bravo", "charlie", "delta"]
dict(zip(kseq, vseq))
>>>
{'a': 'alpha', 'c': 'charlie', 'b': 'bravo', 'd': 'delta'}
파이썬에서 enumerate(seq)와 zip(kseq, vseq) 함수는 (자주 쓰는 range() 함수 또한) 리스트 제너레이터(generator)로 사용한다. 리스트 제너레이터는 이터레이터(iterator)인터페이스를 제공하는데, 이는 for 루프를 사용 가능하게 한다. 실제 리스트와 달리 리스트 제너레이터는 요청이 있을 때만 다음 아이템을 생산하는 지연 방식(lazy way)으로 작동한다. 제너레이터는 대용량의 리스트를 소화할 수 있으며, 심지어 '무한한'리스트도 허용한다. list() 함수를 사용해 제너레이터를 리스트로 명시적으로 변환할 수 있다.
2018년 7월 1일 일요일
4. 기본 문자열 함수 이해하기
문자열은 컴퓨터와 인간의 세계를 잇는 상호 작용의 기본 단위다. 거의 모든 원천 데이터는 문자열 형태로 저장되어 있다. 여기서는 텍스트 문자열을 읽고 변형하는 방법을 배운다.
여기서 다루는 모든 함수는 내장된 str클래스의 멤버다.
대.소문자 변환(case conversion)함수는 원래 문자열 s의 복사본을 반환한다. lower()함수는 모든 문자를 소문자로 변환하고, upper() 함수는 모든 문자를 대분자로 변환한다. 그리고 capitalize() 함수는 첫 번째 문자를 대문자로 변환하고, 나머지 문자들은 소문자로 변환한다. 이 함수들은 아파벳이 아닌 문자는 무시한다. 대.소문자 변환 함수는 62쪽에서 다룰 정규화의 가장 중요한 요소다.
프레디케이트(predicate)함수는 해당 문자열 s가 특정 클래스에 속하는지에 따라 True나 False를 반환한다. islower()함수는 모든 알파벳 문자가 소문자인지 체크한다. isupper()함수는 모든 문자가 대문자인지 확인한다. isspace()함수는 모든 문자가 공백인지 체크한다. isdigit()함수는 모든 문자가 0에서 9 사이 숫자인지 확인한다. 그리고 isalpha() 함수는 모든 문자가 a~z, A~Z사이의 아파벳 문자인지 체크한다. 여러분도 이 함수들을 사용해 단어가 정확하지, 정수가 양수인지, 올바르게 뛰어쓰기를 했는지 등을 테스트할 수 있다.
외부 파일이나 데이터베이스, 웹에서 데이터를 가져왔다면 때때로 파이썬은 문자열 데이터를 문자열이 아닌 바이너리 배열로 표현한다. 이때 파이썬에서는 바이너리 배열 앞에 b를 붙여서 표기한다. 예를 들어 bin = b"Hello"는 바이너리 배열이고, s="Hello"는 문자열이다. 여기서 s[0]은 'H'이고 b[0]은 72인데 72문자 'H'에 해당하는 ASCII문자코드(CHARCODE)다. 디코딩(decoding)함수는 바이너리 배열을 문자열로 변환한다. bin.decode()는 바이너리 배열을 문자열로 변환하고, s.encode()는 문자열을 바이너리 배열로 변환한다. 많은 팡썬 함수는 문자열로 변환된 상태의 바이너리 데이터를 처리한다.
문자열 처리의 첫 번째 단계는 원치 않는 공백(새로운 줄과 탭을 포함한)을 제거하는 것이다. lstrip()(왼쪽 공백 제거)과 rstrip()(오른쪽 공백 제거), strip() 함수는 문자열의 모든 공백을 제거한다(문자 사이의 공백은 제거하지 않는다). 이렇게 공백을 제거하다 보면 아무것도 없는 빈 문자열이 될 수도 있다.!
"Hello, world! \t\t\n".strip()
>>>
'Hello, world!'
때때로 문자열은 공백, 클록이나 쉼표 등 구분자로 분리된 여러 개의 토큰으로 구성되어 있다. split(delim=" ") 함수는 delim을 구분자로 사용해 문자열 s를 부분 문자열의 리스트로 쪼갠다. 구분자를 지정하지 않았다면 파이썬이 공백을 사용해 문자열을 쪼개고, 연속해서 공백이 있으면 이를 하나의 공백으로 인식한다.
"Hello, world!".split() # Hello, 와 world!사이에 2개의 공백이 있다.
>>>
['Hello', 'world!']
"Hello, world!". split(" ") # Hello, 와 world! 사이에 2개의 공백이 있다.
>>>
['Hello', ' ', 'world!']
"www.networksciencelab.com".split(".")
>>>
['www', 'networksciencelab', 'com']
자매 함수인 join(ls)는 객체 문자열을 접착제로 사용해 문자열 리스트 ls를 하나의 문자열로 붙인다. join()함수를 사용하면 문자열 조각을 재조합할 수 있다.
", ".join(["alpha", "bravo", "charlie", "delta"])
>>>
'alpha, brawo, chalie, delta'
앞의 예제에서 join() 함수는 접착제 문자열 사이에만 넣고, 첫 번째 문자열 앞이나 마지막 문자열 뒤에는 넣지 않는 것을 볼 수 있다. 문자열을 자르고 다시 합치는 것은 구분자를 다른 문자열로 치환하는 것과 같다.
"-".join("1.617.305.1985".split("."))
>>>
'1-617-305-1985"
이따금 여러분은 이 두가지 함수를 같이 사용해서 필요 없는 공백을 문자열에서 제거하고 싶을 것이다. 정규 표현식에 기반한 치환을 사용하면 같은 결과를 얻을 수 있다.
" ".join("This string\n\r has many\t\tspaces".split())
>>>
'This string has many spaces'
find(needle) 함수는 해당 문자열에서 부문 문자열 needle이 처음 등장하는 인덱스를 반환하며, 부분 문자열이 없ㅇ르 때는 -1을 반환한다. 이 함수는 대.소문자를 구분(case-sensitive)한다. 문자열에서 특히 관심 있는 부분을 찾는데 find()함수를 활용할 수 있다.
"www.networksciencelab.com".find(".com")
>>>
21
count(needle) 함수는 대상 문자열에서 부문 문자열 needle이 등장하는 횟수를 반환한다. 이 함수 역시 대.소문자를 구분한다.
"www.networksciencelab.com".count(".")
>>>
2
문자열은 데이터 처리 프로그램을 구성하는 요소이지만 유일한 구성 요소는 아니며, 가장 효율적인 요소라고도 할 수 없다. 여러분은 앞으로 리스트(list), 튜플(tuple), 셋(set), 딕셔너리(dictionary)를 사용해 문자열과 수치형 데이터를 묶고, 더 효율적인 방법으로 검색하고 정렬하게 될 것이다.
여기서 다루는 모든 함수는 내장된 str클래스의 멤버다.
대.소문자 변환(case conversion)함수는 원래 문자열 s의 복사본을 반환한다. lower()함수는 모든 문자를 소문자로 변환하고, upper() 함수는 모든 문자를 대분자로 변환한다. 그리고 capitalize() 함수는 첫 번째 문자를 대문자로 변환하고, 나머지 문자들은 소문자로 변환한다. 이 함수들은 아파벳이 아닌 문자는 무시한다. 대.소문자 변환 함수는 62쪽에서 다룰 정규화의 가장 중요한 요소다.
프레디케이트(predicate)함수는 해당 문자열 s가 특정 클래스에 속하는지에 따라 True나 False를 반환한다. islower()함수는 모든 알파벳 문자가 소문자인지 체크한다. isupper()함수는 모든 문자가 대문자인지 확인한다. isspace()함수는 모든 문자가 공백인지 체크한다. isdigit()함수는 모든 문자가 0에서 9 사이 숫자인지 확인한다. 그리고 isalpha() 함수는 모든 문자가 a~z, A~Z사이의 아파벳 문자인지 체크한다. 여러분도 이 함수들을 사용해 단어가 정확하지, 정수가 양수인지, 올바르게 뛰어쓰기를 했는지 등을 테스트할 수 있다.
외부 파일이나 데이터베이스, 웹에서 데이터를 가져왔다면 때때로 파이썬은 문자열 데이터를 문자열이 아닌 바이너리 배열로 표현한다. 이때 파이썬에서는 바이너리 배열 앞에 b를 붙여서 표기한다. 예를 들어 bin = b"Hello"는 바이너리 배열이고, s="Hello"는 문자열이다. 여기서 s[0]은 'H'이고 b[0]은 72인데 72문자 'H'에 해당하는 ASCII문자코드(CHARCODE)다. 디코딩(decoding)함수는 바이너리 배열을 문자열로 변환한다. bin.decode()는 바이너리 배열을 문자열로 변환하고, s.encode()는 문자열을 바이너리 배열로 변환한다. 많은 팡썬 함수는 문자열로 변환된 상태의 바이너리 데이터를 처리한다.
문자열 처리의 첫 번째 단계는 원치 않는 공백(새로운 줄과 탭을 포함한)을 제거하는 것이다. lstrip()(왼쪽 공백 제거)과 rstrip()(오른쪽 공백 제거), strip() 함수는 문자열의 모든 공백을 제거한다(문자 사이의 공백은 제거하지 않는다). 이렇게 공백을 제거하다 보면 아무것도 없는 빈 문자열이 될 수도 있다.!
"Hello, world! \t\t\n".strip()
>>>
'Hello, world!'
때때로 문자열은 공백, 클록이나 쉼표 등 구분자로 분리된 여러 개의 토큰으로 구성되어 있다. split(delim=" ") 함수는 delim을 구분자로 사용해 문자열 s를 부분 문자열의 리스트로 쪼갠다. 구분자를 지정하지 않았다면 파이썬이 공백을 사용해 문자열을 쪼개고, 연속해서 공백이 있으면 이를 하나의 공백으로 인식한다.
"Hello, world!".split() # Hello, 와 world!사이에 2개의 공백이 있다.
>>>
['Hello', 'world!']
"Hello, world!". split(" ") # Hello, 와 world! 사이에 2개의 공백이 있다.
>>>
['Hello', ' ', 'world!']
"www.networksciencelab.com".split(".")
>>>
['www', 'networksciencelab', 'com']
자매 함수인 join(ls)는 객체 문자열을 접착제로 사용해 문자열 리스트 ls를 하나의 문자열로 붙인다. join()함수를 사용하면 문자열 조각을 재조합할 수 있다.
", ".join(["alpha", "bravo", "charlie", "delta"])
>>>
'alpha, brawo, chalie, delta'
앞의 예제에서 join() 함수는 접착제 문자열 사이에만 넣고, 첫 번째 문자열 앞이나 마지막 문자열 뒤에는 넣지 않는 것을 볼 수 있다. 문자열을 자르고 다시 합치는 것은 구분자를 다른 문자열로 치환하는 것과 같다.
"-".join("1.617.305.1985".split("."))
>>>
'1-617-305-1985"
이따금 여러분은 이 두가지 함수를 같이 사용해서 필요 없는 공백을 문자열에서 제거하고 싶을 것이다. 정규 표현식에 기반한 치환을 사용하면 같은 결과를 얻을 수 있다.
" ".join("This string\n\r has many\t\tspaces".split())
>>>
'This string has many spaces'
find(needle) 함수는 해당 문자열에서 부문 문자열 needle이 처음 등장하는 인덱스를 반환하며, 부분 문자열이 없ㅇ르 때는 -1을 반환한다. 이 함수는 대.소문자를 구분(case-sensitive)한다. 문자열에서 특히 관심 있는 부분을 찾는데 find()함수를 활용할 수 있다.
"www.networksciencelab.com".find(".com")
>>>
21
count(needle) 함수는 대상 문자열에서 부문 문자열 needle이 등장하는 횟수를 반환한다. 이 함수 역시 대.소문자를 구분한다.
"www.networksciencelab.com".count(".")
>>>
2
문자열은 데이터 처리 프로그램을 구성하는 요소이지만 유일한 구성 요소는 아니며, 가장 효율적인 요소라고도 할 수 없다. 여러분은 앞으로 리스트(list), 튜플(tuple), 셋(set), 딕셔너리(dictionary)를 사용해 문자열과 수치형 데이터를 묶고, 더 효율적인 방법으로 검색하고 정렬하게 될 것이다.
3. 보고서 구조
프로젝트 보고서는 우리가 데이터 분석 의뢰인(고객)에게 전달하는 결과물이다. 보고서는 보통 다음 항목으로 구성된다.
- 요약(짧은 프로젝트 설명)
- 서론
- 데이터 수집과 처리에 사용한 방법
- 분석 결과(중간 결과나 중요도가 떨어지는 내용은 포함하지 않고 부록에 삽입)
- 결론
- 부록
부록에는 부차적이 결과와 차트뿐만 아니라 데이터를 처리하는 데 사용한 모든 재사용 코드를 기록한다. 스크립트에는 주석을 충실히 달아서 별도의 파라미터 입력이나 사용자 상호 작용 없이도 실행할 수 있어야 한다.
마지막으로 원천 데이터를 제출하는 것도 매우 중요하다. 의뢰인이 데이터를 제공했거나 해당 파일을 변형하지 않았다면, 제출하는 원천 데이터는 코드를 재사용 가능한 방법으로 실행할 수 있어야 한다. 보통 첨부한 모든 데이터 파일의 출처와 포맷은 README 파일에 기록한다.
이러한 보고서 구조를 반드시 지켜야 할 필요는 없다. 데이터 분석 의뢰인의 요청이나 상식적인 판단에 따라 다른 대안을 사용해도 좋다.
- 요약(짧은 프로젝트 설명)
- 서론
- 데이터 수집과 처리에 사용한 방법
- 분석 결과(중간 결과나 중요도가 떨어지는 내용은 포함하지 않고 부록에 삽입)
- 결론
- 부록
부록에는 부차적이 결과와 차트뿐만 아니라 데이터를 처리하는 데 사용한 모든 재사용 코드를 기록한다. 스크립트에는 주석을 충실히 달아서 별도의 파라미터 입력이나 사용자 상호 작용 없이도 실행할 수 있어야 한다.
마지막으로 원천 데이터를 제출하는 것도 매우 중요하다. 의뢰인이 데이터를 제공했거나 해당 파일을 변형하지 않았다면, 제출하는 원천 데이터는 코드를 재사용 가능한 방법으로 실행할 수 있어야 한다. 보통 첨부한 모든 데이터 파일의 출처와 포맷은 README 파일에 기록한다.
이러한 보고서 구조를 반드시 지켜야 할 필요는 없다. 데이터 분석 의뢰인의 요청이나 상식적인 판단에 따라 다른 대안을 사용해도 좋다.
피드 구독하기:
글 (Atom)