2015/04/16 17:50

AngularJS SPA 형태 개발을 진행할 때 AMD(Asychronous Module Definition)에 대한 고려를 하지 않고 있다. 계속해서 확장 되어야 하는 애플리케이션을 개발한다면 AMD를 염두에 두자. 하지만 AMD가 아니라 앵귤러 스러운 모듈단위의 동적 로딩을 하고 싶을 경우 어떻게 하는지 Smart Analytics 관점에서 컨셉을 테스트해 보자. 



개념 


  - CommonJS : exports, require, module을 통한 서버사이드 자바스크립트 모듈화 스팩이고 Node.js에서 많이 사용함

  - AMD : 브라우져에서 모듈화에 대한 스팩. 가장 많이 쓰는 구현체 require.js  를 통한 자세한 사용예(NHN)

    + 특징 : 동적 로딩, 의존성 관리, 모듈화 

    + define을 통한 모듈 패턴을 적용하여 모듈을 만든다

    + require를 통해 의존관계 모듈들을 주입받아 사용한다. 

  - AngularJS는 모듈화와 DI 즉, 의존성 주입을 가능하게 하고, RequireJS는 JS 파일의 의존성을 관리하고 동적 로딩을 통한 성능 최적화를 얻는다. (참조)





Smart Analytics에서 바로 보는 동적 로딩 시나리오

  

  ElasticSearch의 Kibana는 엘라스틱서치의 데이터를 자유롭게 표현할 수 있는 대시보드 소프트웨어이다. AngularJS + Require.js를 사용하고 있다. 하지만 좀 더 AngularJS 스러운 방식으로 앵귤러 모듈을 필요한 시점에 동적으로 할 수는 없을까? 화면이 라우팅될 때 또는 필요한 시점에 필요한 모듈만 로딩할 수 있도록 지원하는 앵귤러 컴포넌트로 ocLazyLoad 모듈이 있고 이를 이용하여 대시보드 화면에 국한하여 시나리오를 써보자


  - 사용자가 로그인을 하면 사용자마다 할당 된 대시보드 목록을 가져오고 첫번째 대시보드를 브라우저 영역 전체화면으로 보여준다.

  - 대시보드에는 사용자가 직접 제작한 차트가 보이고 해당 차트는 별도의 파일로 존재하고 앵귤러의 독립 모듈로 존재한다. 따라서 대시보드안에 들어가는 차트들은 플로그인 방식으로 동적으로 로딩되어 대시보드 일부분에 포함되어 들어가야 한다. 

  - 그러나 사용자가 직접 제작하지 않고  저작도구를 통해 제작한 차트는 별도의 파일로 존재하지 않고 환경값을 서버로 부터 받아 차트 컨테이너에 자동으로 해석되어 표현된다. 


  여기서 동적으로 로딩되어 표현할 것은 직접 별도로 제작된 차트를 대상으로 하고, 별도의 파일로 존재한다. 해당 파일은 로컬 또는 네트워크를 통해 로딩 될 수 있어서 다양한 차트 화면을 대시보드로 수용할 수 있다. 마치 플러그인 방식으로 대시보드 운영 서버의 재기동 없이도 플러그인을 설치하기만 하면 자동으로 대시보드의 특정위치에 차트가 표현되는 것이다. 

  

   - chart-config.json + chart-container를 통해 차트를 자동으로 표현하거나

   - 로컬에서 사용자가 직접 제작한 bizChart01.js 파일을 동적으로 로딩해서 표현하거나, bizGrid01.js를 원격에서 동적 로딩하는 개념이다. 







ocLazyLoad 기반 앵귤러 모듈의 동적 로딩


  ocLazyLoad 모듈을 이용해 파일 로딩하는 예를 보자. 설치하고 모듈 의존성 설정

// survey-gorilla 설문조사 오픈소스를 위해 만들어 놓은 제너레이터로서 generator-angular-fullstack을 기반으로 수정한 것이다. 

$ npm install generator-sg --save

$ mkdir prototyping & cd prototyping


// 애플리케이션 생성 : mongodb는 선택안하고, ui-bootstrap과 sass를 선택함

$ yo sg SAProto 

// oclazyload를 설치함 

$ bower install oclazyload --save

bower install       oclazyload#0.6.3


  ocLazyLoad 모듈을 위한 별도의 서비스를 /app/components/base/pluginer 폴더에 만들어 보자. pluginer 앵귤러 서비스를 base 모듈에 포함시키기 위해 먼저 base.module.js를 만든다. 

// base.module.js 를 만들고, oc.lazyLoad 모듈에 대한 의존관계를 설정한다. 

$ cd client/components

$ mkdir base & cd base

$ vi base.module.js 


(function() {

  'use strict';


angular 

    .module('sa.base', ['oc.lazyLoad']);


})();



// pluginer 서비스를 만들어 보자 

$ mkdir pluginer & cd pluginer

$ vi pluginer.service.js 


(function() {

  'use strict';


  angular

    .module('sa.base')

    .service('pluginer', pluginer);


  /* @ngInject */

  function pluginer($q, $ocLazyLoad) {

    this.load = load;


    function load(moduleName, filePath) {

      var deferred = $q.defer();


      $ocLazyLoad

        .load({

          name: moduleName,

          files: [ filePath ]

        })

        .then(function() {

          console.log('loaded plugin: ' + moduleName + ' successfully.');

          deferred.resolve('ok');

        }, function() {

          console.log('failed plugin: ' + moduleName + ' successfully.');

          deferred.reject('fail');

        });


      return deferred.promise;

    }

  }


})();


// 최종 폴더 구조 


  pluginer.service.js는 $ocLazyLoad를 통해 지정한 파일의 모듈을 로딩해서 사용할 수 있고 promise 패턴을 통해 비동기적인 상황에 대응한다. 다음으로 플러그인을 하나 만들어 보자. 우선 client 밑에 plugins 폴더를 만들고 index.html에 포함되지 않는 *.js / *.css / *.jpg(png) 등을 놓는다. plugin.bizchart01이라는 별도의 모듈을 만들고 bizchart01 서비스를 만든다. 

// client 밑에 plugins 폴더를 생성한다.

$ mkdir plugins & cd plugins

$ mkdir bizchart01 & cd bizchart01

$ vi bizchart01.js 


(function() {

  'use strict';


  angular

    .module('plugin.bizchart01', [])

    .service('bizchart01', bizchart01);


  function bizchart01() {

    this.draw = draw;


    function draw() {

      return 'drawing....';

    }

  }


})();


// plugins 폴더 

 

  이제 pluginer 서비스를 통해 plugin.bizchart01 모듈을 필요한 시점에 로딩을 하고 bizchart01 서비스의 draw() 를 호출해서 출력해 보자. sa.base 모듈을 app.js에 의존관계를 설정하고 app/main/main.html 를 바꿔보자. 

// /client/app/app.js 의 sa.base 모듈 의존 설정 

  angular

    .module('saprotoApp', [

 'ngCookies',

 'ngResource',

 'ngSanitize',

 'ui.router',

 'ui.bootstrap',

                  'sa.base'

])

    .config(config)

    .factory('authInterceptor', authInterceptor)

    .run(run);


// main.html 과 main.controller.js를 수정하여 테스트 코드 작성

// main.html 

 <li><a href="#" ng-click="lazyloading()">Load Module</a>: {{lazyloadingMsg}}</li>


// main.controller.js 

(function () {

  'use strict';


  angular

    .module('saprotoApp')

    .controller('MainCtrl', MainCtrl);


  /* @ngInject */

  function MainCtrl($scope, $injector, pluginer) {

    $scope.lazyloading = lazyloading;


    function lazyloading() {

      pluginer

        .load('plugin.bizchart01', 'plugins/bizchart01/bizchart01.js')

        .then(function() {

          var bizchart01 = $injector.get('bizchart01');

          $scope.lazyloadingMsg = 'lazyloading message: ' + bizchart01.draw();

          console.log($scope.lazyloadingMsg);

        });

    }    

  }


})();


  pluginer를 통해 "plugins/bizchart01/bizchart01.js" 에 있는 "plugin.bizchart01" 모듈을 로딩하고, $injector를 통해 "bizchart01" 서비스를 얻어와 draw()를 호출했다. 이를 확인할 수 있는 것은 크롬의 개발자 도구에서 브라우저에서 로딩 링크를 클릭했을 때 실제로 bizchart01.js 파일을 호출하는지 보면 된다. 


1) "Load Module"를 클릭한다. 



2) 크롬 개발자 도구의 Nework에서 "Load Module" 링크를 클릭시 bizchart01.js을 요청하는지 확인한다. 



이제 별도의 차트를 앵귤러 모듈로 만들어서 필요한 시점에 로딩할 수가 있다. 이외에도 ui-router를 통해 partial view가 변경될 때도 가능하고 다양한 예제는 ocLazyLoad를 참조한다. 


테스트 소스 : https://github.com/Smart-Analytics/prototyping/tree/feature/lazyloading




<참조>


  - CommonJS와 AMD 개념 비교 (NHN)

  - AMD : require.js 사용예

  - Node.js와 브라우져 사용예 (Mobicon)

  - ocLazyLoad GitHub

저작자 표시 비영리 변경 금지
Posted by peter yun 윤영식
2015/03/07 21:19

NMF(non-negative matrix factorization) 기법을 소개한다. 이 기법은 데이터내에 독립된 특성을 찾는데 사용한다. 많은 데이터 세트 내의 항목들은 미리 알기 어려운 다른 특성들과의 조합으로 생성되고 이러한 특성을 찾아 본다. 






이전 분류 방식

  

  - 베이지안 분류기 (Classification)

  - 의사결정트리

  - 지지벡터머신(SVM)

  - 군집 (Clustering)




비음수 행렬 인수분해 (NMF)


  - 행렬 준비 

    + 특성 행렬(feature matrix) : 가로줄에 각각의 특성을 가졌고 세로줄에 단어, 값들은 단어 특성의 중요도

     


    + 가중치 행렬(weights matrix) : 가로줄 타이틀, 세로줄 특성

      


    + 행렬 만들기 = 특성 행렬 * 가중치 행렬


  - 비음수 행렬 인수분해라 불리는 이유는 음수가 아닌 특성과 가중치를 리턴하기 때문이다. 모든 특성은 양수 값을 가져야 함을 의미한다.

  - 단어 출현 횟수와 같은 명사류 데이터뿐만 아니라 주식시장 데이터와 같은 숫자 데이터 문제에도 잘 어울린다.

  - 진행 : 행렬 준비 -> NMF 실행 -> 결과 출력    

     * 특성을 나누는 행렬을 만들고 필요없는 특성을 제거하면서 원하는 차원을 줄여서 원하는 것을 종합적인 결과를 출력함




<참조> 

 

 - 얼굴 인식

 - PCA, NMF


저작자 표시 비영리 변경 금지
Posted by peter yun 윤영식
2015/02/28 11:56

선형 분류기 개념과 지지벡터머신(SVM, support-vector machines)에 대해 알아본다. 데이트 매칭에 데이터를 기본으로 알아봄. 



데이터 세트 


  - 데이터 분할에서 의사결정트리는 세로, 가로 직선으로 고지식함

  - 산포도(scatter plot chart)를 통해 도움받음 

 



기본 선형 분류


  - 산포도에서 각 범주(class) 내 모든 데이터들의 평균을 찾고 그 범주의 중앙을 나타내는 점을 만듦 (그림. 9-4)

  - 일치분류를 위해 백터의 각도를 계산해서 작으면 일치, 크면 불일치 (그림. 9-6)

  - 백터내적(dot-product) : 벡터와 벡터의 방향/크기 비교 






분류 데이터의 특성


  - 데이터 정규화 (Data Normalization)

  - 숫자로 변형 -> 예/아니오(1/-1), 관심/비관심(0/1) : 사람 쌍을 다룰 때 유용 

  - 공통 관심의 수, 모든 관심을 포용할 새로운 변수를 만듦

  - 거리 데이터 구함

  - 각 변수에 대한 축적(scale)을 조정함 : 최대/최소값 




커널 기법 이해

  

  - 커널 트릭 : 차원을 높이지 않고 차원을 올리는 효과를 거둠. 

  - 펑션을 통해 원하는 값을 구함 : 방사 펑션 (RBF: radial basis function)




지지 벡터 머신 (SVM)


  - 각 범주에서 가능한 멀리 떨어진 선을 찾아 해결하려고 시도한다. 비선형을 극복 (non-linear)

  - 먼저 범주를 나눈다 이때 커널 트릭을 사용해서 구하고 이것이 차원이 된다. 각 차원 즉 범주의 사이의 초평면(hyperplane)을 만든다. 

  - 해당 초평면에 근접한 것들이 매칭하는 것이다.  (그림. 9-10)





<참조> 


  - 내적 공간

  - 서포트 벡터 머신(한글), 서포트 벡터 머신 공식(영어)

  - 초평면

  - LIBSVM 라이브러리 

  - 정규화

저작자 표시 비영리 변경 금지
Posted by peter yun 윤영식
2015/02/21 13:23

가격 결정을 위한 모델링은 이질적인 속성을 기반을 둔 숫자 데이터를 예측하는데 최적의 알고리즘이다.




kNN


  - K-nearnest neighbors : k는 마지막 결과를 얻기 위해 평균을 낼 물품의 개수를 말한다. 데이터가 완벽하다면 k=1을 사용한다. 

  - 인접개수의 평균을 낼 때 너무 작거나 크면 안되고 적정개수를 찾아야 한다. 




물품 가중치


  - 거리에 따라 가중치를 둔다. 물품들이 비슷할 수록 그들 간의 거리가 더 가까워진다. 

  - 물품들을 군집화하기 위한 방법 - 적정한 인접 개수를 구하는 것이 필요하다. 

  - 역함수(inverse function), 빼기 함수(substraction function), 가우스 함수(gaussian function)

  - 가중 kNN (Weighted kNN) : 가우시안을 구하고 평균을 구한다 




교차검증


  - 데이터를 학습 세트와 테스트 세트로 나누는 기법들을 총칭한다. (cross validation set) : 표본값을 잘 뽑는 방법

  - training set -> test set 




이질 변수


  - 가격 결정에 너무 큰 영향을 미치는 이질적 요소

  - 변수의 단위가 틀릴때 스케일(Scale)을 조정하여 대입한다. 




실습 


  - $ pip install virtualenvwrapper

 - $ source /usr/local/bin/virtualenvwrapper.sh

 - mkvirtualenv env1

 - vi requirements.txt

// requirements.txt 내역 

beautifulsoup4==4.3.2

html5lib==0.999

lxml==3.4.2

numpy==1.9.1

pandas==0.15.2

python-dateutil==2.4.0

pytz==2014.10

six==1.9.0

wsgiref==0.1.2


  - pip install ipython  (module 없을 경우 계속 pip install <moduleName>)

  - ipython notebook 을 통해서 실습 시작

  - chapter7의 treepredict 데이터 생성 : data.txt

Referrer,Location,Read FAQ,Pages viewed,Service chosen

Slashdot,USA,Yes,18,None

Google,France,Yes,23,Premium

Digg,USA,Yes,24,Basic

Kiwitobes,France,Yes,23,Basic

Google,UK,No,21,Premium

(direct),New Zealand,No,12,None

(direct),UK,No,21,Basic

Google,USA,No,24,Premium

Slashdot,France,Yes,19,None

Digg,USA,No,18,None

Google,UK,No,18,None

Kiwitobes,UK,No,19,None

Digg,New Zealand,Yes,12,Basic

Google,UK,Yes,18,Basic

Kiwitobes,France,Yes,19,Basic


  - treepredict.py 작성 : pandas 통해서 데이터 만듦

import pandas as pd 


def main():

  data = pd.read_csv("./data.txt", sep=",")

  print data

  values = data.values

  print values


if __name__ == '__main__':

  main()


  - pandas로 하면 데이터 유형이 틀려지므로 그냥 책에 있는 내용 copy&paste

  - 실행 내역을 html로 출력

$ ipython nbconvert treepredict.ipynb

[NbConvertApp] Using existing profile dir: u'/Users/nulpulum/.ipython/profile_default'

[NbConvertApp] Converting notebook treepredict.ipynb to html

[NbConvertApp] Support files will be in treepredict_files/

[NbConvertApp] Loaded template full.tpl

[NbConvertApp] Writing 202262 bytes to treepredict.html

(env1)




<참조> 


  - https://virtualenvwrapper.readthedocs.org/en/latest/ : python 가상 환경 

  - https://pypi.python.org/pypi/virtualenv

  - iPython notebook 사용하기 

저작자 표시 비영리 변경 금지
Posted by peter yun 윤영식
2015/02/14 11:29

의사결정 과정 모델링에 대해 알아본다. 의사결정트리는 고객 프로파일링, 재무 위험 분석, 보조 진단, 트래픽 예측과 같은 넓은 응용분야에서 사용한다. 예로 사용자가 유료 고객이 될 가망성을 예측하여 사용자가 고객이 될 것임을 시사하는 요소를 알았다면 이 정보를 이용해서 광고 전략을 짜거나 사이트의 특정 측면에 쉽게 접근할 수 있게 만들거나 유료 고객의 숫자를 늘리는 데 도움이 되는 다른 전략들을 사용할 수 있다.




가입 유형 추정 


  - 유료 고객이 될 가망성을 예측하기 : 베이지안 분류기, 신경망을 이용

  - 관찰 결과를 분류하는 방법 : 의사 결정 트리를 if~then으로 만들고 경로를 따라 내려가면 해답에 이르게 됨 




트리 학습 


  - CART(Classification and Regression Tree) : 데이터를 분리하는 최적의 변수 찾기 true or false로 분기해야 하기 때문 

  - 최적 단편 선정

    + 최상위 부모로 있을 노드를 선정하고 그 하위로 나뉘어 내려감  

    + 지니 불순도(Gini imprity) : 집합 내의 항목 중 하나에 무작위로 적용될 기대 오류율 - 확률이 0이면 모든 것이 올바른 집합안에 있음

    + 엔트로피 : 데이터를 두개의 그룹으로 나누어 엔트로피를 줄여야 한다.

       p(i) = frequency(outcome) = count(outcome) / count(total rows) Entropy = sum of p(i) x log(p(i))  

       p(i) = 빈도(출력) = 횟수(출력)/횟수(가로줄 개수)

       엔트로피 = 모든 출력에 대해 p(i) * log(p(i))의 합 




재귀적으로 트리 만들기


  - 전체 그룹에 먼저 엔트로피를 구함 

  - 어떤 속성이 가장 잘 나누는지 결정하기 위해 정보이득(information gain)을 계산 -> 모든 속성마다 정보이득을 계산해 가장 높은 정보이득을 가진 것을 선택한다. 

  - 관측 값에서 더 분할 할지를 결정 : 새로운 노드마다 최적을 속성을 계산하면서 트리를 생성한다. 




트리 가지치기 


  - 트리를 학습시키면 학습 데이터를 과대하게 반영하는 과잉적합(overfitted) 문제에 직면한다. 

  - 노드 쌍을 병합해서 경계값 이하로 엔트로피를 늘 수 있는지 본다. 그렇다면 한개 노드로 병합한다. -> 과잉적합을 회피 

  - 최소 이득이 높아지면 상위 부모 노드로 병합.

 



손상된 데이터 다루기


  - 데이터 조각이 없을(손상된) 경우 : 각 가지의 결과를 계산하고 개별 가중치로 결합한다.




<참조> 


  - 의사결정트리

  - slideshare 의사결정트리

저작자 표시 비영리 변경 금지
Posted by peter yun 윤영식

티스토리 툴바