읽기전

  • 데이터를 많이 들여다 보려고 노력하고 있는데, 이거 참 기본이 있어야지...

  • 특히 데이터를 어떻게 들여다 볼 것인가? 에 대한 고민이 필요해서 구매 한 책.

  • 기존 딥러닝 책들은, 이미 잘 정제 되어 있거나, 필요한 값들을 이미 선별해 둔 책이 많다.

  • 하지만, 실제 데이터들은 잘 정제되어 있지도, 어떠한 값을 딥러닝에 넣어야 할지도 모르니....

  • 에라, 모르겠다. 걍 딥러닝에 다 때려 박으면 되지 싶다가도,

    • 그래도 기본은 알아야지.
    • 필요한 것만 때려 박으면 더 잘 되겠지.
  • 싶어서 구매한 책

  • 이 책에 있는 대부분의 예제는 전체 소스코드가 나와 있지 않고, 설명이 생략 된 것도 꽤나 된다.

  • 그러므로 초보자가 읽기에 적당하지 않은듯 하다.

책 읽기

서문

옮긴이의 말

  • 하지만 너무나 다양한 데이터의 종류가 특성에 따라 경험적으로 수행돼 왔을 뿐, 이를 범용적으로 적용하는 방법에 대한 책이나 논문이 거의 없었다.
  • 머신 러닝 입문자들에게는 피처 엔지니어링에 대한 원리를 배우고 실습을 통해 실력을 높일 수 있는 좋은 기회가 될 것이며, 데이터 과학에 종사하는 분들에게는 그동안 경험적으로 수행해 오던 피처 엔지니어링 기법들을 암묵지에서 형식지로 정리하는 계기가 될 것이다.

들어가며

  • 모델은 피처(feature)를 입력으로 사용한다. 피처는 원시 데이터의 숫자적인 표현이다..
  • 피처 엔지니어링은 원시 데이터로부터 피처를 추출하고 이를 머신 러닝 모델에 적합한 형식으로 변환하는 작업이다.
  • 데이터와 모델은 매우 다양하기 때문에 피처 엔지니어링 방법으로 일반화 하기 어렵다.

1장 머신 러닝 파이프라인

데이터

  • 데이터, 모델, 피처, 모델 평가
    • 실제 세계의 현상에 대한 관측 결과
    • 데이터의 각 조각은 현실의 제한된 한 측면에 대한 창을 제공
    • 원시 데이터는 숫자가 아닌 경우가 많다. ( 앨리스가 수요일에 책을 샀다. )
    • 피처는 원시 데이터의 숫자적인 표현이다.
    • 우리가 해결하고자 과제에 적합한 모델에, 잘 들어 맞는 피처를 만들어야 한다.
    • 피처가 적으면 제대로 과제를 수행하지 못하고, 피처가 많아도 필요 없는 피처로 인해 모델의 학습에 많은 비용과 어려움이 있을 수 있다.
  • 원본 소스가 통찰력까지 가기는...
    • 소스 ->(추출 및 통합)-> 원시 데이터 -> (정제 및 변환) -> 피처 -> 모델링 -> 통찰력
    • 여기서 "정제 및 변환" 부분이 피처 엔지니어링 부분이다.

2장 숫자를 위한 멋진 트릭

  • 이미 숫자는 수학적 모델로 처리하기 쉬운 형식.
  • 하지만 좋은 피처는 데이터를 가장 두드러진 특징을 표현할 뿐만 아니라, 모델의 가정에도 맞아야 한다. 그러므로 피처 엔지니어링이 필요.
  • 고려사항
    • 값의 크기 : 양수? 음수?, 구간을 나눠야하나? 숫자가 누적되나?
    • 스케일 : 가장 큰 값, 가장 작은 값, 둘의 차이가 몇자리 수. 출력 값이 커질 수 있나? 출력값이 바이너리면?
    • 숫자 피처의 분포
    • 여러 피처를 조합해 더 복잡한 피처를 만들 수도 있음

스칼라, 벡터, 공간

  • 스칼라(scalar) : 단일 숫자 피처
  • 벡터(vector) : 방향이 있는 스칼라의 리스트, 벡터는 벡터공간내에 위치.
  • 벡터는 공간상의 한 점( 종종 원점에서 그 점까지의 선이나 화살표로 그린다. )

카운트 처리

  • 노래나 영화를 플레이 한 횟수 등 이런 카운트
  • 누군가가 조작하기가 쉬우므로, 그래도 사용할지, 존재 여부만 처리 할지, 몇개의 구간으로 나눌지 등을 고민해야 한다.

바이너리 변환

  • '견고한 척도'(통계 용어에서 "견고함"은 해당 기업이 매우 다양한 조건하에서도 잘 작동함을 말한다. 라는 말이 있는데.. 이걸 이쪽 세상에서는 로버스터(robust)라는 용어를 훨씬 더 많이 사용한다.
  • 데이터의 값이 너무 많이 차이가 나면, 그냥 1 과 0 으로 나눠 주는것도 가능하다.

양자화 또는 비닝

  • 비닝(binning)은 구간화 정도로 생각하면 되겠다.
  • 양자화랑 비슷한 듯.
  • 쉽게 말하면, 값을 구간을 두고 정리 한다는것. ( 10대, 20대, 30대 등 )
  • 고정폭 비닝
    • 나이를 가지고 할 것이라면, 10대, 20대로 할 수도 있지만, 삶의 단계에 맞게, 초등학교, 중학교, 고등학교, 대학교의 나이로 나누는것이 더 좋을 수도 있다.
    • 여러 자리수라면, 0 ~ 9, 10 ~ 100, 100 ~ 1000 등으로 나눌 수도 있다.
  • 분위수(quantile) 비닝
    • 그냥 고정폭 비닝은, 중간에 빈 값이 많으면 데이터가 없는 구간이 너무 많다.
    • 걍 전체 값의 1/2이나 1.4 단위, 혹은 1/10 단위로 나눠서 배치한다.

로그 변환

  • 작은 숫자가 많고, 큰 숫자가 듬성 듬성 적게 데이터가 존재한다면, 작은 숫자들을 좀 더 잘게 쪼개야 하고, 큰 숫자를 좀 더 모아줘야 한다.
  • 이럴때는 로그 변환을 사용하면 된다.
  • log10(x) 는
    • 1 ~ 10 사이의 숫자를 0 ~ 1 사이로 배치
    • 10 ~ 100 사이의 숫자를 1 ~ 2 사이로 배치
    • 100 ~ 1000 사이의 숫자를 2 ~ 3 사이로 배치 할 수 있다.
  • 즉, 큰 수의 변화량을 작은 변화량으로 바꿀 수 있어, 상대적으로 작은 숫자의 변화량을 더 잘 표현할 수 있게 된다.
  • 뒤에 Box-Cox 라는것도 나오는데, 잘 모르겠지만, 결국 데이터를 잘 분산한다는것에 목적이 있는 듯 하다.

피처 스케일링 또는 정규화

  • 위도나 경도는 피처의 숫자 값에 한계가 있음. 하지만 카운트는 한계가 없음.
  • 모델이 입력 피처의 스케일링(값 범위)에 민감하다면, 피처를 적절히 스케일링 해 주어야 한다.
  • 이걸 피처 스케일링, 혹은 피처 정규화(normalizataion)이라고 부른다.

min-max 스케일링

  • 제일 작은 값을 0, 제일 큰 값을 1로 변환
  • min-max scailing

표준화(분산 스케일링)

  • 피처 표준화(standardization) : 모든 데이터 포인트에 대한 피처의 평균을 빼고 분산으로 나눈다.
  • 그래서 분산 스케일링이라고도 부름
  • 스케일링된 피처의 결과는 평균이 0, 분산이 1
  • 즉 0을 중심으로 좌우로 적절히 데이터를 배치한다.

l2 정규화

  • 원본 피처 값을 유클리드 노름(norm)으로 불리는 l2 노름으로 정규화한다.(나눈다)
  • 원본 값 / (모든 데이터에 제곱을 한 뒤, 이를 모두 더하고, 다시 제급근(루트)를 씌워 준다.)
  • 자세한건 나도 모르니깐 통과.
  • 이상과 같은 피처스케일링은, 피처의 분포의 모양을 바꾸지는 않는다. 다만 분포에 대한 스케일만 변경한다.
  • 예를들면 원본 데이터를 이용해서 만든 그래프와, min-max를 이용해서 만들어진 그래프의 모양은 동일하다. 다만, 피처의 스케일만 달라져 있는 것이다.
  • 입력 피처들의 기준이 다를때는 비슷하게 만들어 주는것이 좋다. 방문자 수가 100만명 단위인데, 구매자 수가 100명 단위라면, 균형을 맞춰줄 필요가 있다.
  • 그렇지 않으면 모델 학습 알고리즘에서 수치 안정성 문제를 일으킬 수 있다.

상호작용 피처

  • 한개의 피처만을 사용하는것이 아니라, 두개의 피처를 모두 사용하는 방법.
  • 예를들면, "서울"에서 "30대" 같은것.
  • 고객의 위치만으로 예측하는것, 혹은 고객의 나이만으로 예측하는것 보다는, 둘 다의 값으로 예측하는것이 더 정확
  • 하지만, 더 복잡한 계산이 필요. 어떤 피처들 선택할 것인가도 문제.

피처 선택

  • 필요 없는 피처는 제거하는것이 모델의 복잡성을 줄일 수 있음.
  • 그러면 정확도는 거의 저하시키지 않고, 빠르게 연산 할 수 있을 것임.
  • 어느 피처가 중요한지 알아 내기 위해서, 오히려 전체 학습 시간이 오래 걸릴 수도 있음.

필터링

  • 피처와 목표 변수 사이의 상관관계, 상호 정보량등을 계산해 크게 영향을 미치지 않는것을 걍 제거.
  • 쉽게 할 수 있지만, 내가 필터링 할 피처를 잘못 선택할 수도 있다.
  • 아예 해당 데이터를 사용하지 않을 것이므로, 유용한 필터를 제거 할 수 있으므로, 보수적으로 선택해야 한다.

레퍼메소드

  • 비용은 많이 들지만, 피처의 하위 집합을 시험해 볼 수 있도록 해 줌.
  • 정보량이 많지 않을 수도 있지만, 조합했을 경우 유용한 것일 수 있으므로 실수를 방지 해 줌.

내장 메소드

  • 모델 학습 과정의 일부로서 피처 선택을 수행
  • 의사결정트리는 각 학습 단계에서 트리를 분할하기 위한 피처를 선택하게 되어 있음.
  • 선형 모델 학습에 사용하는 l1 정규화도, 모델 학습 과정의 일부로 피처를 선택하게 되어 있음.
  • 레퍼메소드 방식보다 강력하지 않지만, 비용이 절감
  • 필터링과 비교 했을 때 보다는 모델에 적합한 피쳐를 선택,
  • 필터링과, 내장 메소드 사이의 적절한 균현을 이룸
  • 이 책의 설명 범위가 벗어난다면서, 여기에 대한 설명을 다른곳을 찾아 보라고 함.

요약

  • 일반적인 숫자 피처에 대한 피처 엔지니어링을 설명
  • 통계적인 머신러닝에서 모든 데이터는 결국 숫자 피처로 귀결
  • 결국 몇가지 숫자 피처 엔지니어링 기법이 필요

3장 텍스트 데이터: 플래트닝, 필터링, 청킹

  • 문장이 있다면, 어느 부분을 추출해야 하나?
  • 단어 카운트 총계를 기초로 하는 가장 단순한 표현인 BoW
  • 텍스트와 매우 깊은 연관이 있는 변환 tf-idf

bag-of-x: 자연어 텍스트를 평면 벡터로 변환

  • 결과가 단순하고 해석 가능할때가 가장 좋음, 단순해야 시도해 보기 좋고, 디버깅이 쉽다.
  • 우선 단순하게 시작하고, 필요한 경우 복잡성을 더하도록 하자.
  • 문서를 분류하는 작업은 종종 단어 카운트 통계만으로도 충분함.
  • 특정 단어의 존재 유무가 문서의 주제를 잘 나타내는 지표가 됨.

BoW

  • Bag of word
  • 단어별 단어가 노출되는 갯수를 테이블로 만든것.
  • 이러한 단어별 카운트의 분포에 따라서 문서가 어떠한 특징을 가지는지 알 수 있다.
  • 텍스트는 원래 플랫(flat)한 구조이나, BoW는 단어가 몇번 나오는지만 저장해 둔다.
  • 텍스트는 순서(Sequance)를 가지나, BoW는 순서도 없다. 단어별 계층 구조도 없다.
  • 오직 등장한 횟수만...
  • 이렇게 단어와 등장 횟수를 피처를 만들고, 어떠한 문장을 분석해 보도록 하자.
  • 각 단어가 1개의 차원이 된다. 등장 횟수가 해당 피처의 값이 된다.
    • 특정 문장에서 cute라는 단어와 puppy라는 단어가 각각 몇번 나왔는지를 x, y로 두면 그 문장이 2차원의 어느 위치에 있는지 알 수 있다.
    • 특정 문장에서 cute, puppy, extremely 이라는 단어가 각 몇 번 나왔는지를 x, y, z로 두면 그 문장이 3차원에서 어느 위치에 있는지 알 수 있다.
    • 각 단어와 등장한 횟수가 피처가 되고, 문장이 어느 위치에 있는지 알 수 있다.
  • 반대로 각 문장 자체를 피처로 두고, 단어들을 배치해 볼 수도 있을 것이다. 이러한 것은 bag-of-documents 라고 한다. ( 자세한건 4장에 설명 된다고... )
  • BoW는 문장을 단어로 분해 할 때 의미가 파괴 될 수 있다. not bad의 경우 '나쁘지 않다.'라는 뜻인데, 분해를 해 버리면 둘다 나쁘다라는 의미를 표현하게 된다.
  • 이러한 문제를 일부 해결 하기 위해 bag-of-n-grams를 사용한다.
  • BoW는 유용한 경험적 방법이지만, 텍스트의 정확한 의미를 파악하는것과는 거리가 멀다.

bag-of-n-grams

  • BoW는 단어 당 하는건데, 여기는 n개의 연속된 단어로 하는거다. 1개로 되어 있으면, 1-gram, unigram 이다.
  • 중첩된 시퀀스를 n-gram이라고...
  • "Emma knocked on the door'를 2-gram으로 나타내면
    • Emma knocked
    • knocked on
    • on the
    • the door
  • 로 나타낼 수 있다.
  • 하지만 당연히 BoW 보다 훨씬 더 많은 피처 갯수가 생긴다.

정제된 피처를 위한 필터링

  • 단어를 사용할 때는 필요한 정보(시그널)과 노이즈(필요 없는 정보)를 분리해야 함.

불용어

  • 분류와 검색은 텍스트이 대한 깊은 이해를 요구하지 않음(의미까지 명확하게 파악하지 않아도 된다는 뜻일까?)
  • 분류와 같은 섬세하지 않은 작업에서 대명사, 관사, 전치사의 가치는 그다지 크지 않다.
  • 하지만 섬세한 의미론적 이해를 요구하는 감성 분석에서는 매우 다를 수 있다.
  • 영어의 불용어 리스트는, 파이썬 NLP 패키지인 NLTK에 수 많은 언어에 대해 불용어 리스트를 가지고 있다.

빈도 기반 필터링

  • 얼마나 단어가 나오는지를 확인하면, 상용어를 필터링 하기 쉽다.
  • 빈출 단어
    • 또한 단어가 너무 많이 나와도 의미를 파악하기 어려울 수 있다.
    • 의사 회의록은 'House of Commons(하원)'이라는 단어가 많이 나와서 house라는 단어가 너무 많이 나옴.
    • 이를 어떻게 처리 할 것인가를 정하는게 어렵다. 또한 얼마나 많이 등장 할 때만 의미를 부여/제거 할 것인가? 를 정하는것도 쉽지는 않다.
  • 희귀 단어
    • 잘 알려있지 않은 단어거나, 철자가 틀린 것일 수도 있음.
    • 통계적인 모델에서는, 한 두번 나오는건 잡음(노이즈-noise)에 가깝다.
    • 아주 적은 횟수가 등장하는 단어 때문에, 분류를 잘못 할 수도 있다.
    • 또한, 이러한 단어들을 모두 포함해서 연산을 하게 되면 필요 없는 계산을 많이 해야 한다.
    • 책에서 설명하는 Yelp 데이터 160만개 리뷰는 35만개의 고유 단어가 포함되어 있고, 약 23만개의 단어가 1개 혹은 2개의 리뷰에서만 나온다. 즉, 60%의 단어가 크게 의미를 가지지 않을 수도 있다는 뜻이다.
    • 이러한 피처를 모두 모델을 만들때 추가하게 되면, 계산 비용과 저장 비용이 많이 들게 된다. 그러므로 이러한 단어들을 적절히 제거해 주어야 한다.
    • 텍스트의 문장이 매우 짧은 경우, 통계적 의미를 찾기 어려울 수 있기 때문에, 이러한 문장을 제외해야 할 수도 있다. 하지만 트위터는 짧은 문장만을 가질 수 있으므로, 다른 방식의 기법을 사용해야 한다.
  • 어간 추출
    • 어간(語幹) : 활용어의 활용에서 변하지 않는 부분. '읽는다, 읽느냐, 읽고…' 등에서의 '읽'. 어간에 어미 '-다'를 붙인 것을 기본형이라고 하여 사전의 표제어로 올림. 줄기.
    • 단어를 공백이나 구둣점으로 잘라서 세면, 같은 의미를 가진 단어를 모두 따로 카운트 하게 된다. 'swin', 'swinging'은 의미가 비슷하지만 서로 다르다고 카운트 된다.
    • 통계적인 데이터로 처리 할 때에는 어간(stem)을 추출해서 단어의 기본형으로 변환하여 저장하는것이 좋은 경우가 많다.
    • 하지만, news 와 new는 전혀 다른 의미를 가지지만, 같은 new로 어간 추출이 될 수도 있다. 그러므로 항상 어간 추출을 사용해야 한다는것은 아님을 명심하자.

의미의 단위: n-grams에서 구문까지

파싱과 토큰화

  • 문자열에 의미가 있는 텍스트가 아닌게 많다.
  • 또한, 의미를 구분해 주는것도 있을 것이다. 이메일의 from, to 등.
  • 단어를 쪼갤때, 공백, 구둣점 등으로 나누면 된다.
  • n-grams으로 n개를 쪼갤때는, 문서가 아니라 "문장" 단위로 되어야 한다.
  • 즉, 마침표가 있으면 n-grams를 늘리면 안된다.
  • 하지만, word2vec 과 같이 복잡한 것을 할 때는, 단락에 적용할 수도 있다.
  • 암튼, 그냥 상황에 따라서 잘 나눠서 하면 된다는것 같다.

구문 탐색을 위한 연어 추출

  • 연어. 연달아 적힌 단어가 의미를 가질 수 있다.
  • strong tea는 "진한 차" 인데, 두 단어를 쪼개면, "물리력이 강하다"와 "차"로 나눠진다. 그러므로 의미가 달라진다. 이러한것을 연어라고 한다.
  • 'cute puppy'는 'cute'와 'puppy'의 의미를 합쳤을때 동일한 의미를 가진다. 이런건 연어가 아님.
  • 연어가 꼭 연속되어 나오라는 법도 없고, 모든 연속된 단어가 연어라는 법도 없다.
  • 그래서 너무 어려움. 통계적인 기법을 사용한다.
빈도 기반 방법
  • 많이 나타나는 n-grams을 보는 법. bigrams등의 빈도수를 실제로 확인해 보고, 의미 있는것을 찾을 수 있다.
연어 추출을 위한 가설 검증
  • 책에 나오는 복잡한 내용은 생략...
청킹과 품사 태깅
  • 주제를 찾는 경우에는 명사에 가장 관심이 있을 수 있음.
  • 즉, 품사를 찾아야 함.
  • 걍 형태소 분석을 한다는것으로 보인다. 통과. ㅋㅋㅋ

요약

  • Bag of Word
    • BoW, 단어를 하나씩 Bag에 넣는것
    • 단순 검색에는 좋으나, 문맥이 유지 되지 않아 의미를 파악하기 어려움
  • Bag of n grams
    • n-gram을 Bag에 넣는것, 연속된 단어를 n개 조합해서 저장
    • 하지만 연속된 단어 n개의 조합이 너무 많아서 데이터 양이 너무 많음
    • 데이터 양이 많다면, 의미를 가지는 데이터를 더 찾기 어려울 수 있다.
  • 연어(구문, 상용구) 추출
    • 연속된 구문을 보고 의미가 있고, 없는 것들을 통계적으로 추출할 수 있다.
  • 이 장에서 설명한 문장을 처리하는 방법은, 문장을 쪼개 단어의 bag으로 만들게 된다. 그러므로 이러한 방식으로는 문장의 의미를 구체적으로 파악하기는 어렵다.

4장 피처 스케일링의 효과: BoW에서 tf-idf로

  • BoW 는 필요 없는 단어들이 강조 될 수 있다. "is", "the", "and" 는 문장에서 너무 많이 나올 것이다.
  • 하지만, 문장에서 "happy", "gloomy" 등은 자주 등장하지는 않지만, 문장의 의미를 잘 표현한다. 이러한 것들을 잘 찾아 주는 방법을 찾아야 한다.

tf-idf: BoW 비틀기

  • tf-idf : term frequency-inverse document frequency
  • tf-idf : 용어 빈도 - 역 문서 빈도
    • 각 단어의 카운트를 해당 단어가 나타나는 문서의 수로 나눈 정규화 카운트
    • (하나의 문서에서 해당 단어 카운트)*log((전체 문서 수)/(해당 단어가 나타나는 문서의 수))
    • 전체 문서가 5개 일때, 모든 문서에 'is'가 들어간다고 하면 위 공식의 뒷 부분이 log(5/5) = log(1) = 0이다. 그러므로 위의 공식의 결과는 0 이다.
    • 'is'는 tf-idf 를 이용해서 처리하면 0이 된다. 즉, 모든 문서에 나오는 단어의 의미를 제거할 수 있다.

tf-idf 테스트

  • 자세한 내용은 생략
  • 학습을 시킬때, 데이터 카테고리별 갯수가 차이가 많이 나면 당연히 결과가 좋지 않을 것이다. 그러므로 데이터 카테고리별 갯수를 세고, 작은 쪽에 맞춰 주어야 한다.
  • 테스트셋에 트레이닝셋에 존재하지 않는 정보가 있다면, 당연히 테스트셋의 결과를 제대로 확인 할 수 없을 것이다.
  • 충분히 많은 양의 데이터라면, 테스트셋에만 존재하는 데이터는 "희귀"한 데이터 일 수도 있다. 그러므로 이때는 "그냥 무시"하는 방법을 써도 되는지 검토해 볼 필요가 있다.
  • 이 장에는... 머신러닝 관련되는 이런저런 이야기가 나온다. 난 걍 통과.

심층 분석: 무슨 일이 일어나고 있는가?

  • 생략

요약

  • 피처 스케일링을 통해 정보가 많은 단어는 강조되고, 상용어는 가중치가 낮아진다.

5장 범주형 변수: 로봇닭 시대에 달걀 개수 세기

  • 범주형 변수(categorycal variable)
  • 카테고리나 레이블(label)을 나타내는 방법
  • 범주형인지 아닌지 알아 내는건 쉬움. 연속적인지 아닌지를 판단하면 됨.
    • 주가 10달러와 15달러는 연속적인 값.
    • "정치", "경제", "사회"는 연속적이지 않은 값.
  • 문서 코퍼스(corpus)의 어휘도 각 단어가 구분되므로 커다란 범주형이라고 볼 수 있음.
  • 하지만 같은 단어가 여러번 나타날 수도 있으니, 이를 카운팅 할 수 있음.

범주형 변수 인코딩

  • 범주는 일반적으로 숫자가 아님. 예를 들면 "빨간색","검은색","파란색" 등이다.
  • 제일 쉬운 방법은 숫자를 1씩 증가시키면서 매길 수 있을 거다. 하지만, 이렇게 하면 값의 크기가 의미가 생길 수 있다. 그러므로 다른 방법을 찾아 보자.

원-핫 인코딩

  • 00001000, 1000000, 00100000 와 같이 여러개 중에 한개만 켜지는거(아니깐 생략)

더미 코딩

  • 원-핫 인코딩은 1개는 무조건 1이어야 하나, 더미 코딩은 모두 0 인게 있음.
  • 모두 0 인게 기준 범주.(기준 범주와 다른 애들과의 차이를 쉽게 볼 수 있다.)

이펙트 코딩

  • 더미 코딩의 모두 0 인것이, 모두 -1로 되는 것
  • 뭔 말인지 모르겠으니깐 통과. ㅎ.

범주형 변수 인코딩의 장단점

  • 원-핫 인코딩, 더미 코딩, 이펙트 코딩의 처리 방법은, 범주의 수가 매우 커지면 성능이 급격히 떨어진다. 수가 매우 많은 범주형 변수를 처리하기 위해서는 또 다른 전략 필요.

대규모 범주형 변수 처리

  • 피처 해싱 : 문자열, 숫자등을 해싱해서 변환, 매핑. 단점 : 원본 피처에 대한 정보가 사라져 더 이상 해석하기 어려워짐.
  • 빈 카운팅 : 어려우니깐 생략

요약

  • 책에 잘 정리 되어 있으니, 책 참고.

6장 차원 축소: PCA로 데이터 패케이크 납잡하게 만들기

  • 주성분 분석(PCA, Principal Component Analysis), 피처 차원 축소
  • 어려운건 다 생략하고...

직관

  • 차원 축소 : 핵심 정보는 유지하면서, '쓸모없는 정보'를 제거하기 위한 것
  • 수학적으로 새로운 피처 공간에서 데이터포인트들의 분산이 최대로 되게 한다.

수식 유도

  • 생략

PCA의 활약

  • MNIST 데이터중 8x8 로되어 있는 저해상도 데이터는, 64차원의 데이터를 갖는다.
  • pca_tranformer = PCA(n_componets=0.8)로 하면, 전체 분산의 최소 80%를 설명하는 수준에서 자동 선택.
  • 화면에 출력 결과, 3차원의 데이터만으로 비슷한 숫자들을 가깝게 그룹지은것을 볼 수 있음.

화이트닝과 ZCA

  • 모르겠으니깐 생략.

PCA의 고려사항과 한계

  • 차원 축소를 위해 PCA를 사용할 때는 얼마나 많은 주성분(k)을 사용할 것인지를 확인해야 한다.
  • PCA는 변환이 매우 복잡함. 결과 또한 해석이 어려움. 계산 비용도 많이 듬. 데이터 포인트나 피처의 수가 매우 많다면 수행하지 않는것이 좋다.
  • 데이터가 스트리밍으로 들어오면 PCA를 수행하기 어려움 ( 지금까지의 값으로 분산이 크도록 해 두었는데, 새로 들어온 값이 그것을 깰 수도 있다. )
  • 카운트에 사용하지 않는것이 좋다. 이상치(아웃라이어)들이 있기 때문에, 상관 관계가 쉽게 깨질 수 있다. 사용하고 싶다면, log등을 사용해서 처리하는 방법을 찾거나 하면 된다.

사용 예

  • PCA 변환은 데이터에서 정보를 제거한다. 따라서 이 정보로 모델을 학습할 때는 계산 비용이 적게 들지만, 정확도는 떨어질 수 있다.
  • PCA를 사용한 멋진 애플리케이션 : 시계열 데이터의 이상 탐지, 재무 모델링, 주가의 상관관계 패턴...(모르겠음 ㅋ )

요약

  • PCA에 대해 기억해야 할 두가지 핵심
    • 메커니즘 : 선형 투영
    • 목표 : 투영된 데이터의 분산 최대화
  • PCA는 모델 중심 피처 엔지니어링의 한 예. 분산이 데이터가 가지고 있는 정보를 적절하게 표현한다는것.
  • PCA는 잘 알려진 차원 축소 기법. 하지만 큰 계산 비용이 들고 결과물을 해석할 수 없다는 제약.
  • PCA 특히 피처들 사이의 선형 상관관계가 있을 때 전처리 단계로써 유용.

7장 k-평균 모델 스태킹을 통한 비선형 피처 생성

  • PCA는 데이터가 평평한 팬케이크 모양의 선형 부분 공간에 있을때 유용
  • 데이터가 휘어진 곡면으로 이뤄진(스위스 롤 같은) 경우. 결국은 2D 평면이 둥글레 말려 3D로 된 것임.
  • 피처 엔지니어링의 목적은 피처의 차원을 낮게 만드는것이 목적이 아니라, 과제를 수행하기 적합한 피처를 얻는 것
  • 가까이 있는것들을 모으는 클러스터링 방법을 사용할 수 있다.
  • 클러스터의 수가 원래의 피처 수 보다 작으면, 차원이 축소 되었다고 볼 수 있다.

k-평균 클러스터링

  • 비슷한 공간상에 놓여진 데이터를 그룹화 하는것.
  • 비지도 학습
  • 유클리드 기하학으로 두 점 사이의 거리를 측정 하여 근접성을 측정한다.
  • k-평균은 각 데이터 포인트가 오직 하나의 클러스터에만 할당되는 하드 클러스터링
    from sklearn.cluster import KMeans
    # 10개의 클러스터로 나눈다.
    clusters = KMeans(n_clusters=10, ramdom_state=1).fit_predict(numpy_array);

곡면 분할로서의 클러스터링

  • 스위스 롤 형태의 데이터를 KMeans 클러스터링으로 할때 k가 너무 작으면 클러스터가 잘 나눠지지 않는다.

분류를 위한 k-평균 피처 생성

  • 목표 변수를 사용하면, 그 값을 기준으로 클러스터링을 할 수 있다.(?)
  • 생략

장단점과 몇 가지 사항들

  • 생략

8장 피처 생성 자동화: 이미지 피처 추출과 딥러닝

  • 예전 방식에 대한 설명과, 딥러닝에 대한 설명을 모두 진행

가장 단순한 이미지 피처(그리고 이것이 동작하지 않는 이유)

  • 이미지를 검색하려고 한다마녀, 이미지 데이터 베이스에서 비슷한 이미지를 찾아야 한다.
  • 단순히 이미지에 있는 개별 픽셀 색상 값을 가지고 처리 할 수 없음. 이미지 간의 차이를 어떻게 계산 할 것인지를 결정하는것이 핵심

수동 피처 추출: SIFT와 HOG

  • 이미지 그래디언트(인접픽셀과의 차이)를 활용해서 벡터를 구한다.
  • ... 생략 ...

심층 신경망으로 이미지 피처 학습

  • Fully Connected Network, Convolution, ReLU, Normalization, Max Pooling 설명
  • AlexNet 설명
  • 이 분야에서의 엄청난 발전에도 불구하고 이미지 피처 생성은 아직 과학보다는 예술에 가깝다.
  • 10년 전에 사람들은 이미지 그래디언트, 테두리 탐지, 방향 탐지, 공간 단서, 스무딩, 정규화 등을 사용해 피처 추출을 수작업으로 진행했다.
  • 요즘은 딥러닝 아키텍트가 동일한 아이디어를 캡슐화 하는 모델을 작성하기는 하지만, 파라미터들은 학습용 이미지를 통해 자동으로 학습된다. 마법은 여전히 존재하며, 단지 모델의 더 깊숙한 곳에 추상화돼 숨어있을 뿐이다.

9장 다시 피처로: 학술 논문 추천 시스템 구축

  • 실제 예제를 사용해서 데이터 피처링을 해 보자

항목 기반 협업 필터링

  • 생략

첫 번째 단계: 데이터 가져오기, 정제하기, 피처 파싱하기

  • 단순 두 개의 피처만 사용해서 항목 유사도(코사인유사도)를 구했는데. 시간이 엄청 오래 걸렸다.
  • 데이터 갯수가 너무 많으니 계산하는데 시간이 너무 오래 걸림.
  • 현재의 방식은 반복적인 엔지니어링을 위해서 너무 느리다.

두 번째 단계: 피처 엔지니어링과 더 똑똑한 모델

  • 출간년도를 비닝으로 처리. 10년 단위로 비닝을 해서 피처 공간을 156에서 19로 줄임.
  • 데이터 프레임을 희소 배열로 변환
  • 위와 같이 하면 누락된 데이터가 매우 많을 것이다. 더 많은 정보를 가진 피처를 선택할 수 있는지 살펴 봐야 한다.

세 번째 단계: 추가 피처 = 추가 정보

  • 기존의 피처에서 추가로 초록(abstract)과 저자(authors)를 추가 할 수 있음
  • 초록(abstract)이나 제목의 경우 명사구나 stem(어근)을 구해서 처리 할 수도 있다.

[도서]타입스크립트 마스터 2/e

나단 로젠탈 저/김유성 역
에이콘출판사 | 2018년 03월

내용     편집/구성     구매하기

서두

자바스크립트를 공부하고, 실제로 사용하려고 했지만, 너무나 어려웠다. 가장 어렵다고 생각한 부분이 "자동완성"을 제대로 지원하지 않는것.

Type이 정확하지 않기 때문에, 내가 parameter로 전달해야 하는것도 명확하지 않았고, 모든것을 다 알고(혹은 외우고) 호출해야 하는 일이 어려웠다.

그래서 타입스크립트를 공부해 보기로 결심.

에이콘 출판사의 "타입스크립트 마스터 2/e - 예제로 배우는 타입스크립트"를 구매 했다.

출판사에 있는 정오표에 표시된 것 말고도 잘못 된 곳이 보여, 이곳에 정리해 두고자 한다. 지금 발견한건 딸랑 하나라.. 나중에 더 추가 될 수 있을지 모르겠다.

책을 다 읽었다. 당근 완벽하게 모든 내용을 이해한건 아니다. ㅋㅋ 아래 내용중 내가 잘 모르는 상태로 "잘못됐다"라고 이야기 하는것도 있으니, 이 글을 읽는 사람이 잘 가려서 읽기를 바란다.

책 후기

  • TypeScript의 문법은 거의 java와 비슷하다. 좀 다른게 있다면.

    • 변수나 함수의 type을 정의 할 때, 변수명 뒤 쓰는 형태 public id : string;
    • interface 정의에 field도 정의할 수 있음 interface A { id:string }
    • field에 접근할 때, get set 키워드를 통해서 hooking 할 수 있음 get id() { return this._id; }
    • 읽기 전용 속성은 final 대신, readonly readonly name: string;
    • 여러개의 type을 받고 싶을때는 Object 대신 any var a : any = "aa"
    • 여러개의 정해진 type(Union)을 받고 싶을때는 Object 대신 | var a : string|number;
    • 함수의 파라미터에서 같은 타입의, 다른 갯수에 대한 오버로딩시 모두 각각 정의하는 대신 ? 사용 funnction a( b: string, c?: string, d?: string) { ... }
    • 함수의 파라미터에서 타입이 다른 오버로딩시 모두 각각 정의하는 대신 아래 문법 사용

        function a ( b: string, c: string) : string;
        function a ( b: number, c: number) : number;
        function a ( b: any, c: any) : any {
            // code
        }
      
    • 상속 받은 클래스의 생성자에서는 반드시 super()를 수동으로 불러줘야 한다. Java에서는 super()가 자동으로 호출 되지만, 타입스크립트는 그렇지 않음. 자동으로 호출해 주자는 건의(?)가 많았지만, JavaScript의 super-set이라는 등의 이유로 안된듯 하다.

정오표 및 이해하기 어려운 곳 설명

3장 인터페이스, 클래스, 상속

216 페이지

  • Simple Class는 id, name의 속성과 -> Simple Class는 id 속성과
    • Simple Class에는 name 속성이 없다.

156 페이지

  • myClosure; -> myClosure();
    • 예제 소스에서 의도한것은 myClosure라는 함수가 실행되는것을 의도한 것이다(p157페이지의 상단 설명). 그러므로 함수 실행을 위해서 마지막에 () 를 붙여 주어야 한다.

159 페이지

  • 제일 아래의 예제 처음에 아래의 코드 추가

    enum PersonCategory {
        Audlt,
        Infant,
        Child
    }
    
    interface IPerson {
        Category: PersonCategory;
        canSignContracts(): boolean;
        printDetails(): void;
    }
    
  • 아마도 PersonCategory에 관한 enum과, IPerson이라는 interface 관련 코드가 아예 빠진것 같다. p160 내용이나, 그 뒤의 예제 결과등을 참고하면, 위의 코드가 있어야 될 듯 하다.

174 페이지

  • 제일 아래의 예제 코드에서 static staticName: string; -> static name: string;
    • 다음페이지에 나오는 출력 결과물과, 설명을 보면 코드상의 속성 이름이 staticName이 아니라 name이 되어야 한다.

203 페이지 (오타아님)

  • 유창한 구문으로 함수에 프라미스를 -> 플루언트 구문으로 함수에 프라미스를
    • Fluent의 번역을 "유창한"이라고 했다. 그래서 오히려 이해하기 어렵다. fluent 에 대한 개념은 여러 라이브러리의 사용에서 나오므로, 그냥 "플루언트"라고 그대로 적는게 어떨까 싶다. "데코레이트"도 그대로 사용했으니깐. 324페이지에도 "유창한"이라고 적혀 있으니, 이후에 나오는건 모두 걍 fluent라고 생각하면 된다.

226 페이지

  • containsErros 메서드와 ErrorHelper.trace 메서드를 -> ErrorHelper.containsErrors 메서드와 ErrorHelper.trace 메서드를
    • ErrorHelper는 containsError와 trace 메소드를 모두 가지고 있는데, 한쪽에만 ErrorHelper의 메소드인것 처럼 적어 두었다.

261 페이지

  • 정의에 모델 속성을 할당하려면 model: NoteModel 구문이나 -> 정의에 모델 속성을 할당하려면 model = NoteModel 구문이나
    • 260페이지의 마지막에서 이미 model: NoteModel은 오류가 발생한다고 적혀 있다. 그러므로 261페이지의 내용은 model = NoteModel 이 되어야 한다.

274, 463 페이지 (오타아님)

  • MVC는 모델-뷰-컨트롤러의 두 문자 집합으로 -> MVC는 모델-뷰-컨트롤러의 앞 글자의 집합으로
  • 객체지향 모범 사례의 두 문자를 모은 SOLID 디자인 -> 객체지향 모범 사례의 앞 글자를 모은 SOLID 디자인
    • 두 문자는 머리 두(頭)를 이야기 한 것으로 보인다. 그러므로 읽기 쉽게 "앞 글자" 라고 적어두는게 더 읽기 좋겠다.

323 페이지

  • Jasmine uses a simple format for writing tests. Consider the following TypeScript code: -> 삭제
    • 이미 위에 한글로 해석이 되어 있는데, 코드 쪽으로 설명이 내려와 있다. 그러므로 삭제

334 페이지, 335 페이지

  • doCallback 함수 -> doCallBack 함수
    • 예제에서는 "B"지만, 설명에서는 어떤 때는 "B", 어떤 때는 "b"로 사용한다. 그러니 잘 읽어내도록 하자. 심지어, 334페이지 아래쪽에는 let doCallback 으로 변수를 하나 만들어서 쓰고 있어서 더 혼동이 될 수 있다. 예제를 만들때 요런 점도 좀 고려해서 만들었으면 좋았을 텐데...

341 페이지, 342 페이지

  • jasminjquery -> jasmin-jquery
    • 라이브러리 이름이니 정확하게 "-"를 포함해서 적어야 한다.

363 페이지

  • Id: 0, DisplayName: "none"}}); -> { Id: 0, DisplayName: "none"}});
    • SelectedItem의 값으로 Id와 DisplayName을 넣는 Struture를 넣어야 하는것으로 보인다. 그렇게 되려면 "{"를 제일 앞에 추가해 줘서 객체(?) 형태로 만들어야 한다.

09장 타입스크립트 호환 프레임워크 테스트 는 생략함

  • TypeScript 자체를 공부하기 위해서 책을 보는것이라. 지금 당장은 테스트용 프레임워크를 열심히 볼 필요는 없다고 판단. ㅋ. 그래서 걍 이 부분은 읽지도 않고 패스함.ㅋ.

417 페이지

  • mod1.print(); -> m1mod1.print();
    • 첫번째 예제에서 let m1mod1 으로 정의해서 쓰고 있기 때문에, 다음줄에 있는 코드는 당연히 m1mod1.print(); 가 되어야 한다.

426 페이지 (오타아님)

  • 글 내용을 보면, "main.js파일에서는..." 이런 내용이 나오는데, 어디에도 그 main.js 파일을 찾을 수 없다. 그냥 작가가 있다고 생각하고 이야기 한 것인지 모르겠다. 그래서 책 내용을 읽을때, 독자도 상상력을 가지고 읽으면 될 것 같다.

429 페이지

  • 항목 이름은 'jasmineboot'로 -> 항목 이름은 'jasmine-boot'로
    • 소스코드에서는 물론이고, 직전의 설명에서도 'jasmine-boot'로 설명 되고 있다.

432 페이지

  • 다음 AMD 오류인 filenot-found 오류일 수 있다. -> 다음 AMD 오류인 file-not-found 오류일 수 있다.
    • 이전 설명에서도 file-not-found 와 같이 중간에 모두 - 을 넣어 두었다.

436 페이지 (오타아님)

  • 중간에 보면 http-server를 실행하고 결과를 보여주는 설명이 있는데, http-server를 설치하는 방법은 설명도 안 해 줬다. ( 설마.. 9장에서 해 줬나? ). http-server를 설치하려면 console(cmd)창에서 아래의 명령을 입력해 주면 된다.
  • npm install http-server -g
  • 그 이후 http-server를 실행시키면 된다.

448 페이지, 451 페이지, 565 페이지 등 (오타이님)

  • {{{body}}}

    • handlebars 템플릿은 일반적으로 {{ }} 처럼, 이중 괄호를 2개만 쓴다. 그런데 예제에서는 {{{ }}} 에 대한 설명 없이 body만 {{{body}}}로 사용중이다.
    • handlerbars는 {{ }} 를 사용하게 되면, 단순 String으로 치환하는것 이외에, HTML Tag와 관련되는것들을 모두 화면에 출력할 수 있도록 치환해 준다. 예를 들어 title이 "제목은 귀여워 >_<" 와 같다면, "제목은 귀여워 &gt;_&lt;" 와 같이 치환한다.
    • 하지만 {{{ }}} 를 사용하면 치환하지 않고, 그대로 String이 들어가게 된다. 여기에서는 {{{body}}} 영역에 각종 HTML 코드(<p> 나 <br>등)가 들어가야 페이지 HTML 페이지 구성을 할 수 있기 때문에 {{{ }}}를 사용한 것이다.


오늘 도착할지 안 할지도 몰랐는데 -_-
갑자기 덜컥 -_- 책상이 와 버렸다. -_-

그래서 -_- 그냥 의자도..
오늘 밖에 나가서 사 버렸다. -_-

책상이 왔는데, 의지가 없으면 쓰나 -_-?
오프라인에서 사면 가격이 비싸긴 하지만 -_-
그래도.. 하는 김에 확! 해야 되지 않겠나?

이것 저것 찔끔찔끔하면 아무것도 안될거라는 생각에.
그냥 확 사 버렸다. -_-


핸폰으로 찍은거라 화질이 엉망이다.
동영상은 다음에 올렸다. 딴것은 아이디를 만들어야 해서...
( 그리고 -_- 다음 주식을 9주 샀다. ㅋㅋ 사람들은 UCC 세상에 많이 들어가야 한다.ㅋㅋㅋ )

책상은 배송비포함 26,000 원.
의자는 38,000 원 -_-
( 4만 5천원짜리 현금으로 한다고 4만원, 거기다가 다시 2,000원 깍았다. )
( 의자 -_- 졸라비싸 -_-;; 쩝 -_-; 인터넷이면 1만원 아낄 수 있을것 같았는뎅.. )

도합 6만 4천원이다.

이걸로 일주일만 공부해도.. 쓴 돈 보다 더 많은 이득을 볼 수 있을거라 생각한다.


좌우명 중에 하나.
공부하는것, 사람 만나는 것에는 시간과 돈을 아끼지 말라.
  1. 如水 2007.07.01 00:00

    좋쿠만

  2. 옷장수 2007.07.01 11:50

    오... 좋아보이는걸요.. 축하^^

    • Chan 2007.07.01 12:03

      돈이 너무 많이 들었다는 ㅠ_ㅠ

  3. sungsunc 2007.07.01 22:04

    오~

    착한 가격에~ 좋은 물건 사셨는데요~ ^^

    • Chan 2007.07.02 00:55

      물건 살때, 3만원 이상이면.. 전부다 착한 가격이 아니라고 생각하는 1人

  4. 유겸애비 2007.07.02 01:58

    좋은데요. 멋지삼

    • Chan 2007.07.02 02:34

      오늘 한시간 공부했으니. 이제 6시간만 더 공부하면 본전은 뽑을것 같네요 ^_^

  5. 박서은 2007.07.02 18:26

    책상 멋지네. 내가 좋아하는 스타일~

    • Chan 2007.07.03 00:59

      ㅎㅎ.. 제가 한 센스 하죠~ ㅋ

  6. 토끼 2007.07.05 08:20

    나보다 비싸게 샀군!

    책상 16000원
    의자 24000원

    합계 4만원 +ㅁ+

일을 하다가 발견한 문제이다.

특정한 동작을 하는것이 있었는데..
이 놈이 유독스럽게 Mac 에서만 무진장 오래 걸린다는 문제 였다.

윈도우에서는 단 1초도 안되어서 끝나는 작업이었지만,
Mac 에서만 22초가 소요되고 있었다.

문제가 어디서 발생하는지는 찾았는데,
왜 Mac 에서만 유독 느린지 이유를 밝혀 내지는 못했다.


여하튼, 문제는 ArrayList의 removeAll 메소드에 있었다.
removeAll 메소드에 대해서 좀 살펴 보자.



ArrayList 의 상속 관계를 보면 아래와 같다.

사용자 삽입 이미지



여기서 removeAll 이라는 메소드는 Collection 에서 interface를 제공하고 있으며,
실제 그 구현은 AbstractCollection 에 아래와 같이 되어 있다.

사용자 삽입 이미지


보다시피 현재의 컬렉션에서 param 으로 들어온 컬렉션에 있는 item들을 모두 지우기 위해서
iterator 를 구하고, next를 하나꺼내와서
param으로 들어온 c 에 이미 들어 있는지 확인을 하고,
들어 있다면 지워주는 형태로 되어 있다.


여기서 다시 "c에 이미 들어 있는지 확인하는 c.contains( .. ) 의 코드는
indexOf(Object)가 0 보다 큰지 확인하게 된다.
이때 ArrayList의 indexOf(Object) 는 아래와 같이 구현되어 있다.

사용자 삽입 이미지

열심히 이미 가지고 있는 배열에서 루프를 돌면서 같은 놈이 있는지 확인을 한다.
물론 이 놈들이 Object 형태를 비교해야 하기 때문에 equals() 메소드를 사용하여서
비교를 한다.


그렇다면 내가 원래 있던 20개의 Collection 에서
10개의 데이터를 removeAll 한다고 해 보자.

1. AbstractCollection의 removeAll을 호출한다.
2. 20개에 대해서 iterator 를 구해서 20번 루프를 돌아야 한다.
2.1. 현재 선택되어 있는 아이템이 10개에 포함되어 있는지 확인해야 한다.
2.2. 이것을 확인하기 위해서는 indexOf() 를 수행해야 한다.
2.3. indexOf 내부에서는 10개에 대해서 루프를 돌아야 한다.
2.4. Object 비교이기 때문에 equals 를 수행하기 위해서 내부적인 연산을 해야 한다.


중요한것은 전체 배열에 대해서 이중 for loop 를 돌아서 처리 한다는것이다.




그렇다면 이 loop를 좀 더 덜 돌릴 수 있는 방향이 없을까?
항상 cpu 와 memory 사이에는 trade-off 가 있다.
물론 지금 이야기 하고자 하는 방법은 memory 측면에서는 손해 볼 수 있다.




내가 그래서 선택한 방법은 HashMap을 사용하는 방법이다.
안타깝게도 HashMap 에서는 removeAll 같은 메소드를 제공해주지 않기 때문에.
직접 for 루프를 돌아 가면서 데이터를 지워주어야 하는 귀찮은 점은 있다.

HashMap의 remove(Object) 코드는 아래와 같이 구성되어 있다.

사용자 삽입 이미지


remove(Object)를 수행하게 되면 removeEntryForKey(Object)를 수행하게 된다.

이때 removeEntryForKey(Object) 에서는
param으로 들어온 key에 대해서 hashCode() 를 구하고,
전체 배열 중에서 구해진 hash와 같은 값을 가지는 위치만을 비교 하게 된다.


그렇다면 HaspMap 에서 데이터를 지우는 순서를 보자.

1. removeAll이 없기 때문에 어쩔 수 없이 외부에서 for를 돌려서 remove 를 여러번 시켜 준다.
2. hashCode() 값을 구하고, hash 같은 배열 부분만을 검색한다.
3. equals()를 호출하여 비교하면서 처리 한다.

여기서도 사용자가 for를 외부에서 돌려 주고,
내부에서도 while loop를 도는 2중 loop 구조이기는 하지만,
hash 가 같은것만 돈다는것이 핵심이다.


이 결과는 equals()과 hashCode()를 구현하는 방식에 따라서 다른 결과를 도출할 수도 있다.



약 400개의 데이터에 대한 작업이었는데
ArrayList.removeAll()에서는 22 초가 걸렸었고,
HashMap.remove() + for 로 수정한 뒤에는 0.5 초대의 시간이 걸렸다.


이 결과는 Mac 에서만 유용할 수도 있다. 실제 윈도우에서도 약간 더 빨리 동작하기는 했다.
시간 날때  똑같은 코드가 왜 Mac 에서만 이렇게 느리게 동작하는가에 대한 조사를 해 보아야 겠다.


대학교 자료구조 수업 시간에 자주 등장하는 내용이지만,
실제로 이렇게 -_- 겁나게 차이를 느껴 보기는 처음이었다. -_-;


대학교때 공부 잘했던 사람들이 나와서도 잘 사는 이유가 있나 보다. ㅋㅋ
  1. 유야 2007.06.10 00:30

    역시 난 제대로 디버깅한거였어!!!!
    Font의 canDiaplay도 무쟈게 느리더만 -_-

    • Chan 2007.06.10 01:18

      대단해. ㅋㅋ.
      근데 -_- 왜 느릴까 -_-? 쩝쩝쩝..

  2. 옷장수 2007.06.10 12:55

    Font의 canDisplay()가 느린이유는 char를 glyph으로 변환하는 과정을 거치기 때문이 아닐런지..

    • Chan 2007.06.10 21:27

      ㅇㅎㅎ ;; 뭔 말인지 몰겠따.. ㅎㅎ ;;;

  3. 유겸애비 2007.06.11 11:40

    이거 맥하고 상관이 없는글이자나욧!!
    글구 canDisplay()는 글립으로 만들지 않고 그냥 폰트에 어떤 문자가 정의되어있는지를 보는것일듯 싶네요

    • Chan 2007.06.11 18:17

      수정했습니다. ㅋㅋ;;
      그리고 ;; 또 어려운 말들을 하시는군요.;; ㅎㅎ ;;

    • 옷장수 2007.06.12 09:39

      오랜만에 보는거라서 소스를 봤었는데 canDisplay가 호출되면 CharToGlyphMapper라는 놈을 찾아서 여기에서 glyph이 보여질 수 있는지를 체크하던데요.

  4. 유겸애비 2007.06.12 19:16

    Re:옷장수// Font란 char to glyph의 map이라고 추상화 시킬수 있는데 key가 정의되어있난 보는거지 char에서 glyph으로 변환을 시키는건 아닐껍니다.

    • Chan 2007.06.12 23:36

      심도 있는 댓글이군요~ ㅋ
      찾아봐야 겠당~ ㅋㅋ

    • 옷장수 2007.06.14 14:03

      음.. char를 glyph으로 변환한다는게.. char 값을 glyph의 index 값으로 변환한다는 의미였는데요.

http://phpschool.com/bbs2/inc_view.html?id=11732&code=tnt2

<link rel=alternate media=print href="http://junyoung.info/aaa.doc">
<a href="javascript:window.print()">프린트</a>


지금 현제 제 서버에 파일을 올려 놓았으니...
그냥 복사 하셔서 실행하시면 될겁니다 ^^
참고로 http:// 이거 꼭 쓰셔야 합니다. 상대경로는 되지 않습니다...

+ Recent posts