산티아고 순례길, JMT(존 뮤어 트레일)과 함께 세계 3대 트레일로 불리는 캐나다 빅토리아 섬의 WCT(West Coast Trail)에 다녀온 영상을 정리하였습니다. 

 

2019년 5월에 register-in 하여 5일간 백패킹 모드로 76km를 이동하였습니다.

아래 영상은 1일 차 영상 정리분입니다.

 

 

작성중 ...

'Expired > Java Works' 카테고리의 다른 글

왜 Java NIO는 사용하기 힘든가?  (2) 2011.12.23
Java로 구현하는 웹기반 원격제어 프로그램  (8) 2009.04.19
자막(smi) 파일에서 대본 추출 프로그램  (6) 2008.11.09
NIO 강좌 - 3  (0) 2008.02.09
NIO 강좌 - 2  (0) 2008.02.09

DL4J의 Word2Vec을 활용하여 여러가지 실험을 해보고 있습니다.


DL4J 내부적으로 다차원 vector로 처리된 파일을 사람이 인지할 수 있도록 2차원으로 차원을 축소하여 csv 파일로 변환하는 tsne library를 제공하고 있습니다.


해당 tsne로 처리된 csv파일을 이미지화 하기 위해서 DL4J 내부적으로 UIServer를 제공합니다만, 아무리 노력해도 해당서버는 장황한 에러메시지를 뱉아내며 실행이 되지 않습니다.


UIServer의 문제를 해결해볼까 하다가, 그림 그리기가 그리 복잡하지 않은 듯 하여 D3.js를 활용하여, csv 파일 시각화하는 코드를 작성해 보았습니다.


아래는 어느 무협지를 학습시켜서, tsne로 2차원 csv 파일 추출후, 시각화한 화면입니다.




이해할 수 없는 부분이 더 많기는 합니다만, 중간중간 의미적으로 유사성이 높은 단어가 뭉쳐져 있는 모습을 확인 할 수 있습니다.


저같은 시각화로 인한 고민을 하시는 분들이 어딘가엔 계실듯 하여 대충 만들어진 html 파일을 공유합니다. 

csv파일 로딩 때문에 톰켓이나 was에 올려야 동작하며, 적절히 수정해서 쓰시면 될 듯 합니다.

파일처리를 위하여 csv 상단에 아래의 header가 추가되어야 합니다.

 ax,ay,word

1601.4119873046875,2464.052734375,검법 

-5537.662109375,1058.436767578125,독물 

-1954.671142578125,-3149.0380859375,탄로 

57.20676040649414,494.7344970703125,부축 

0.006148473359644413,-0.020917901769280434,시인 

0.001806588377803564,0.13746240735054016,겸허 

-0.039052389562129974,-0.013289138674736023,동료 


....



html 파일


 <html>

<head>

<title>D3 Axis Example</title>

<script src="http://d3js.org/d3.v2.js"></script>

<style type="text/css">

.axis path,

.axis line {

fill: none;

stroke: black;

shape-rendering: crispEdges;

}

.axis text {

font-family: sans-serif;

font-size: 9px;

}


</style>

    </head>

    

    <body>

    

    <script>

        var width = 1000,   // width of svg

            height = 1000,  // height of svg

            padding = 40; // space around the chart, not including labels

       

        var x_domain = [-500, 500],

        y_domain = [-500, 500];

            

        // display date format

        var  date_format = d3.time.format("%d %b");

        

        // create an svg container

        var vis = d3.select("body").

            append("svg:svg")

                .attr("width", width + padding * 2)

                .attr("height", height + padding * 2);

                

        // define the y scale  (vertical)

        var yScale = d3.scale.linear()

        .domain(y_domain) // make axis end in round number

.range([height - padding, padding]);   

            

        var xScale = d3.scale.linear()

        .domain(x_domain)    // values between for month of january

    .range([padding, width - padding]);   

        // define the y axis

        var yAxis = d3.svg.axis()

            .orient("left")

            .scale(yScale);

        

        // define the x axis

        var xAxis = d3.svg.axis()

            .orient("bottom")

            .scale(xScale);

            //.tickFormat(date_format);

            

        // draw y axis with labels and move in from the size by the amount of padding

        vis.append("g")

        .attr("class", "axis")

            .attr("transform", "translate("+ (width/2 ) +",0)")

            .call(yAxis);


        // draw x axis with labels and move to the bottom of the chart area

        vis.append("g")

            .attr("class", "xaxis axis")  // two classes, one for css formatting, one for selection below

            .attr("transform", "translate(0," + (height/2) + ")")

            .call(xAxis);

            

          vis.selectAll(".xaxis text")  // select all the text elements for the xaxis

          .attr("transform", function(d) {

             return "translate(" + this.getBBox().height*-2 + "," + this.getBBox().height + ")rotate(-45)";

         });

    

        vis.append("text")

            .attr("text-anchor", "middle")  // this makes it easy to centre the text as the transform is applied to the anchor

            .attr("transform", "translate("+ (padding/2) +","+(height/2)+")rotate(-90)")  // text is drawn off the screen top left, move down and out and rotate

            .text("Y-axis");


        vis.append("text")

            .attr("text-anchor", "middle")  // this makes it easy to centre the text as the transform is applied to the anchor

            .attr("transform", "translate("+ (width/2) +","+(height-(padding/3))+")")  // centre below axis

            .text("X-axis");

        

        var maxX = 10, 

        maxY = 10;

        var dirX = 1, 

        dirY = 1 ;

        

        // check max value

        d3.csv("visual7.csv", function(data){

        data.forEach(function(d){

        //console.log(d.ax + ' --- ' + maxX + ' === ' + (d.ax > maxX));

        if(Math.abs(d.ax) > maxX) maxX = Math.abs(d.ax);

        if(Math.abs(d.ay) > maxY) maxY = Math.abs(d.ay);

        });

        console.log('max X:Y = ' + maxX + ':' + maxY);

        // draw text

        drawText(vis) ;

        });

               

        function drawText(pannel) {

        d3.csv("visual7.csv", function(data){

            data.forEach(function(d){

              console.log('Word -> ' + d.ax + ',' + d.ay + ':' + d.word);

                        

              pannel.append("text")

          .style("font-size", "10px")

          .attr("x", ((d.ax/maxX) * (width/2) + width/2))

          .attr("y", (height/2 - (d.ay/maxY) * (height/2)))

          .attr("dy", '-10')

          .text(d.word)

          

            });

          });

        }

    </script>

    

    </body>

</html>


다차원을 2차원으로 축소하는 개념이라 왜곡이나 이해 못 할 부분들이 많은 것 같습니다.

t-sne 의 여러 옵션에 대한 이해가 있어야 아름다운 그림이 나올 듯 하네요. 


옵션에 대한 대략적인 이해는 아래 링크를 참조하면 될 듯 하네요.. (결국엔 이것저것 넣어보고 돌려보는게 답일 듯.. -_-)


http://docs.flowjo.com/v9/flowjo-v9-documentation-home/platforms/t-sne/


'Expired > Web Art' 카테고리의 다른 글

Java 물리 시뮬레이션 툴  (0) 2008.11.03
Tree Viewer  (0) 2008.11.02

[DEMO]

[동기]

모 앱스토어에서 결제시스템을 운영하면서 크고작은 많은 문제들이 발생을 하였고, 

제니퍼와 같은 기존의 서버 모니터링 툴로는 위험 상황을 감지하기 힘든 상황이 계속해서 발생하게 됩니다.



[운영 장애 사고의 유형]

  • 예측하기 힘든 트래픽
  • 자동화된 툴 혹은 인위적인 서비스 취약점 공격


[요구사항 원칙]

  • 앱스토어를 통해 배포된 앱별로 모니터링이 가능할 것
    • 배포된 앱별 사용자수와 앱의 이벤트 시점에 따라서 트래픽이 급증하는 상황이 발생
  • 특정사용자 혹은 사용자군의 모니터링이 가능할 것  
  • Velocity Check
    • 통상적인 수치를 벗어나는 상황에 대한 인지가 필요 (QA나 혹은 인지할 수 없는 오류 혹은 장애 확인 필요)
    • FDS 시스템과 연동 등을 고려 (특정 API에 대해서 일정 수준이하의 응답 시간 확보)


[고려사항 및 설계]

  • 로그 수집을 통한 실시간 혹은 대량의 데이터에 대한 MR 분석이 가능할 것
    • 별도 plugin 설치등 Live 서비스에 영향을 주지 않고 각 was 인스턴스의 로그만 수집하는 agent만 가동
    • 특정 기능에 대해서 일정수준 실시간 성을 지원하여 허용 시간 범위내에서 데이터 분석이 가능할 것
    • MR을 활용한 대량의 데이터를 분석하여 원사는 데이터를 추출 할 수 있을 것
    • 다양한 데이터 분석 결과에 대응할 수 있는 Chart를 지원할수 있을 것
  • 개발과 운영 비용의 최소화
    • IT회사가 아니기 때문에 장비 지원은 항상 최소를 고려 (ㅠㅠ)
      • 시스템 운영으로 장애 및 피해 예방을 통하여 비용확보 필요
    • 기존 업무를 하면서 남는 시간을 활용하여 개발 진행, 초기 운영까지도.. 개인 업무 Capacity 고려


[개발 stack]

  • Java 8
  • SpringBoot Web (with thymeleaf)
  • d3.js
  • Hbase 1.2


[참고 자료]

  • OpenTSDB
    • Hbase를 활용하여 시계열(time series) 데이터 처리를 위한 sheme 설계에 참고
  • D3.js
    • 다양한 정적 or 동적 차트 처리를 위해 도입



[시스템 구조]
  • LogCrawlAgent
    • 각 Live 서버상의 로그를 실시간으로 전송(http keepalive socket)
    • jar console application
  • TXD (Transaction Deamon)
    • 실시간 모듈 : API, 실시간 처리, UI 제공
    • Batch 모듈 : 앱 전체의 통계 및 Report 추출

[데이터 스키마]

  • 총 6개의 Table로 구성되며, 
    • 실시간 시계열 데이터 처리를 위한 tsTable은 아래와 같이 OpenTSDB 유사 scheme 적용 (아래)
    • 사용자 데이터의 Velocity Check의 응답 속도 보장을 위한 별도의 table에 scheme 적용
  • MR처리 효율상 특정 부분은 bit가 아닌 String, Number 등의 데이터 Type 적용

범주RowKey
구성metricId:3bytebaseTimeStamp:4bytekey1:3bytevalue1:3bytekeyN:3bytevalueN:3byte
각주정의된 metric 시단위까지의 변환값추가정보 key값추가정보 value값추가정보추가정보

범주Column
구성qualifervalue
데이터 구조time offset:4byteString or Long
각주

시단위 미만 시간값

임의 등록 가능



[Major Features]

  • 메인화면
    • 상단 Traffic Chart는 30초 주기로 갱신 (Cubism.js 적용)
    • 트래픽, 결제 상위 앱들의 랭킹을 최근 10분 및 일간 누적 기준으로 제공
    • 고 결제빈도 사용자 군 랭킹 추출

  • 실시간 로그 확인
    • 각 API별 트래픽의 갱신주기를 사용자가 정의할 수 있도록 하여 긴급 상황 대응

  • 트래픽 비교
    • 양일간 특정 트래픽의 추이 비교를 통하여, 감지되지 않은 장애상황 및 프로모션 등 이벤트 등 마케팅 분석에 활용


  • 앱별 트래픽
    • 특정 트래픽을 기준으로 앱별 & 시간대별 순위를 추출하여 차지하는 비중을 확인


  • 상위 결제 유저 
    • 자동화 툴 혹은 악의적(실험적)의도의 사용자 트래픽의 분석 확인

[개발과 운영을 하면서]

  • Hbase는 실시간 및 대량 Batch(MR)의 두마리 토끼를 잡을 수는 있으나,
    • 잘못된 Scheme 적용시 Data 증가에 따라 응답 속도가 기하급수적으로 느려질 수 있음 (당연한 이야기 이겠지만..)
    • Scheme 디자인시 철저히 데이터 실시간 요구사항에 근거해야 하며, 이외의 기능은 MR로 커버 가능
    • MR자체의 성능은 Hadoop의 RawData 직접 처리보다는 느리다 (2,3배 정도)
    • 성능 및 효율을 위해서는 Bit 단위의 data 를 기반으로 하는 scheme 적용이 필요하나,
      • Hadoop Eco 시스템 기반의 쿼리 등의 다양한 툴을 적용하기에 어려움이 있으며,
      • 경우에 따라서는 별도의 공용(범용) Query Lang혹은 API 제공이 필요할 듯 보이며,
      • 개발 자체의 어려움도 수반하니 신중을 기해야 하겠다
  • D3.js는 정말 훌륭하다
  • 부하량은,
    • Agent의 부하는 CPU사용률 1%이내로 Live 시스템에 미치는 영향이 거의 없으나,
    • TXD의 특정 쿼리의 실시간 처리를 위해 CPU사용률이 최대 20%가량 치솟는 경우도 있었음
      • 실시간 통계 처리를 위해서는 Cache등의 적용이 필요할 듯 (사용자가 늘어나면..)
    • Hbase
      • StandAlone 모드로 300tps 수준 로그 적제시에도 CPU 사용률은 최대 3%를 넘지않은 미미한 수준
  • TBD


'Expired > Hadoop Hbase Nutch2' 카테고리의 다른 글

Hbase JSON API 사용하기  (0) 2015.01.04
Nutch Cycle Step  (0) 2015.01.03
하둡 이클립스 플러그인(Hadoop1.1.0 Eclipse Plugin)  (0) 2012.11.17

아직 HBASE에 쓸만한 client tool 이 없는 것 같네요. 

몇몇 오픈소스와 cloudera쪽의 몇개 툴들이 보이긴 합니다만, 무거움은 사람과 시스템을 지치게 만들죠.


찾아보니 HBASE에서 공식적으로 제공되는 API 툴이 있는 것 같습니다.

KVP, Json, XML 등 다양하게 지원하는 듯 하구요, Stargate라는 경량 Servlet container를 Jetty상에서 실행시켜야 사용할 수 있습니다.

 % ./bin/hbase rest start -p <port>  


아래는 실행 화면



자세한 내용은 아래 공식 페이지 참조

 https://wiki.apache.org/hadoop/Hbase/Stargate




InjectorJob

Crawling에 필요한 URL을 crawlDB에 적재하는 작업. 해당 Job을 구동시키기 위해서는 URL 리스트가 제공되어야 하며, 일반적으로 URL Directory를 생성하여 해당정보 파일을 넣어둔다. 다음은 Nutch에서 InjectorJob을 실행시키는 명령어,

#bin/nutch inject crawl/crawldb urls

urls는 crawling 대상 seed URL이 포함된 디렉토리이고, crawldb는 해당 url이 포함된 nutch의 자료구조에 해당된다.


GenerateJob

InjectorJob이 완료되었으며, CrawlDB에 저장된 URL을 fetch (다운로드 및 각종 operation) 해야 한다.

URL에 대해서 fetch작업 이전에 우선적으로 GenerateJob이 실행되어야 하며, 다음은 명령어 이다.

#bin/nutch generate crawl/crawldb crawl/segments

crwaldb는 URL이 생성된 db이며, segment는 crawling시에 필요한 정보를 fetch하는데 필요한 디렉토리이 이다.


FecherJob

GeneratorJob에 의해 생성된 URL을 실질적으로 fetch하는 역할로, GeneratorJob에 의해서 생성되는 input으로 fetch(consume)작업을 수행한다.

#bin/nutch fetch -all

-all 옵션은 Generator에 의해 생성된 모든 URL을 fetch하겠다는 의미이다.


ParserJob

Fetch가 완료된 이후에 URL에 대한 파싱작업을 수행하며, 명령어는 아래와 같다.

#bin/nutch parse -all


DbUpdateJob

일단 ParserJob이 완료되며, FetcherJob에 의해 제공되는 결과를 DB에 Update를 해야한다.이 작업으로 각자의 DB에 가장 최근에 Fetch된 URL의 정보를 update한다. 명령어는 다음과 같다.

#bin/nutch updatedb crawl/crawldb -all

이 작업이 완료되면 DB는 초기 페이지의 update된 정보와 신규 페이지 정보가 DB에 적재된다. 신규 페이지는 Link 정보를 포함된 새롭게 발견된 페이지를 의미한다.


Invertlinks

인덱스를 적용하기 이전에, 모든 링크에 대한 invert가 필요하다.이 작업을 통하여, 특정 페이지에 대해서 anchor text를 인덱스에 적용할 수 있다. 다음은 명령어이다.

#bin/nutch invertlinks crawl/linkdb -dir crawl/segments


Indexing with Apache Solr

크롤링이 완료되며, Nutch에 의해 완료된 URL 데이터에 대해서 Apache Solr로 인덱싱이 가능하다. 인덱싱이 완료되면 특정 URL을 쉽게 검색할 수 있다. 다음은 명령어 이다.

#bin/nutch solrindex http://127.0.0.1:8983/solr/ crawl/crawldb -linkdb crawl/linkdb crawl/segments/*


+ Recent posts