jar 추가 하기

  • spark-shell --jars <jar_name1,jar_name2, ...>



repl에서와 동일하게 다음과 같이 하면 버전이 나온다. 


scala> scala.util.Properties.versionString

res0: String = version 2.10.5



형태소 분석기 은전한닢이 스칼라용이 있어서 시범삼아 돌려보았다. 

실행방법은 너무나 간단하다. 


참고 페이지

  • https://bitbucket.org/eunjeon/seunjeon


build.sbt에 다음 내용 추가

libraryDependencies += "org.bitbucket.eunjeon" %% "seunjeon" % "1.1.1"



그리고 다음 코드 실행해봄

object Test extends App {
  import org.bitbucket.eunjeon.seunjeon.Analyzer

  // 형태소 분석
  println( "@@ Step 1")
  Analyzer.parse("아버지가방에들어가신다").foreach(println)

  // 어절 분석
  println( "@@ Step 2")
  Analyzer.parseEojeol("아버지가방에들어가신다.").foreach(println)
  // or
  println( "@@ Step 3")
  Analyzer.parseEojeol(Analyzer.parse("아버지가방에들어가신다.")).foreach(println)

  /**
   * 사용자 사전 추가
   * surface,cost
   *   surface: 단어
   *   cost: 단어 출연 비용. 작을수록 출연할 확률이 높다.
   */
  println( "@@ Step 4")
  Analyzer.setUserDict(Seq("덕후", "버카충,-100", "낄끼빠빠").toIterator)
  Analyzer.parse("덕후냄새가 난다.").foreach(println)

  // 활용어 원형
  println( "@@ Step 5")
  Analyzer.parse("빨라짐").flatMap(_.deInflect()).foreach(println)

  // 복합명사 분해
  println( "@@ Step 6")
  Analyzer.parse("삼성전자").flatMap(_.deCompound()).foreach(println)
}



실행결과 (가독성을 위해 일부 메시지 제거)

[info] Running Test
@@ Step 1
LNode(Morpheme(아버지,1784,3536,2818,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135)
LNode(Morpheme(가,490,1044,1501,WrappedArray(JKS, *, F, 가, *, *, *, *),COMMON,WrappedArray(J)),3,4,-738)
LNode(Morpheme(방,1784,3537,2975,WrappedArray(NNG, *, T, 방, *, *, *, *),COMMON,WrappedArray(N)),4,5,660)
LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,203)
LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,583)
LNode(Morpheme(신다,5,4,3583,WrappedArray(EP+EC, *, F, 신다, Inflect, EP, EC, 시/EP/*+ㄴ다/EC/*),INFLECT,WrappedArray(EP, E)),9,11,-1256)

@@ Step 2
Eojeol(MutableList(LNode(Morpheme(아버지,1784,3536,2818,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135), LNode(Morpheme(가,490,1044,1501,WrappedArray(JKS, *, F, 가, *, *, *, *),COMMON,WrappedArray(J)),3,4,-738)))
Eojeol(MutableList(LNode(Morpheme(방,1784,3537,2975,WrappedArray(NNG, *, T, 방, *, *, *, *),COMMON,WrappedArray(N)),4,5,660), LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,203)))
Eojeol(MutableList(LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,583), LNode(Morpheme(신다,5,6,3600,WrappedArray(EP+EF, *, F, 신다, Inflect, EP, EF, 시/EP/*+ᆫ다/EF/*),INFLECT,WrappedArray(EP, E)),9,11,-1256)))
Eojeol(MutableList(LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),11,12,325)))

@@ Step 3
Eojeol(MutableList(LNode(Morpheme(아버지,1784,3536,2818,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135), LNode(Morpheme(가,490,1044,1501,WrappedArray(JKS, *, F, 가, *, *, *, *),COMMON,WrappedArray(J)),3,4,-738)))
Eojeol(MutableList(LNode(Morpheme(방,1784,3537,2975,WrappedArray(NNG, *, T, 방, *, *, *, *),COMMON,WrappedArray(N)),4,5,660), LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,203)))
Eojeol(MutableList(LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,583), LNode(Morpheme(신다,5,6,3600,WrappedArray(EP+EF, *, F, 신다, Inflect, EP, EF, 시/EP/*+ᆫ다/EF/*),INFLECT,WrappedArray(EP, E)),9,11,-1256)))
Eojeol(MutableList(LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),11,12,325)))

@@ Step 4
LNode(Morpheme(덕후,1784,3535,800,WrappedArray(NNG, *, F, 덕후, *, *, *, *),COMMON,WrappedArray(N)),0,2,-1135)
LNode(Morpheme(냄새,1784,3536,2123,WrappedArray(NNG, *, F, 냄새, *, *, *, *),COMMON,WrappedArray(N)),2,4,-139)
LNode(Morpheme(가,490,1044,1501,WrappedArray(JKS, *, F, 가, *, *, *, *),COMMON,WrappedArray(J)),4,5,-437)
LNode(Morpheme(난다,2421,6,1277,WrappedArray(VV+EF, *, F, 난다, Inflect, VV, EF, 나/VV/*+ᆫ다/EF/*),INFLECT,WrappedArray(V, E)),6,8,348)
LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),8,9,-394)

@@ Step 5
LNode(Morpheme(빠르,-1,-1,0,WrappedArray(VA),COMMON,WrappedArray(V)),0,2,-1092)
LNode(Morpheme(지,-1,-1,0,WrappedArray(VX),COMMON,WrappedArray(V)),2,3,-1092)
LNode(Morpheme(ᄆ,-1,-1,0,WrappedArray(ETN),COMMON,WrappedArray(E)),2,3,-1092)

@@ Step 6
LNode(Morpheme(삼성,-1,-1,0,WrappedArray(NNG),COMMON,WrappedArray(N)),0,2,-2008)
LNode(Morpheme(전자,-1,-1,0,WrappedArray(NNG),COMMON,WrappedArray(N)),2,4,-2008)




내용 분석을 위한 사전 참고 사항

품사 태그 테이블 - https://docs.google.com/spreadsheets/d/1-9blXKjtjeKZqsf4NzHeYJCrr49-nXeRF6D80udfcwY/edit#gid=589544265

실질의미유무
대분류(5언 + 기타)
세종 품사 태그mecab-ko-dic 품사 태그
태그설명태그설명
실질형태소
체언
NNG일반 명사NNG일반 명사
NNP고유 명사NNP고유 명사
NNB
의존 명사
NNB의존 명사
NNBC단위를 나타내는 명사
NR수사NR수사
NP대명사NP대명사
용언
VV동사VV동사
VA형용사VA형용사
VX보조 용언VX보조 용언
VCP긍정 지정사VCP긍정 지정사
VCN부정 지정사VCN부정 지정사
수식언
MM관형사MM관형사
MAG일반 부사MAG일반 부사
MAJ접속 부사MAJ접속 부사
독립언IC감탄사IC감탄사
형식형태소
관계언
JKS주격 조사JKS주격 조사
JKC보격 조사JKC보격 조사
JKG관형격 조사JKG관형격 조사
JKO목적격 조사JKO목적격 조사
JKB부사격 조사JKB부사격 조사
JKV호격 조사JKV호격 조사
JKQ인용격 조사JKQ인용격 조사
JX보조사JX보조사
JC접속 조사JC접속 조사
선어말 어미EP선어말 어미EP선어말 어미
어말 어미
EF종결 어미EF종결 어미
EC연결 어미EC연결 어미
ETN명사형 전성 어미ETN명사형 전성 어미
ETM관형형 전성 어미 ETM관형형 전성 어미
접두사XPN체언 접두사XPN체언 접두사
접미사
XSN명사 파생 접미사XSN명사 파생 접미사
XSV동사 파생 접미사XSV동사 파생 접미사
XSA형용사 파생 접미사XSA형용사 파생 접미사
어근XR어근XR어근
부호
SF마침표, 물음표, 느낌표SF마침표, 물음표, 느낌표
SE줄임표SE줄임표 …
SS
따옴표,괄호표,줄표
SSO여는 괄호 (, [
SSC닫는 괄호 ), ]
SP쉼표,가운뎃점,콜론,빗금SC구분자 , · / :
SO붙임표(물결,숨김,빠짐)
SY
SW기타기호 (논리수학기호,화폐기호)
한글 이외
SL외국어SL외국어
SH한자SH한자
SN숫자SN숫자


내용이 너무 많아서 다사 sbt console에서 하나씩 돌려봄

$ sbt console

[info] Starting scala interpreter...

[info]

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_91).

Type in expressions for evaluation. Or try :help.


scala> import org.bitbucket.eunjeon.seunjeon.Analyzer

import org.bitbucket.eunjeon.seunjeon.Analyzer


scala> Analyzer.parse("아버지가방에들어가신다.").foreach(println)

LNode(Morpheme(아버지,1784,3536,2818,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135)

LNode(Morpheme(가,490,1044,1501,WrappedArray(JKS, *, F, 가, *, *, *, *),COMMON,WrappedArray(J)),3,4,-738)

LNode(Morpheme(방,1784,3537,2975,WrappedArray(NNG, *, T, 방, *, *, *, *),COMMON,WrappedArray(N)),4,5,660)

LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,203)

LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,583)

LNode(Morpheme(신다,5,6,3600,WrappedArray(EP+EF, *, F, 신다, Inflect, EP, EF, 시/EP/*+ᆫ다/EF/*),INFLECT,WrappedArray(EP, E)),9,11,-1256)

LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),11,12,325)


scala>

 


결과를 보니 LNode, Morpheme라는 클래스들이 많이 보인다. 이게 뭔지 알아보자.


/**

  * Lattice 노드

  * @param morpheme   Morpheme

  * @param startPos  시작 offset

  * @param endPos   끝 offset

  * @param accumulatedCost  누적비용

  */

case class LNode(morpheme:Morpheme,

                 var startPos:Int,

                 var endPos:Int,

                 var accumulatedCost:Int = Int.MaxValue) {

 

/**

  * 형태소

  * @param surface  표현층

  * @param leftId   좌문맥ID

  * @param rightId  우문맥ID

  * @param cost     Term 비용

  * @param feature  feature

  * @param poses    품사 

  */

@SerialVersionUID(1000L)

case class Morpheme(var surface:String,

                    var leftId:Short,

                    var rightId:Short,

                    var cost:Int,

                    var feature:mutable.WrappedArray[String],

                    var mType:MorphemeType,

                    var poses:mutable.WrappedArray[Pos]) extends Serializable {




샘플

// Lattice 노드 
LNode(

    // 형태소
    Morpheme(
        아버지,         // surface - 표현층
        1784,           // leftId - 좌문맥Id
        3536,           // rightId - 우문맥Id
        2818,           // cost - 비용
        WrappedArray(NNG, *, F, 아버지, *, *, *, *), // feature
        COMMON,         // morpheme type
        WrappedArray(N) // poses - 품사
    ),
    0,     // 시작 offset
    3,     // 끝 offset
    -1135  // 누적비용
)


위 예제를 변형해서 표현층만 추출해보자. 

scala> Analyzer.parse("아버지가방에들어가신다.").toList.foreach( node => println(node.morpheme.surface ))

아버지



들어가
신다
.

scala>



사용자 사전을 추가해보자.

scala> Analyzer.setUserDict(Seq("아버지", "가방").toIterator)
scala> Analyzer.parse("아버지가방에들어가신다.").foreach(println)

LNode(Morpheme(아버지,1784,3535,700,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135)
LNode(Morpheme(가방,1784,3535,800,WrappedArray(NNG, *, T, 가방, *, *, *, *),COMMON,WrappedArray(N)),3,5,-239)
LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,-3709)
LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,-3329)
LNode(Morpheme(신다,5,6,3600,WrappedArray(EP+EF, *, F, 신다, Inflect, EP, EF, 시/EP/*+ᆫ다/EF/*),INFLECT,WrappedArray(EP, E)),9,11,-5168)
LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),11,12,-3587)

scala> 


어절분석

scala> Analyzer.parseEojeol("아버지가방에들어가신다.").foreach(println)

Eojeol(
  MutableList(
    LNode(Morpheme(아버지,1784,3535,700,WrappedArray(NNG, *, F, 아버지, *, *, *, *),COMMON,WrappedArray(N)),0,3,-1135)
  )
)
Eojeol(
  MutableList(
    LNode(Morpheme(가방,1784,3535,800,WrappedArray(NNG, *, T, 가방, *, *, *, *),COMMON,WrappedArray(N)),3,5,-239),
    LNode(Morpheme(에,356,307,1248,WrappedArray(JKB, *, F, 에, *, *, *, *),COMMON,WrappedArray(J)),5,6,-3709))
)
Eojeol(
  MutableList(
    LNode(Morpheme(들어가,2421,3574,1648,WrappedArray(VV, *, F, 들어가, *, *, *, *),COMMON,WrappedArray(V)),6,9,-3329),
    LNode(Morpheme(신다,5,6,3600,WrappedArray(EP+EF, *, F, 신다, Inflect, EP, EF, 시/EP/*+ᆫ다/EF/*),INFLECT,WrappedArray(EP, E)),9,11,-5168))
)
Eojeol(
  MutableList(
    LNode(Morpheme(.,1794,3555,3559,WrappedArray(SF, *, *, *, *, *, *, *),COMMON,WrappedArray(S)),11,12,-3587))
)

scala>

 


복합명사 분해

scala> Analyzer.parse("삼성전자").flatMap(_.deCompound()).foreach(println)

LNode(Morpheme(삼성,-1,-1,0,WrappedArray(NNG),COMMON,WrappedArray(N)),0,2,-2008)

LNode(Morpheme(전자,-1,-1,0,WrappedArray(NNG),COMMON,WrappedArray(N)),2,4,-2008)

 






[error] (run-main-0) java.nio.charset.MalformedInputException: Input length = 1

java.nio.charset.MalformedInputException: Input length = 1

        at java.nio.charset.CoderResult.throwException(CoderResult.java:281)

        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)

        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)

        at java.io.InputStreamReader.read(InputStreamReader.java:184)

        at java.io.BufferedReader.fill(BufferedReader.java:161)

        at java.io.BufferedReader.readLine(BufferedReader.java:324)

        at java.io.BufferedReader.readLine(BufferedReader.java:389)



위와 같은 에러가 발생했다면 다음 설정을 .bashrc에 추가해주자.


export JAVA_OPTS="-Dfile.encoding=UTF-8"



CRISP-DM

  • CRoss-Industry Standard Process for Data Mining
  • 초보자나 전문가가 비즈니스 전문가와 함께 모형을 만들어 내는 포괄적인 데이터 마이닝 방법론/프로세스


CRISP-DM 프로세스는 일반적인 오류를 줄이고 다음과 같은 이점을 제공함

  • 비즈니스 문제 인식 및 해결을 위한 데이터 마이닝 프로세스 명료화
  • 데이터 탐색 및 이해
  • 데이터를 통한 문제 인식 및 해결
  • 데이터 마이닝 기법 적용
  • 비즈니스 상황에 따른 데이터 마이닝 결과의 해설
  • 데이터 마이닝 결과의 전개 및 유지


CRISP-DM 프로세스

  • Business Understanding
  • Data understanding
  • Data prepation
  • Modelding
  • Evaluation
  • Deployment


CRISP-DM 홈페이지

원문: http://blog.naver.com/yoonsunh/20034885744


CRISP-DM 모델

  1. 비즈니스 이해(Business Understanding)
    • 프로젝트 목적 이해
    • 지식을 데이터 마이닝 문제 정의를 위해 전환
    • 목적 달성을 위한 예비 계획 수립
  2. 데이터 이해(Data Understanding)
    • 초기 데이터 수집
    • 데이터 파악
    • 데이터 품질 확인
    • 데이터 통찰력 발견
    • 데이터 탐색
  3. 데이터 준비(Data Preparation)

  4. 모델링(Modeling)
  5. 평가(Evaluation)
  6. 배포(Deployment)



원문: http://www.comworld.co.kr/news/articleView.html?idxno=14271




추천시스템 - 대상자가 좋아할 만한 무언가를 추천하는 시스템


활용사례

  • 아마존 
    • 평점, 구매행위, 검색행위 정보들을 이용해 상품 추천시스템을 운영
  • 넷플릭스
    • 사용자의 성향을 파악해 좋아할 만한 영화 추천
    • 사용자가 로그인 하는 순간 해당 사용자의 취향에 맞춰 전체 페이지가 구성되는 수준까지 발전
  • 페이스북
    • 상품이나 뉴스 추천이 아니라 친구 추천을 하는데 활용
    • 친구 추천은 교류를 증대 시킬 목적을 가지고 있기 때문에 Link Prediction이라는 것에 중점을 둠

추천시스템 주요기술

  • 협업 필터링
    • A라는 사람이 부산행이라는 영화를 좋아하면, A와 성향이 비슷해 보이는 B라는 사람 역시 부산행을 좋아할 것이라는 생각을 활용한 방법
    • 거의 모든 추천시스템에서 활용
    • 유유상종의 대상이 무엇이냐에 따라 2가지 방식으로 나뉘어짐
      • 사용자기반 협업 필터링
        • 유사한 성향을 가진 사람들을 구분하고, 해당 성향의 사람들이 좋아하는 것을 추천하는 방식
        • 피어슨상관계수
      • 아이템기반 협업 필터링
        • 아이디어는 동일하지만 사람이 아닌 아이템으로 대치된 것이다. 
        • 코사인유사도
    • 2가지 기술의 장점: 구현이 간단하고 이해하기 쉽다
    • 단점: 정보가 많지 않은 경우 예측의 정확도가 높지 않다.
  • 모델 기반 협업 필터링
    • 머신러닝을 이용해 평점을 예측할 수 있는 모델을 만드는 방식
    • 의사결정트리, SVM 등의 머신러닝 알고리즘을 이용해 평점예측모델을 만든다.

평가방법

  • 사용자 평가
    • 특정한 시점에 사용자를 초청해 추천시스템의 성능을 점검해 보는 것
    • 사용자들로부터 피드백을 받는다.
  • 온라인 평가
    • 추천시스템이 실제 환경에서 활용되고 있는 상황에서 사용자가 보여주는 행위를 보고 성능을 평가하는 방식
    • A/B 테스팅을 이용해 추천시스템의 성능을 평가한다.
  • 오프라인 평가
    • 과거의 데이터를 이용해 평가하는 방식
    • 데이터 기반의 평가이기 때문에 사용자를 초청할 필요가 없다. 


원문: http://www.oss.kr/oss_repository14/658203


노트7 소셜 반응 분석(제플린 사용)

원문: http://bcho.tistory.com/1138


데이터 스튜디오는 쿼리 사용이 불가능

상세 분석에는 노트북 계열의 어플리케이션을 써야함


제플린 설치하면 다음 prefix로 사용가능

%bigquery.sql


노트7 소셜 반응 분석 구현하기

원문: http://bcho.tistory.com/1137


실시간 분석 애플리케이션 개발

트위터 피드 분석

솔루션 아키텍처

  • twitter 
  • fluentd - 특정 키워드 기반 twitter 피드 수집
  • Pub/Sub - 피드 저장
  • DataFlow - 필요한 데이터 필터링후 Google NLP API 사용
    • Google NLP API - 명사와 형용사 분리
  • BigQuery - 30초 sliding window로 명사, 형용사 카운트를 빅쿼리에 저장
  • DataStudio





화면이 깨지는 경우 인코딩 조절방법


mc를 설치해서 실행해봤더니 특수문자가 깨져나왔다. 

검색을 해보니 다음과 같이 실행하면 깨져보이지 않는다. 


$ LC_ALL=en mc


그래서 .bashrc에 alias를 걸어서 항상 위와 같이 실행되도록 하였다. 


alias mc='LC_ALL=en mc'


참고: http://serverfault.com/questions/475925/how-to-fix-putty-showing-garbled-characters


+ Recent posts