<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Hello 희희낙락</title>
    <link>https://hello-heehee.tistory.com/</link>
    <description>혼자 공부하면서 작성하는 공간</description>
    <language>ko</language>
    <pubDate>Sun, 12 Apr 2026 05:56:37 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>헬로희</managingEditor>
    <image>
      <title>Hello 희희낙락</title>
      <url>https://tistory1.daumcdn.net/tistory/5408650/attach/2d40250c30484e4287dc768268c09082</url>
      <link>https://hello-heehee.tistory.com</link>
    </image>
    <item>
      <title>[Python] List 원소 추가하기, 삭제하기, 위치찾기</title>
      <link>https://hello-heehee.tistory.com/57</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;1. 추가하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) append&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774015442325&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,2,3]
ls.append(5)

ls #[1,2,3,5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) insert&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 index에 값 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774015531938&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,2,3]
ls.insert(0, 2) #(index, value)

ls #[2, 1, 2, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) extend&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;list에 다른 list 원소값 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774016273956&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,2]
ls.extend([3,4]) #list 확장

ls #[1,2,3,4]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) +&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;'+'를 이용하여 list에 list 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774016392519&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls1 = [1,2,3]
ls2 = [4,5,6]

ls = ls1 + ls2
ls #[1,2,3,4,5,6]&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;2. 삭제하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) del&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index를 기입하여 값 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774015612654&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,3,5,7,9]
del ls[1] #[index]

ls #[1,5,7,9]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) pop&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index를 기입하여 값 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774015724391&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,3,5,7,9]
a = ls.pop(1) #(index)

ls #[1,5,7,9]
a #3 #삭제하는 원소를 반환하는 특징이 있음 


ls.pop() #index를 넣지 않으면 맨 뒤 원소 삭제
ls #[1, 5,7]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) remove&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값을 기입하여 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774016072962&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,5,7,1,3,5]
ls.remove(5) #value

ls #[1,7,1,3,5] #가장 앞에 있는 값이 삭제&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) clear&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리스트 안 모든 원소 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774016115070&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [1,2,3]
ls.clear()

ls #[] #모든 원소 삭제&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;3. 위치찾기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) index&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;찾고자 하는 값의 index를 구함&lt;/li&gt;
&lt;li&gt;값이 여러 개가 있는 경우 해당 값의 첫 index 반환&lt;/li&gt;
&lt;li&gt;시작 index와 끝 index 지정 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774016672396&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;A&quot;, &quot;C&quot;]
ls.index(&quot;A&quot;) #0

# 시작과 끝의 index 지정
ls.index(&quot;A&quot;, 1, 5) #4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기초</category>
      <category>append</category>
      <category>clear</category>
      <category>del</category>
      <category>extend</category>
      <category>index</category>
      <category>insert</category>
      <category>List</category>
      <category>pop</category>
      <category>Remove</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/57</guid>
      <comments>https://hello-heehee.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 21 Mar 2026 09:00:07 +0900</pubDate>
    </item>
    <item>
      <title>가상환경(Virtual Environment) 생성하기/삭제하기/복제하기</title>
      <link>https://hello-heehee.tistory.com/56</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;1. 가상환경 &lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 환경을 여러 개로 분리하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1)&amp;nbsp; 가상환경이 필요한 이유&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라이브러리를 설치하다보면 '버전 충돌'문제가 발생하기 때문.&lt;br /&gt;가상환경이 없다면 라이브러리 버전을 매번 설치/삭제를 반복해야하지만 가상환경을 만들면 버전을 다르게 설치 할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 대표적인 가상환경 도구&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;venv : Python 3.3부터 내장된 기본 도구로 가볍고 별도 설치 필요 없음.&lt;/li&gt;
&lt;li&gt;Conda : Data Science, Machine Learning 분야에서 주로 사용.&lt;/li&gt;
&lt;li&gt;Poetry : 의존성 관리와 배포가 편리함.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;2. venv 가상환경 구축&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;터미널(CMD or VSCode)에서 실행&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1774014133129&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#가상환경 생성
python -m venv test_env #현재 폴더에 test_env 라는 이름의 가상환경 생성

#가상환경 활성화
test_env\Scripts\acticate

#패키지 설치
pip install requests #패키지들을 test_env 환경에 설치

#가상환경 비활성화
deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;3. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Conda 가상환경 구축&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;보통 Anaconda Prompt에서 실행. Anaconda 설치는 &lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://hello-heehee.tistory.com/10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이전 글&lt;/a&gt; 참고&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1774017623170&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Anaconda] 가상환경에서 GPU Tensorflow 구축하기&quot; data-og-description=&quot;GPU를 사용하여 딥러닝을 하기 위해서는 다음을 설치해야한다.1. Anaconda 설치 Installing Anaconda Distribution &amp;mdash; Anaconda documentationTip More of a visual learner? Sign in to Anaconda Cloud and watch the Installing Anaconda (Mac) &quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/10&quot; data-og-url=&quot;https://hello-heehee.tistory.com/10&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dvLwUy/dJMb83kr7z3/ImPsSXHr5q3QQTIoyAV6fK/img.png?width=420&amp;amp;height=62&amp;amp;face=0_0_420_62,https://scrap.kakaocdn.net/dn/gltlu/dJMb88F35wG/cVOkSRUQTj3ktV1pogVvw1/img.png?width=420&amp;amp;height=62&amp;amp;face=0_0_420_62,https://scrap.kakaocdn.net/dn/0my16/dJMb88eZQs2/eM7sQGf7joNLBnSmvNh2f0/img.png?width=1404&amp;amp;height=477&amp;amp;face=0_0_1404_477&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/10&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dvLwUy/dJMb83kr7z3/ImPsSXHr5q3QQTIoyAV6fK/img.png?width=420&amp;amp;height=62&amp;amp;face=0_0_420_62,https://scrap.kakaocdn.net/dn/gltlu/dJMb88F35wG/cVOkSRUQTj3ktV1pogVvw1/img.png?width=420&amp;amp;height=62&amp;amp;face=0_0_420_62,https://scrap.kakaocdn.net/dn/0my16/dJMb88eZQs2/eM7sQGf7joNLBnSmvNh2f0/img.png?width=1404&amp;amp;height=477&amp;amp;face=0_0_1404_477');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Anaconda] 가상환경에서 GPU Tensorflow 구축하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GPU를 사용하여 딥러닝을 하기 위해서는 다음을 설치해야한다.1. Anaconda 설치 Installing Anaconda Distribution &amp;mdash; Anaconda documentationTip More of a visual learner? Sign in to Anaconda Cloud and watch the Installing Anaconda (Mac)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1774014964190&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#가상환경 생성
conda create -n test_env python=3.10.9 #test_env라는 이름의 가상환경이 python3.10.9 버전으로 설치됨

#가상환경 목록 확인
conda env list

#가상환경 활성화
conda activate test_env #activate test_env 로도 실행됨

#패키지 설치
conda install keras # keras라는 라이브러리가 설치됨

#패키지 목록 확인
conda list

#패키지 버전 검색
conda search keras #keras라는 라이브러리 버전 확인

#가상환경 비활성화
conda deactivate #deactivate 로도 실행됨

#가상환경 복사
conda create -n new_env --clone test_env #test_env 환경을 복사하여 new_env 환경을 생성

#가상환경 삭제
conda env remove -n new_env #new_env 이름의 가상환경이 삭제됨&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기초</category>
      <category>conda</category>
      <category>venv</category>
      <category>virtual environment</category>
      <category>가상환경</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/56</guid>
      <comments>https://hello-heehee.tistory.com/56#entry56comment</comments>
      <pubDate>Fri, 20 Mar 2026 23:00:31 +0900</pubDate>
    </item>
    <item>
      <title>[추리소설] 용의자 X의 헌신</title>
      <link>https://hello-heehee.tistory.com/55</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zXERi/btsM3mtTQn0/ovKWhbfdwicp7Z3ugKGO20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zXERi/btsM3mtTQn0/ovKWhbfdwicp7Z3ugKGO20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zXERi/btsM3mtTQn0/ovKWhbfdwicp7Z3ugKGO20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzXERi%2FbtsM3mtTQn0%2FovKWhbfdwicp7Z3ugKGO20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;395&quot; height=&quot;449&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;히가시노 게이고 작가의 소설로 영화로도 개봉되어 아주 유명한 작품이다.&lt;br /&gt;일반적인 추리소설과 달리 살인사건의 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;'범인'은 이미 정해져있고, 어떻게 시신을 처리한지와 인물들의 감정과 심리에 초점이 맞춰져있는 독특한 소설&lt;/span&gt;로 평가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. 시놉시스&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야스코의 전 남편 도미가시는 야스코에게 늘 돈을 요구하며 괴롭혀 왔었고, 야스코는 그를 피해 다녔지만 끊임없는 괴롭힘에 우발적으로 도미가시를 살해하게 된다. 야스코를 짝사랑 중인 이시가미는 그녀를 위해 완전 범죄를 설계하였고, 그의 오랜 친구인 물리학자 유가와가 사건을 추적한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. 후기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 추리소설과는 달리 '범인'은 정해져있어서 중후반부까지는 지루할 수 있다. 도미가시를 죽인 야스코가 '범인'이고 그녀를 도와 이시가미가 시체를 처리하기 때문이다. 하지만 이시가미가 시체를 어떻게 처리한지는 자세히 묘사되지 않고 살인사건의 전말과 시체처리 후의 내용만 담겨있어서 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;추리소설보단 일반소설 느낌이 강하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 마지막 후반은 약간의 반전과 슬픈 내용이 담겨있어서 오묘한 느낌이 들었다. 살인을 정당화할 수 없지만 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;분명히 나쁜 사람은 도미가시이고,&lt;span&gt; 야스코는 그저 살기위해 발버둥치는 중2 딸을 둔 엄마로, 범죄자의 측은한 마음이 들었다. 또한 짝사랑을 위해 이시가미가 이렇게 까지 헌신을 하는 모습이 안타까우면서도 그 또한 결국 나쁜 길로 들어선 모습에 범죄자를 응원했던 나도 죄책감이 들기도 했다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;끝까지 다 읽었을 때 느낀 감정은 굉장히 슬펐다. 보통의 추리소설은 새드엔딩도, 해피엔딩도 없는 그저 엔딩만 있다 생각했는데, 이 책은 새드엔딩이 아닐까&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;3. 줄거리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;*결말포함&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1) 이시가미와 야스코&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야스코는 호스티스에서 일하던 직원으로, 도미가시는 그 가게에 오던 손님이었다. 당시 야스코는 첫 결혼에 실패하고 혼자 일을 하면서 딸 미사토를 키우고 있었는데 도미가시와 재혼 후 행복한 나날을 보낼 것 같았지만 그의 태도는 돌변하여 결국 이혼하고 그의 손아귀에서 벗어나기 위해 이사를 하고 '벤덴데이'라는 도시락집에서 일을 하고있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이시가미는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;천재적인 수학자&lt;/span&gt;였지만, 현실적인 어려움 때문에 평범한 고등학교에서 수학을 가르치는 선생이다. 그의 삶의 낙은 옆집에 살고 있는 야스코를 지켜보는 것으로 그녀가 일하는 날에는 꼭 '벤덴데이'에서 도시락을 산다. 이를 유심히 지켜보던 도시락집 주인 요네자와 부부는 이시가미가 야스코를 좋아하는 것이 아닌가 생각하게 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) 완전범죄&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느날 도미가시는 야스코를 찾기위해 야스코의 지인이자 호스티스에서 일하는 사람을 찾아가 야스코의 행방을 묻는다. 결국 야스코를 찾아낸 도미가시는 그녀의 집으로 찾아가 돈을 갈취하고, 그 상황을 참지 못했던 미사토는 도미가시의 뒤통수를 향해 꽃병을 내리쳤다. 증오에 찬 도미가시는 미사토를 향해 덤벼들었고 야스코는 이대로 내버려두면 안되겠단 생각에 고다츠 코드를 뽑아 도미가시의 목에 둘러 그를 교살하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옆방에 살았던 이시가미는 야스코가 누군가를 죽였을 것이라는 것을 알아차렸고 안절부절 못하는 야스코에게 여자 혼자서는 시체처리하기는 힘들다며 그녀를 도와 도미가시의 시체를 대신 처리한다.&lt;br /&gt;이시가미는 뛰어난 두뇌를 이용하여 시체를 처리하고, 경찰이 의심하지 않도록 야스코에게 철저한 알리바이를 지시한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) 사건 범행일은 3월 10일&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시체는 남자. 교살흔적이 있음. 양말도 구두도 안 신은 전라상태로 발견.&lt;br /&gt;얼굴은 망가져 있어서 누구인지 분간 불가. 손가락은 불에 타 지문조회 불가.&lt;br /&gt;시체 옆 발견된 바퀴가 터져있던 새 자전거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 자전거는 도난신고가 들어온 자전거로 자전거가 도둑맞은 것은 3월 10일 오전 11시에서 오후 10시 사이라고 한다. 즉, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;범행이 일어난 날은 3월 10일&lt;/span&gt;로 추정된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형사 구사나기는 범인에 대한 결정적인 단서를 찾지 못하였지만, 숙박업소와 호텔 손님 가운데 사라진 자는 없는지 철저한조사를 벌이다 한 &amp;nbsp;렌탈 룸에서 한 남자손님이 사라졌다는 사실을 알게 되었다. 그 사실이 확인된 것은 3월 11일로 시체가 발견된 날이다. 그 방의 문손잡이나 짐에서 모발, 지문 등이 채취되었고 그 머리카락은 시체의 것과 일치했으며 자전거에서 채취한 지문 하나가 방이나 짐에 남아 있던 것과 동일하다는 사실이 확인되었다. 사라진 손님은 &quot;도미가시 신지&quot;이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4) 용의자는 야스코&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형사들은 야스코의 집에 찾아가 야스코와 그녀의 딸 미사토에게 3월 10일 사건 당일 알리바이 조사를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야스코는 아침부터 저녁6시까지 일을 했고, 미사토는 학교로 등교를 했으며, 6시 반정도엔 두 모녀가 영화를 보고, 후에 라면집에서 식사를 하고 노래방을 들렀다고 답했다. 사건 조사결과 두 모녀는 영화를 본 것이 입증되었고 노래방을 들린 것 또한 노래방주인에 의해 확인되어, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;그녀가 범인인 것 같지만 그녀를 도운 또 다른 이가 있을 것&lt;/span&gt;이라고 형사들은 추측한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구사나기는 야스코 옆집에 사는 이시가미를 찾아가 3월 10일 옆집에서 어떤 특이한 점이 없었는지 물으며, 이시가미가 데이도 대학에 나온 것을 알게 된다. 구사나기 또한 데이도 대학 졸업자로 그에게 묘한 동질감을 느낀다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5) 이시가미의 친구 유가와&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유가와는 대학교의 조교수로 구사나기의 오랜 친구이자 사건해결을 도우는 협력자이다.&lt;br /&gt;구사나기가 야스코에 대한 심문 내용을 유가와에게 털어 놓으면서, 데이도 대학 출신인 이시가미에 대해서도 말을 한다.&lt;br /&gt;유가와 또한 데이도 대학 출신으로 '이시가미' 이름을 듣자마자 대학에서 '수학'분야에서 유명했던 그를 기억한다. 추억에 잠긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이시가미와 유가와는 나름 대학에서 꽤 친했던 사이로 이시가미에겐 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;유일한 '친구'&lt;/span&gt;와도 같은 존재였다. 서로 하는 얘기는 수학관련 얘기밖에 없었지만 ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유가와는 구사나기에게서 이시가미의 집주소를 받아 이시가미의 집을 찾아가고, 그들은 오랜만에 만나 회포를 푼다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6) 이시가미의 짝사랑&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도미가시를 살해한 용의자로 유명한 야스코. 그럼에도 불구하고 이시가미는 '벤덴데이'에서 도시락을 늘 사는 것이 신기하여 유가와는 이시가미에게 도시락을 먹어보고 싶다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이시가미는 유가와와 함께 벤덴데이에서 도시락을 주문하는 와중에 어떤 남자손님이 가게로 들어왔다. 그의 이름은 '구도'로 이시가미는 이전에 구도가 야스코를 집앞까지 데려다 줬던 것이 생각났다. 구도가 벤덴데이로 들어오면서 야스코와 구도의 묘한 기류를 느끼게 된 이시가미는 질투심에 표정이 일그러졌고, 이를 발견한 유가와는 이시가미가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;야스코를 짝사랑한다는 것&lt;/span&gt;을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이시가미의 성격상 짝사랑하는 여자가 용의자라면, 그녀를 위해 무엇이든지 할 그가 아무런 행동을 취하지 않아 유가와는 이시가미에 대한 의문을 품는다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7) 용의자는 구도&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구도는 야스코가 호스티스 시절부터 서로에게 호감이 있었던 남자이다. 하지만 구도는 당시 유부남이었고, 야스코 또한 도미가시와 결혼한 상태였다. 그러하여 둘은 선은 넘지 않았고, 서로의 앞길을 응원하며 헤어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 년이 흘러 도미가시의 사건을 알게된 구도는 야스코가 걱정되어 그녀를 찾아가게 되고, 야스코 또한 구도를 보며 설렘을 느끼게 된다. 서로 연락이 끊긴 몇 년동안 구도는 부인을 사별한 독거남이었고, 야스코 또한 이혼했기 때문에 둘 사이에 거리낄 관계는 없었다. 따라서 구도는 야스코와 잘 되길 원해 미사토에게도 잘 보이려고 노력했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구사나기는 구도의 존재를 알아채고 그가 야스코를 도와 시체를 처리해준 협력자이거나 사건을 범행한 범인으로 생각했다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8) 범인은 이시가미&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구사나기는 유가와가 이시가미에 대해 조사하는 것을 알게되고 이시가미에 대해서도 조사를 시작한다.&lt;br /&gt;하지만 이렇다할 단서를 찾지 못하던 와중 이시가미는 도미가시를 살해하였다고 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;자백&lt;/span&gt;한다.&lt;br /&gt;이시가미가 자백하게 된건 유가와가 이시가미를 찾아가 한 말 때문이었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;나나 자네가 시계에서 해방된다는 것은 불가능해. 사회라는 시계의 톱니바퀴가 되어버리고 말았으니까. 톱니바퀴가 없어지면 시계는 제멋대로 움직여. 아무리 자기 멋대로 돌고 싶어도 주변에서 그걸 허락하질 않아. 그래서 안정이란 것을 얻게 되지만 자유가 없지. 노숙자 가운데는 원래의 생활로 돌아가고 싶어하지 않는 사람이 꽤 있는 모양이야.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이시가미는 본인이 야스코의 보디가드로, 야스코를 괴롭히는 도미가시를 살해했다고 진술했다.&lt;br /&gt;이시가미와 야스코는 미리 입을 맞추었고, 야스코는 이시가미에게 스토킹 당하는 것 처럼 꾸며 형사들 또한 이시가미 혼자서 범인을 살해했다고 생각했다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;9) 사건의 진실&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사건의 진상을 알고 있는 유가와는 친구 이시가미의 천재성을 누구보다 잘 알고 있다. 그의 능력을 범죄에 사용했다는 것을 알고 씁쓸했지만, 사랑을 위해 자신을 희생한 것에 슬펐다. 유가와는 결국&amp;nbsp;야스코를 찾아가 사건의 내막을 알려준다.&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;야스코가 도미가시를 죽인 것을 숨기기 위해 이시가미는 노숙자 한 명을 살해했다는 사실이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;도미가시가 죽은건 3월 9일 저녁&lt;/span&gt;으로, 야스코의 알리바이를 만들기 위해, 그리고 완전 범죄를 위해 3월 10일에 살해당한 것처럼 꾸며야 했다. 그래서 이시가미는 3월 10일 노숙자를 살해하게된다.&amp;nbsp;노숙자는 한달 전에 이주해온 사람으로, 아직 그 부근에 오두막을 짓지 않았고, 집도 없는 노숙자가 노숙자 무리에서 갑자기 사라져도 문제될 것이 없었기 때문에 그를 타겟으로 삼는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야스코가 도미가시를 죽인 다음 날 아침, 이시가미는 노숙자에게 5만엔을 건내주며 며칠간 하천공사를 살펴봐달라고 부탁을 한다. 이시가미는 그를 데리고 도미가시가 빌린 렌탈 룸으로 가서 도미가시의 옷을 갈아입히고 밤이 올 때까지 움직이지 말라고 지시했다.&lt;br /&gt;이시가미는 새 자전거를 훔쳐(주인이 반드시 신고를 한 것이기 때문에), 밤에 노숙자를 불러내었고 노숙자를 태워 시신이 발견된 현장으로 향했다. 이시가미는 노숙자를 도미가시 살해도구와 동일한 흉기(고다츠 코드)로 살해하고 얼굴을 알아볼 수 없게 짓뭉갰으며, 손가락지문을 모두 불에 태웠다. 도미가시의 시체는 이시가미 집으로 옮겨 욕실에서 토막내어 강에다 버렸다. 언젠가 발견되겠지만 이미 도미가시는 사망자 처리되었기 때문에 해당 시체의 신원을 밝힐 수는 없을 것이라고 이시가미는 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유가와가 사건의 진상을 알게되었다는 것을 안 이시가미는 경찰에 자수를 한 것이었고, 야스코에겐 자기에 대해서는 모두 잊어달라며, 구도는 좋은 남자이니 그와 행복하게 산다면 자긴 덧없이 좋을 것 같다는 짤막한 편지를 남겼다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;10) 결말&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사건의 내막과 이시가미의 애정을 알게 된 야스코는 이시가미에게 너무 미안해졌다. 자신때문에 살인누명과 함께 살인까지 하게되었으니 심한 죄책감에 빠진 야스코는 결국 범행자백을 하게된다. 이를 알게 된 이시가미는 크게 절규하여 소설은 끝이 난다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;4. 이시가미의 짝사랑 계기 및 나의 생각&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이시가미가 야스코를 좋아하게 된건 야스코가 이시가미 옆집에 이사 온 이후부터다. 이시가미는 삶의 의미가 없어 굳이 살아가야할 이유가 없었다. 목을 메달려고 한 그 순간 이시가미의 집에 누가 찾아온다.죽으려던 그가 문을 열었을 땐, 두 모녀 야스코와 미사토가 서 있었다. 이시가미는 야스코에게 첫 눈에 반했던 것이다. 몇몇 독자는 어떻게 첫눈에 반해서 살인까지 서슴없이 하냐며 개연성이 없다고 하지만, 나는 조금 달리 생각했다. 야스코에게 &quot;어떤 관계를 가지고싶다는 욕망&quot;이 아예 없었던 이시가미는 생각보다 마음은 순수한 사람으로 해석된다. 따라서 자신에게 관심을 가져주고 먼저 손을 내민 존재였기 때문에 이시가미가 야스코에게 첫 눈에 반한게 아닌가 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 소설을 읽었을 땐 도미가시가 야스코만 괴롭히지 않았어도 야스코가 도미가시를 죽이지 않았을 것이고, 이시가미가 협력자로써 시체를 처리하지 않았을텐데라는 생각이었다. 그래서 이시가미와 야스코가 형사에게 들키지 않길 바랬다. 하지만 사건의 내막을 알게 되었을 땐, 이시가미가 야스코에 대한 헌신이 도를 넘어 아무 죄없는 노숙자를 죽였단 사실에 &quot;내가 범죄자를 응원했구나&quot;하며&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;약간의 죄책감이 들었다. 그러면서 이시가미도, 야스코도 그 어느 누구도 행복하게 끝나지 않아서 안타까웠다...&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start; background-color: #f6e199;&quot;&gt;추리소설 광이라면 꼭 추천해주고 싶은 소설이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>도서리뷰</category>
      <category>용의자x의헌신</category>
      <category>추리소설</category>
      <category>히가시노게이코</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/55</guid>
      <comments>https://hello-heehee.tistory.com/55#entry55comment</comments>
      <pubDate>Sun, 30 Mar 2025 22:20:04 +0900</pubDate>
    </item>
    <item>
      <title>[추리소설] &amp;quot;해바라기가 피지 않는 여름&amp;quot; 해석</title>
      <link>https://hello-heehee.tistory.com/54</link>
      <description>&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;266&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzGRF/btsMSDxHnll/KpVLGyMwYTokpI12TQSZIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzGRF/btsMSDxHnll/KpVLGyMwYTokpI12TQSZIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzGRF/btsMSDxHnll/KpVLGyMwYTokpI12TQSZIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkzGRF%2FbtsMSDxHnll%2FKpVLGyMwYTokpI12TQSZIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;266&quot; height=&quot;244&quot; data-origin-width=&quot;266&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;추리 소설 중에서 나름 인지도 있는 해바라기가 피지 않는 여름.&lt;br&gt;저자는 &lt;b&gt;미치오 슈스케&lt;/b&gt;로 가장 유명한 책이 &quot;해바라기가 피지 않는 여름&quot;이라고 생각한다.&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;background-color: #C0D1E7;&quot;&gt;1. 시놉시스&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;N마을에 사는 초등학교 4학년 미치오는 미카라는 여동생과 엄마, 아빠 넷이 살고 있다. 여름 방학을 앞둔 종업식날 미치오는 담임선생님인 이와무라 선생님의 심부름으로 결석한 S의 집을 찾아간다.&lt;br&gt;미치오는 S의 집에서 목을 매고 죽어있는 S의 시체를 발견하게 되고, 떨리는 마음을 부여잡고 학교로 돌아가 이와무라선생님에게 사건의 내용을 털어놓는다. 소식을 들은 이와무라 선생님은 경찰과 함께 S의 집을 찾아가지만 시신은 사라지고 없었다. 미치오는 미카와 함께 수수께끼같은 사건의 진상을 좇기 시작한다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #C0D1E7;&quot;&gt;2. 후기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;시놉시스를 읽고 내용이 궁금하다면 실제 서적을 읽기를 추천한다. 또한 추리소설을 좋아한다면 한 번쯤 읽어볼만하다.&lt;br&gt;나의 추리로는 범인을 찾지는 못했다. &lt;span style=&quot;background-color: #FFC9AF;&quot;&gt;끝 마무리가 물음표로 끝나기 때문이다.&lt;/span&gt; &lt;br&gt;예전에 이 소설을 읽어본 적이 있었는데, 읽으면서 스토리는 기억났지만 결말이 기억나지 않았다. 다 읽고나니 기억안날만 했다.&lt;br&gt;아가사 크리스티나 히가시노 게이고 소설을 좋아하는 나로써는 조금 난해한 내용이었고 여러 해석 및 견해들을 검색하며 찾아보아도 찜찜함에서 벗어날 수 없었다. 아무튼 이 책을 읽고 나의 생각에 대해 조금 적어보려 한다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot;&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;스포가 될 수 있으니 이 이후부터는 참고 바란다.&lt;br&gt;처음엔 &quot;&lt;span style=&quot;background-color: #FFC9AF;&quot;&gt;환생&lt;/span&gt;&quot;에 관한 이야기인가 생각을 할 정도로 판타지를 좋아하지 않던 나로써는 거부감이 들었지만, 초반 스토리가 흥미진진했고 책 내용의 중반까지 왔을 땐 환생에 대해 긍정적으로 생각할 정도로 내용이 재밌었다. 도코 할머니나 미치오의 동생 미카의 존재를 알게된 순간부터 결말까지 내용이 종잡을 수 없을 정도로 산으로 가는 느낌이 들었다. 그 이유는 죄다 환생을 했기 때문이다. 하지만 이 책은 불교 관련 서적도 아니었기 때문에 이질감이 들 수 밖에 없었고 책을 모두 읽고 내린 결론은 미치오의 &quot;&lt;span style=&quot;background-color: #FFC9AF;&quot;&gt;정신병&lt;/span&gt;&quot; 그리고 인간의 &quot;&lt;span style=&quot;background-color: #FFC9AF;&quot;&gt;죄책감&lt;/span&gt;&quot; 때문에 환생이 나온 것이라는 결론을 내렸다. 결국 S나 도코할머니나 동생 미카는 환생을 한 것이 아닌 미치오의 상상이다. 생각해보면 S도, 미카도 다이조 할아버지도 미치오가 죽인 것이나 다름 없기 때문에 죽어도 환생으로 인해 &quot;행복&quot;하게 잘 살고 있다고 생각하며 자신을 위로하는 내용이라고 본다. 근데 여기서 의문이 드는 점은 도코 할머니이다. 도코할머니는 미치오가 의지하는 존재로 미치오가 죽인 인물은 아니다. 따라서 본인의 죄책감때문에 자신만의 세계를 만들어 도피하는 것도 맞지만 유일하게 의지했던 할머니의 죽음때문에 그리움의 대상인 할머니 또한 환생했다고 생각한 것이다.&amp;nbsp;&lt;br&gt;어찌보면 미치오 또한 가족에게 사랑을 받지 못한 불쌍한 존재로 볼 수 있지만, 인간의 내면에는 나약함, 악함 등등이 순수한 초등학생에도 있음을 보여주는게 아닐까 싶다.&lt;br&gt;그리고 미치오가 도코할머니를 찾아갔을 당시 &quot;군다리명왕&quot;이 있었는데 군다리명왕은 눈이 세개, 팔이 여덟개로 뱀이 손하고 발을 휘감고 있는 동상으로, 이 동상은 다시 태어나는 것을 의미하고 환생에 대한 뜻을 담고 있다고 알려주는 장면이 등장한다.&amp;nbsp;&lt;br&gt;여기서 눈치 챘어야 했는데,,,, 떡밥이라고도 생각하지만, 이 이후로 죽은 등장인물이 죄다 환생하면서 내용이 점차 이상해졌다. &lt;br&gt;아마 미치오가 이 동상을 본 시점부터 죄책감, 그리움에 죽은 사람들이 &quot;환생&quot;했다는 명목하에 정신병이 생겨버린건 아닌가 알려주는 장면이라고 본다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #C0D1E7;&quot;&gt;3. 줄거리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #FFC9AF;&quot;&gt;* 결말포함&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 주인공 미치오가 살고 있는 동네&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;미치오는 N마을에 사는 초등학교 4학년으로, N마을에서는 고양이가 연달아 죽는 사건이 발생한다. 죽은 고양이들은 모두 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;비누&lt;/span&gt;를 입에 물고 있었으며, &lt;span style=&quot;background-color: #F6E199;&quot;&gt;다리가 모두 부서진 형태&lt;/span&gt;였다. 아직 범인을 잡지 못했고 범인 또한 특정되지 않은 상태이다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) S의 죽음&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;여름 방학을 앞둔 종업식날 미치오는 결석한 S에게 전해 줄 S의 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;소설원고&lt;/span&gt;를 들고 S집에 찾아간다. 미치오는 S의 집에서 목을 매고 죽어있는 S의 시체를 발견하게 되고, 떨리는 마음을 부여잡고 학교로 돌아가 담임 선생인 이와무라에게 사건의 내용을 털어놓는다. 소식을 들은 이와무라 선생은 경찰과 함께 S의 집을 찾아가지만 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;시신은 사라지고 없었다&lt;/span&gt;. S의 시신이 없어져버린 탓에 경찰과 이와무라선생은 미치오의 신고에 의심을 품게 된다. 하지만 목을 매단 흔적과 S의 시신이 있던 곳에 배설물을 닦은 흔적이 발견되고 S가 목을 매단 것이 기정 사실화되었다. 하지만 자살한건지 살해당한건지 알 수 없는 상황에서 미치오는 S를 죽인 범인을 찾으려 한다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;3) 도코 할머니&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;미치오는 자신의 친구와도 같은 도코할머니를 종종 찾아가 고민상담을 하기도 하고 조언을 듣는데, 이 사건에 대해서도 도코할머니께 털어놓는다. 도코할머니는 &quot;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;냄새&lt;/span&gt;&quot;라는 짤막한 말만 남겼고, S의 집에 갔던 당일 S가 키우던 강아지 다이키치가 자신에게 달려오던 것이 혹시 냄새 때문이 아닐까 추측하게 된다.&lt;br&gt;미치오는 당일 S의 집에 가기전 이와무라 선생이 땀을 흘리고 있는 자신에게 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;손수건&lt;/span&gt;을 빌려주었다는 것을 깨달았고 범인의 냄새와 동일하다고 느낀 다이키치가 자신에게 달려든 것이 아닐까 생각하며 이와무라 선생을 범인으로 생각했다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;4) 환생한 S&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;S는 생전에 닮았던 거미로 환생하여 미치오를 찾아온다. S는 자신은 이와무라 선생님에게 살해당했다고 미치오에게 고한다. 하지만 물증도 없었고 시신 또한 없었기 때문에 미치오, 미치오의 여동생 미카, 그리고 S는 이와무라 선생을 미행해 집을 알아내어 시신과 증거를 찾아내려 한다.&lt;br&gt;이와무라 선생을 미행하기로 한 날 S가 엄마를 보고 싶어하여 등교하기 전 미치오는 S가 담겨있는 유리병을 가지고 S의 집에 찾아간다. S의 집에는 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;다이조라는 할아버지&lt;/span&gt;가 있었고 다이키치는 그를 향해 매우 짖고 있었다. 다이키치가 다이조 할아버지에 달려 들었던 이유는 무엇일까?&amp;nbsp;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;5) 이와무라 선생의 실체&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;이와무라 선생을 미행해 집에 몰래 들어간 미치오와 S는 이와무라 선생의 집을 뒤져보게 된다. 나체의 소년들의 사진을 보게된 미치오. 그리고 나체의 S가 나오는 영상을 보게된다. 이와무라선생은 어린 남자 아이를 좋아하는 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;소아성애자&lt;/span&gt;였다. 미치오는 가까스로 이와무라의 집을 탈출 하였고, 머리가 복잡해지기 시작했다. 왜냐하면 이와무라선생의 집에서 명찰을 잃어버렸기 때문이다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;6) 다이조 할아버지&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;다이조는 S의 집 건너편에 살고 있는 할아버지로 미치오에게 &quot;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;성애에의 심판 (로쿠무라 가오루 지음)&quot;&lt;/span&gt; 이라는 책에 대해서 알려준다. 이 책은 주인공 남자가 소년을 살해해 시체에 장난을 하는 내용이 가득 담긴 소설책이었다. 왠지 이 책 내용이 현재 상황과 유사하다 생각한 미치오는 도서관에서 책을 대출하였고, 진전이 없는 현재 상황에 조언을 들을겸&amp;nbsp;&amp;nbsp;도코 할머니를 찾아간다. 도코 할머니는 &quot;다이키치 에이고&quot; 라는 말씀을 남겼고 에이고는 '영어'라는 뜻으로 '다이키치' 는 영어로 &quot;Lucky&quot;를 뜻한다. 이를 다시 생각해보면 '이와무라'에서 이와는 바위라는 뜻으로 영어로는 Rock(로쿠)를 의미한다. 소설책의 저자가 이와무라의 필명이라는 것을 깨달은 미치오는 경찰에 이를 알리기 위해 전화를 거는데 해당 사건을 수사하는 경찰은 학교에 있음을 알게 되고 학교를 찾아가게 되지만 이와무라 선생에게 들켜 협박을 당해 소설에 대해 경찰한테 말하지 못하게 된다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;7) S의 시체와 도코할머니의 죽음&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;어느날 S의 집에서 S의 시체가 발견되어 마을이 시끄러웠다. S네의 강아지 다이키치가 S의 시체를 마당에 갖고 온 것이다. 어디서 찾아 온건지도 알 수 없었으며 S의 입에도 비누가 검출되어 사건은 더더욱 미궁으로 빠지는 와중에, 도코 할머니가 살해당했다는 뉴스기사가 떴다. 똑같이 비누를 입에 머금고 처참한 몰골로 죽었다는 기사였다. 가장 의지했던 도코할머니의 죽음으로 인해 미치오는 분노에 휩싸이게 된다.&lt;br&gt;사건이 조금 진정된 후 미치오는 S의 엄마를 찾아가 S에 대해 듣게 된다. S는 상한 고기를 밖에 숨겨놓고 다이키치가 썩은 냄새를 맡으면 집에 찾아오게끔 훈련을 했던 것이다. 이 내용을 듣고 충격받은 미치오는 S를 추궁했지만 별다른 이유를 듣지는 못했다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;8) S의 실체&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;미치오는 종업식날 S에게 전해주려했던 S가 쓴 소설원고지에서 희미하게 보이는 &quot;X&quot; 표시들을 발견하게 되고 이는&amp;nbsp;&amp;nbsp;마을에서 발생한 고양이 연쇄살인사건과 깊은 연관이 있다는 것을 알게 된다. X로 표시된 자국은 마을 지도와 비교했을때 고양이가 죽었던 지역들로, 지도에 표시할 때 지도 아래에 원고지가 있어서 이 자국들이 생긴 것으로 미치오는 추측했다. 미치오는 S에게 실상을 물었지만, S는 본인이 고양이를 죽인 것이 아닌 다이조 할아버지가 범인이라고 지목하였고 그 증거로 이전 다이키치가 할아버지에게 덤벼 든 이유가 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;시체 썩은 냄새&lt;/span&gt; 때문이라고 얘길했다.&lt;br&gt;미치오는 사건의 전말을 깨닫고 다이조 할아버지를 찾아간다. 하지만 할아버지는 S가 고양이를 죽이면, 자신은 그저 고양이의 다리를 부러뜨리는데 일조했단 사실을 털어놓았다. S는 학교에서 왕따를 당해 그 스트레스로 고양이를 죽여왔고, 어느 날 할아버지는 죽은 고양이를 발견했는데, 고양이 다리를 부러뜨리는 것을 S에게 들켜버려 이 상황까지 오게되었다고 한다. 그 날 이후 S가 지도에 X표시를 하여 자신에게 고양이 위치를 알려주면 고양이 다리를 부러뜨려왔다고 설명했다. 또한 할아버지는 과거에 엄마가 돌아가셨는데, 어느날 엄마의 무덤이 파헤쳐 있고 죽은 엄마가 가부좌상태로 앉아있던걸 발견하게 되었다. 죽은 엄마가 환생하여 자신을 찾아왔다는 공포에 휩쌓여 혹시 죽은 고양이들도 자신을 찾아올꺼봐 두려워 고양이들의 다리를 부러뜨려놨다는 것이다.&lt;br&gt;S가 고양이를 처음에 죽였을 땐, 혹시 고양이 시체가 있던 곳에 자신을 보았다는 사람들이 늘어나면 범인으로 지목될까봐&amp;nbsp; 다이키치에게 썩은 냄새가 나는 것들을 집으로 물고 오게 끔 S는 훈련했다. 하지만 S는 다이조 할아버지에게 고양이를 조공하기 위해서는 다이키치가 고양이 시체를 옮기면 안되었기 때문에 과거 다이키치는 비눗물에 안좋은 트라우마가 있어서 비누 냄새를 무서워한다는 점을 이용하여 고양이 입에 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;비누 조각&lt;/span&gt;을 넣었다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: center;&quot;&gt;&lt;b&gt;이 후부터는 결말입니다.&lt;/b&gt;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;9) 반전 - 미카의 존재&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;의문을 품은 미치오는 S를 추궁했지만 계속되는 S의 거짓말로 거미가 된 S를 죽여 미카에게 먹이로 주었다. 실은 미카는 살아있는 사람이 아닌 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;도마뱀&lt;/span&gt;이다. 죽은 미카가 도마뱀으로 환생한 것이었다.&lt;br&gt;미치오의 엄마가 미카를 임신하고 있었을때 미치오는 서프라이즈로 신발장에 선물인 화분을 숨기고 신발장에 불이 났다고 소리쳤다. 이를 들은 엄마가 급하게 계단을 내려오며 발을 헛딛여 미카를 유산하고 영원히 임신할 수 없는 몸이 되어버렸다. 이 이후로 미치오의 엄마는 미치오를 원망하고 미워하게 되었고, 인형을 미카라 생각하며 살아왔던 것이다.&lt;br&gt;미치오는 아직 완전한 사람형태가 아니었던 죽은 미카를 보며 도마뱀처럼 생겼다 생각했는데 어느날 집 앞 마당에서 도마뱀으로 환생한 미카를 보게되었다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;10) 반전 - S의 자살&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;S를 죽이고 다이조 할아버지를 다시 찾아간 미치오. 그리고 할아버지를 추궁했다. 할아버지는 고양이의 다리를 부러뜨릴 이유가 없었기 때문이다. 즉은 고양이가 할아버지를 찾아갈 이유가 없었고, 단순히 무언가를 부수고 싶은 할아버지의 욕망에 죽은 고양이 다리를 부러뜨렸다는 것을 알게되었다. 그리고 S는 마지막으로 다이조 할아버지께 자신을 선물로 주었다. 즉, 마지막 지도의 'X'표시는 S의 집이었으며 S는 스스로 생을 마감했다. 의도치 않게 미치오는 S의 집에 방문하게 되었으며 할아버지는 혹여나 고양이 사건과 비롯하여 자신도 사건에 휘말리게 될까봐 S의 시체를 본인 집 마당에 있는 창고로 옮기게 되었다. 옮기던 와중 S의 입에 있던 비누가 떨어지게 되었고 그 비누는 S의 마당에 있던 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;피지 않은 해바라기&lt;/span&gt; 속에 떨어져 경찰도 수색할 당시 이를 찾을 수 없었다. 후에 시체 썩는 냄새가 더욱 진해져 다이키치는 할아버지 집 마당에서 S를 꺼내 S집으로 옮겨놓게 되었던 것이다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;11) 반전 - 도코할머니&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;사건의 전말을 알게 된 미치오는 다이조 할아버지에게 도코 할머니를 죽이지만 않았다면 자신은 이러지 않았을 것이라고 얘길 하며 다이조 할아버지를 살해하게 된다. 알고 보니 도코할머니는 2년전 죽었고 고양이로 환생하게 되었는데, 다이조 할아버지는 S의 죽음으로 인해 고양이 연쇄살묘(?)사건이 끝나게 되면 S가 범인으로 의심받을 것이고 본인 또한 관련되어 있음이 들킬까봐 일부러 고양이를 죽이고 입에 비누를 넣어놨던 것이다.&lt;br&gt;곱등이로 환생한 다이조 할아버지. 미치오는 환생한 할아버지도 집에서 같이 살게 된다.&lt;br&gt;뉴스에서는 다이조 할아버지가 S를 살해했고, 고양이 연쇄살묘의 범인으로 죄책감끝에 자살했다는 결론으로 이 사건은 마무리 된다.&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;12) 반전 - 미치오의 실체&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;실은 미치오는 S를 직접적으로 괴롭히진 않았지만 싫어했던 한 사람으로써, S와 연극을 하게 되었을 때, S가 미치도록 싫었다. S와 연극을 하게 되면 본인 또한 왕따를 당할 것이라 생각했기 때문에 연극을 하지 않으려면 S가 죽어야 된다고 생각했다. 그래서 S에게 죽어줬으면 좋겠다고 얘기했고, S는 본인이 죽었으면 좋겠냐고 미치오에게 되물었지만 돌아오는 대답은 그렇다였다.&lt;br&gt;어찌보면 미치오가 죽으라고 해서 죽은 S였다.&lt;br&gt;미치오는 본인이 죽인 것이 아니라는 합리화를 위해 이와무라선생이 소아성애자라는 프레임을 씌웠고 (실은 집에도 찾아가지 않았음) 자신 때문에 죽은 이들도 모두 환생하여 잘 산다고 생각해온다. 하지만 현실은 그렇지 않음을 알게 되고 미치오 또한 환생하여 행복하게 살기 위해 집에 불을 피워 자살한다.&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #9D9D9D;&quot;&gt;실제로 자살했다, 죽었다, 이런 표현은 나와있지 않다. 내용의 흐름을 보면 미치오의 방화로 부모도 미치오도 죽게 되었고 장례식에서 만난 사촌에게 본인은 환생하였다고 말하며 사촌을 따라간다는 뉘앙스로 이야기가 마무리 된다. 아마 죽어서도 본인만의 세상에서 산다는 뜻이겠지...&lt;/span&gt;&lt;/p&gt;</description>
      <category>도서리뷰</category>
      <category>스포</category>
      <category>스포일러</category>
      <category>줄거리</category>
      <category>추리소설</category>
      <category>해바라기가피지않는여름</category>
      <category>해석</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/54</guid>
      <comments>https://hello-heehee.tistory.com/54#entry54comment</comments>
      <pubDate>Sun, 23 Mar 2025 00:47:48 +0900</pubDate>
    </item>
    <item>
      <title>[논문리뷰] LogGPT: Log Anomaly Detection via GPT</title>
      <link>https://hello-heehee.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2309.14482&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;LogGPT:&amp;nbsp;Log&amp;nbsp;Anomaly&amp;nbsp;Detection&amp;nbsp;via&amp;nbsp;GPT&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740405305410&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;LogGPT: Log Anomaly Detection via GPT&quot; data-og-description=&quot;Detecting system anomalies based on log data is important for ensuring the security and reliability of computer systems. Recently, deep learning models have been widely used for log anomaly detection. The core idea is to model the log sequences as natural &quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2309.14482&quot; data-og-url=&quot;https://arxiv.org/abs/2309.14482v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clcxjY/hyYjsKpIti/KG5VWzN6bBazFGDi3jDVlk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/sDNo1/hyYjLJSKVf/DYLtJvFwjaEHcYmSfFZkIK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2309.14482&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2309.14482&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clcxjY/hyYjsKpIti/KG5VWzN6bBazFGDi3jDVlk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/sDNo1/hyYjLJSKVf/DYLtJvFwjaEHcYmSfFZkIK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;LogGPT: Log Anomaly Detection via GPT&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Detecting system anomalies based on log data is important for ensuring the security and reliability of computer systems. Recently, deep learning models have been widely used for log anomaly detection. The core idea is to model the log sequences as natural&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; &lt;a href=&quot;https://github.com/nokia/LogGPT&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenSource Code&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740405366514&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - nokia/LogGPT&quot; data-og-description=&quot;Contribute to nokia/LogGPT development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/nokia/LogGPT&quot; data-og-url=&quot;https://github.com/nokia/LogGPT&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/FM6PZ/hyYjuO1GEJ/DeZjqKfOENvljXsUf0riKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/crbKLz/hyYjyX5gdB/JxKeQl2IutqSzgbvcCBer1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/nokia/LogGPT&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/nokia/LogGPT&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/FM6PZ/hyYjuO1GEJ/DeZjqKfOENvljXsUf0riKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/crbKLz/hyYjyX5gdB/JxKeQl2IutqSzgbvcCBer1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - nokia/LogGPT&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to nokia/LogGPT development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. 목적&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 이상 탐지 모델은 Traditional Machine Learning(PCA, OCSVM 등)과 Deep Learning(DeepLog, LogAnomaly, LogBERT 등) 기법이 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 데이터는 자연어처럼 시퀀스로 구성되므로 최근에는 언어 모델인 LSTM, Transformer등을 활용한 방법들이 연구되고 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*시퀀스: 연속적으로 발생하는 이벤트(사건)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 기존 로그 언어 모델 기반 방법들은 학습과정(미래예측)과 이상탐지(정상/비정상구분) 간의 목적불일치가 존재한다.&lt;br /&gt;그러하여 LogGPT 모델을 제안한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. 본론 - 기존 이상탐지 모델&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Traditional Machine Learning&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 분야에서 폭넓게 사용하지만 feature engineering을 매뉴얼로 해야하고 데이터들이 선형적 관계가 있다는 가정하에 사용한다.&lt;br /&gt;복잡한 패턴을 학습하기에 어렵다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PCA(Principal Component Analysis)&lt;/li&gt;
&lt;li&gt;Isolation forest&lt;/li&gt;
&lt;li&gt;OCSVM(one-class Suppert Vector Machines)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Deep Learning&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습한 데이터 내에서만 활용이 가능하다. (새로운 데이터를 사용할 경우 성능이 하락할 수도 있다)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LSTM-based models : DeepLog, LogAnomaly, OC4Seq&lt;/li&gt;
&lt;li&gt;BERT-based models: LogBERT&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 모델들은 Log Language model이라고 하며, 다음에 나오는 Log가 무엇인지 예측하거나 masking된 Log를 예측한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;3. 본론 - 로그이상탐지&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lvy8e/btsMvUkGaHh/0Zo7QcuvPUkL33vVFzqqz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lvy8e/btsMvUkGaHh/0Zo7QcuvPUkL33vVFzqqz1/img.png&quot; data-alt=&quot;Fig 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lvy8e/btsMvUkGaHh/0Zo7QcuvPUkL33vVFzqqz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flvy8e%2FbtsMvUkGaHh%2F0Zo7QcuvPUkL33vVFzqqz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;381&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Log Sequence Preprocessing&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 기반 로그 메세지에서 &lt;a href=&quot;https://hello-heehee.tistory.com/47&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Drain&lt;/a&gt; 기법을 통해&amp;nbsp; LogTemplate을 만들어준다.&lt;/p&gt;
&lt;figure id=&quot;og_1740393432459&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NLP] 텍스트 데이터 전처리 - Log Template&quot; data-og-description=&quot;자연어인 로그 데이터를 딥러닝할 때 전처리는 어떻게 할까?보통 로그 데이터는 패턴이 존재한다. 이 패턴에 대해서 알고 있다면 공통 패턴이 되는 템플릿(Template)을 만들어 처리하면 되지만 만&quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/47&quot; data-og-url=&quot;https://hello-heehee.tistory.com/47&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b8Rmug/hyYjMILccC/WB8PuuEhKJjVAcK3oPe2I0/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/ciAiwq/hyYjvtxJ7w/BLAlS2ekDEfuyAwv6823uk/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/tgkFE/hyYjoOKNmi/2rxBHgu2ZcGj9ByF8LTZ8K/img.png?width=941&amp;amp;height=451&amp;amp;face=0_0_941_451&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/47&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/47&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b8Rmug/hyYjMILccC/WB8PuuEhKJjVAcK3oPe2I0/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/ciAiwq/hyYjvtxJ7w/BLAlS2ekDEfuyAwv6823uk/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/tgkFE/hyYjoOKNmi/2rxBHgu2ZcGj9ByF8LTZ8K/img.png?width=941&amp;amp;height=451&amp;amp;face=0_0_941_451');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NLP] 텍스트 데이터 전처리 - Log Template&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자연어인 로그 데이터를 딥러닝할 때 전처리는 어떻게 할까?보통 로그 데이터는 패턴이 존재한다. 이 패턴에 대해서 알고 있다면 공통 패턴이 되는 템플릿(Template)을 만들어 처리하면 되지만 만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogTemplate의 Index와 Log Sequence간 Matching을 한 Integer값을 LogKey라고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Log Language Model&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 DeepLog에 대해서 설명한다. 여기서 중요한건 Top-K 기법이다.&lt;br /&gt;DeepLog는 작은 windows로 시퀀스를 쪼개서 LSTM model에 학습하고 주어진 새로운 시퀀스의 다음 LogKey에 대해 예측한다.&lt;br /&gt;그런 다음 관찰된 LogKey가 해당 시퀀스의 모든 sliding window에서 Top-K Prediction List에 여러 번 나타나지 않으면 비정상 시퀀스는 비정상으로 라벨링 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;로그 시퀀스의 불확실성과 변동성을 설명하기 위해 Top-K prediction 개념이 도입되었는데, 정상이지만 여러 정상 패턴이 있기 때문에 유효한 &quot;next&quot; LogKey가 여러개 있을 수 있다. 따라서 이상탐지에서 모델은 단일 '가능성이 가장 높은' 다음 LogKey를 예측하는 대신 Top-K most probable next LogKeys를 식별한다. 관찰된 LogKey가 Top-K List에 있는한 정상시퀀스로 생각할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;4. 본론 - LogGPT(Log Generative Pretrained Transformer) 구조&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogGPT는 DeepLog처럼 관찰된 LogKey가 Top-K Prediction List에 있는지 여부를 조사하여 로그이상을 탐지한다.&lt;br /&gt;GPT는 DeepLog에서 사용하는 LSTM에 비해 더 강력한 구조이기 때문에 LogGPT는 시퀀스를 작은 Window로 쪼개지 않아도 된다. 대신 이전 시퀀스에 주어진 다음 LogKey를 예측하도록 훈련되며, 이는 본질적으로 로그 시퀀스의 장기적인 의존성을 포착할 수 있다. 또한 로그이상탐지 성능을 더욱 향상시키기 위한 새로운 강화학습전략을 제안한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVv7ZE/btsMvyvrwfo/Jd6IpY9BiKEPmpPKajj4kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVv7ZE/btsMvyvrwfo/Jd6IpY9BiKEPmpPKajj4kk/img.png&quot; data-alt=&quot;Fig 2: Framework of LogGPT&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVv7ZE/btsMvyvrwfo/Jd6IpY9BiKEPmpPKajj4kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVv7ZE%2FbtsMvyvrwfo%2FJd6IpY9BiKEPmpPKajj4kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1214&quot; height=&quot;437&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 2: Framework of LogGPT&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;1) Pre-training&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적인 언어모델이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;2) Fine-tuning&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정상과 비정상 로그 시퀀스 구분을 하는 모델의 능력으로 재정의한다.&lt;/li&gt;
&lt;li&gt;강화학습기법을 사용하여 pre-trained LogGPT를 fine-tuning(미세조정)한다.&lt;/li&gt;
&lt;li&gt;Fine-tuning을 위한 Top-K Metircs 라는 새로운 reward를 제안한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transformer Decoder는&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Self-Attention을 매커니즘으로 하는데 LogGPT는 이&lt;/span&gt;를 base로 하는 GPT-2를 활용하였다.&amp;nbsp;&lt;br /&gt;LogGPT는 주어진 LogKeys에 대한 다음 LogKey를 예측하도록 학습한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;5. 본론 - 로그이상탐지를 위한 강화학습&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pre-trained GPT-2 모델을 Fine-Tuning하기 위해 강화학습을 사용한다.&lt;br /&gt;강화학습은 모델이 예측을 통해 학습하고 이에 대한 피드백을 바탕으로 행동을 조정할 수 있게 하여 이상탐지 능력을 향상시킨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;State&lt;/b&gt;: 주어진 하나의 로그 시퀀스의 부분으로 정의한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Action&lt;/b&gt;: LogGPT가 예측한 가장 높은 확률로 K개의 LogKeys 중에서 하나를 샘플링(Sampling)하는 것이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Policy&lt;/b&gt;: LogGPT의 형태를 가지며 parameters(매개변수)들에 의해 정의된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reward&lt;/b&gt;: Reward Function은 Policy의 Action 품질에 따라 피드백을 제공한다. &lt;br /&gt;논문에서는 이상탐지에서 예측된 LogKey평가를 위한 새로운 Top-K matirc이라는 Reward Function을 제안한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;* Top-K matric&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Top-K matric은 이상탐지에서 LogGPT의 더 나은 Generalization(일반화)와 Robustness(견고함)을 향상시킨다.&lt;br /&gt;따라서 Top-K matric은 모델의 예측을 로그데이터의 복잡한 특성과 일치시켜 이상탐지의 정밀도를 향상시킨다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Policy업데이트를 위해 Proximal Policy Optimization(PPO)를 사용하였다.&amp;nbsp;&lt;br /&gt;PPO는 예측된 reward를 극대화하여 Policy를 직접 최적화하고 학습과정의 안정성을 더 유지하고 유해한 업데이트를 방지할 수 있는 일종의 Policy Gradient Method이다.&lt;br /&gt;Policy 업데이트 절차는 Policy가 수렴하거나 최대 반복횟수에 도달할 때 까지 여러번 반복된다.&lt;br /&gt;Top-K Metirc은 더 큰 set 내에서 실제 다음 LogKey를 포함하는 예측을 rewarding하여 모델이 정상 로그데이터의 고유한 변동성을 인지하도록 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fine-tuning 후에 LogGPT가 배포되어 비정상 로그 시퀀스를 탐지한다.&lt;br /&gt;새로운 로그 시퀀스가 주어지면 LogGPT는 다음 LogKey에 대해 반복적으로 예측한다.&amp;nbsp;&lt;br /&gt;모델은 각 예측된 LogKey에 대해 Top-K 예측 LogKeys를 생성한다. 이 셋은 현재에서 가장 가능성이 높은 K개의 LogKeys를 나타낸다. 그런 다음 실제 next LogKey를 이 셋과 비교한다. 실제 LogKey가 Top-K 예측 LogKey셋에 하나라도 포함되지 않는다면 전체 로그 시퀀스는 비정상으로 표시된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;6. 본론 - 실험(학습 및 평가)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Datasets&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HDFS(Haddop Distributed File System)&lt;/li&gt;
&lt;li&gt;BGL(BlueGene/L Supercomputer System)&lt;/li&gt;
&lt;li&gt;Thunderbird&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czfn0Q/btsMtrxTNQg/gtQ72OMG4UKHgp4Uywd6o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czfn0Q/btsMtrxTNQg/gtQ72OMG4UKHgp4Uywd6o0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czfn0Q/btsMtrxTNQg/gtQ72OMG4UKHgp4Uywd6o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczfn0Q%2FbtsMtrxTNQg%2FgtQ72OMG4UKHgp4Uywd6o0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;220&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Baselines&lt;/b&gt; :다른 기초가 되는 traditional machine learning model 및 deep learning model과 LogGPT간 비교&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PCA(Principal Component Analysis)&lt;/b&gt;: LogKey 시퀀스의 빈도수 기반으로 Counting Matrix를 구성한다. 그런 다음에 이 행렬을 저차원 공간으로 축소하여 이상치를 식별한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;iForest(Isolation Forest)&lt;/b&gt;: 비지도 학습 알고리즘으로 Counting Matrix를 Input으로 사용하기도 한다. Normal data points를 프로파일링하는 대신 이상치를 분리한다. 이 알고리즘은 트리구조인 특징을 가지고 있고, 구성된 isolation trees에서 평균 path 길이가 짧은 인스턴스로 이상티를 탐지한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OCSVM(One-Class Support Vector Machine)&lt;/b&gt;: 이상탐지를 위해 설계된 Support Vector Machine 알고리즘으로 이 모델은 정상 데이터를 학습하여 정상 데이터와 origin(원점)을 구분하는 최대 margin hyperplane을 찾는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LogCluster&lt;/b&gt;: 유사한 로그 메시지와 함께 밀도기반 로그 클러스터링 접근방식이다. 이상치는 다른 클러스터에 속하지 않거나 작은 클러스터들에 속하는 로그메시지로 탐지된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DeepLog&lt;/b&gt;: 로그데이터 이상탐지를 위한 딥러닝 기반 접근방식이다. Long Short-term memiry(LSTM) 네트워크를 사용하여 로그 시퀀스를 모델링하고 예측오차를 기반으로 이상치를 탐지한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LogAnomaly&lt;/b&gt;: Log stream을 자연어 시퀀스로 모델링하여 순차적과 정량적 로그이상탐지를 동시에 감지할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OC4Seq(Multi-Scale One-Class Recurrent Neural Networks)&lt;/b&gt;: 불연속 이벤트 시퀀스에서 이상치를 탐지하도록 디자인되었다. 개별이벤트, 이벤트의 하위시퀀스 또는 전체 시퀀스에 의해 이상 시퀀스가 발생할수 있다는 것을 인식한 OC4Seq는 multi-scale RNN framework를 사용하여 다양한 수준의 순차적인 패턴을 동시에 캡처한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LogBERT&lt;/b&gt;: 로그 언어모델을 통해 정상 시퀀스의 패턴을 캡처하는 BERT기반 아키텍처이다. 정상 로그 시퀀스를 통해 masking된 LogKeys를 예측하도록 학습되며, 예측 오차 기반으로 비정상 로그시퀀스를 탐지한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CAT(Content-Aware Transformer)&lt;/b&gt;: 이벤트 시퀀스에서 이상탐지를 위해 설계된 self-attentive encoder-decorder transformer framework이다. content-awareness layer를 사용하여 각 이벤트의 representation을 생성함으로써 event content의 semantic information을 통합한다. Encoder는 콘텐츠 인식을 통해 preamble event sequence representations를 학습하고 Decoder는 탐지하에 시퀀스를 이상탐지 가능한 latent space에 임베딩한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) Implementation Details&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Drain을 이용하여 로그메시지들을 파싱하여 LogKeys로 만들어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이상탐지를 위해 PCA, OCSVM, iForest, LogCluster에는 Loglizer 패키지를 이용하고, DeepLog, LogAnomaly에는 Deep-loglizer 패키지를 이용하여 평가한다. OC4Seq, LogBERT, CAT은 각각 저자들이 제공하는 오픈소스코드를 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogGPT의 경우 6개의 Layers와 6개의 Heads인 GPT모델을 사용하였고 임베딩과 hidden states의 차원은 60으로 설정했다.&lt;br /&gt;pre-training에서 Learning rate는 1e-4로 fine-tuning에서는 1e-6으로 설정했다.&lt;br /&gt;다양한 데이터셋에 적용하기 위해 Top-K의 K를 training LogKeys의 50%로 설정했다. 이는 test단계에서 관찰된 LogKey가 GPT의 prediction list 에 상위 50%에 포함되지 않으면 시퀀스가 이상치로 라벨링된다는 것을 의미한다.&lt;br /&gt;이를 통해 다양한 크기와 특성을 가진 데이터셋을 다룰 때 높은 수준의 flexibility를 유지할 수 있다.&lt;br /&gt;pre-training에서 batch size는 16으로, epoch은 100으로 학습하였고 과적합을 방지하고 효율적인 학습을 위해 early stop을 20으로 설정하였다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) Experimental Results&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/llKF8/btsMufw381W/goJDfWWYwSayy2kQedyhSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/llKF8/btsMufw381W/goJDfWWYwSayy2kQedyhSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/llKF8/btsMufw381W/goJDfWWYwSayy2kQedyhSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FllKF8%2FbtsMufw381W%2FgoJDfWWYwSayy2kQedyhSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1192&quot; height=&quot;299&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PCA, iForest, OCSVM은 HDFS, BGL 데이터셋에서 낮은 F-1 Score로 인해 성능이 떨어진다&lt;br /&gt;Thunderbird 데이터셋에서 PCA 성능은 높다.&lt;br /&gt;따라서 데이터 셋간 성능이 일치하지 않다는건 데이터 셋에 대한 PCA의 민감성을 의미한다.&lt;/li&gt;
&lt;li&gt;LogCluster는 HDFS, BGL 데이터 셋에서 기존 Machine Learning 모델보다 성능이 높지만 Thunderbird 데이터 셋에서는 PCA보다 성능이 더 뛰어난다.&amp;nbsp;&lt;br /&gt;따라서 데이터셋 특성에 따라 다양한 방법을 적용해보아야 한다.&lt;/li&gt;
&lt;li&gt;DL 방식인 DeepLog, LogAnomaly, OC4Seq, LogBert, CAT은 세가지 데이터셋에서 ML방식보다 성능이 뛰어나며, 이는 로그 시퀀스에서&amp;nbsp; 복잡한 패턴을 학습하기엔 딥러닝을 활용하는 것이 뛰어나다는 것을 의미한다.&lt;/li&gt;
&lt;li&gt;LogGPT는 세가지 데이터셋 모두에 일관되게 가장 높은 F-1 Score를 잘성하며, 모든 기준선에서 상당한 차이를 보였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reinforcement Learning(RL, 강화학습)이 LogGPT 성능에 미치는 영향을 조사하기 위해, RL이 있는경우와 없는 경우를 비교하여 연구를 수행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wfh3t/btsMt6fB8Cr/TSVKmQLkGA5hieBgbIx1o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wfh3t/btsMt6fB8Cr/TSVKmQLkGA5hieBgbIx1o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wfh3t/btsMt6fB8Cr/TSVKmQLkGA5hieBgbIx1o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWfh3t%2FbtsMt6fB8Cr%2FTSVKmQLkGA5hieBgbIx1o1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;202&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HDFS, Thunderbird 데이터셋에서 RL이 있는 LogGPT가 상당히 우수하다.&lt;br /&gt;이는 RL이 로그이상 탐지를 위한 LogGPT의 전반적 성능을 향상시켜준다는 것을 보여준다.&lt;/li&gt;
&lt;li&gt;HDFS 데이터셋에서는 RL이 GPT 모델을 fine-tuning 함으로써 precision을 희생하면서 recall이 큰 폭으로 향상되어 F-1 score가 큰 폭으로 향상되었다.&lt;/li&gt;
&lt;li&gt;LogGPT는 RL이 없는 경우에도 Baseline ML, DL보다 성능이 더 뛰어나다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogGPT는 관찰된 LogKey가 GPT가 예측한 Top-K list에 있는지 여부를 조사하여 이상치(비정상)를 탐지한다.&lt;br /&gt;K는 이상치를 파악하는데 중요한 매개변수이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 이상치를 탐지하기 위해 K를 tuning하여 성능차이를 분석한다. 기본적으로 K는 unique LogKeys의 50%로 설정한다.&lt;br /&gt;즉, 다음 LogKey가 GPT가 예측한 unique LogKeys의 tkddnl 50%에 속하면 시퀀스는 정상이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkl3uB/btsMvCScZWH/6hCMKNRtC77IyGcfechWJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkl3uB/btsMvCScZWH/6hCMKNRtC77IyGcfechWJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkl3uB/btsMvCScZWH/6hCMKNRtC77IyGcfechWJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbkl3uB%2FbtsMvCScZWH%2F6hCMKNRtC77IyGcfechWJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1174&quot; height=&quot;334&quot; data-origin-width=&quot;1174&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정상 LogKey 비율이 증가하면 HDFS와 BGL의 40%와 같이 임계값보다 크면 recall이 계속 감소한다.&lt;br /&gt;이는 비율이 클때 대부분의 Key가 정상으로 간주되기 때문에 발생한다. 이 경우 recall은 낮다.&lt;/li&gt;
&lt;li&gt;관찰된 LogKey가 특정위치에서 매우 낮은 확률로 예측되면 높은 확률로 이 LogKey가 비정상적이다.&lt;br /&gt;따라서 비율의 증가와 함께 precision의 증가를 관찰 할 수 있다.&lt;/li&gt;
&lt;li&gt;Thunderbird 데이터셋의 경우 Top-K 비율이 증가함에 따라 precision이 증가하는 반면 recall은 거의 일정하게 유지되며, Top-K비율이 높을수록 약간 감소한다. F1 score는 꾸준이 증가하여 특정 Top-K 비율에서 정점에 도달한다.&lt;br /&gt;아마 데이터셋 고유한 특성 때문일 수 있다.&lt;/li&gt;
&lt;li&gt;전반적으로, 낮은 Top-K 비율은 높은 recall을 가지지만 precision이 낮은 경향이 있다&lt;br /&gt;높은 Top-K 비율은 높은 precision을 가지지만 잠재적으로 낮은 recall을 초래할 수 있다.&lt;br /&gt;최적 Top-K비율은 각 데이터셋의 고유 특성을 반영하여 설정하여야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습데이터 크기가 로그이상탐지 모델 성능에 미치는 영향은 매우 크고 중요하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdH2YC/btsMtOsON3M/x3FJkpBYBgf5TRX3Fp1qqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdH2YC/btsMtOsON3M/x3FJkpBYBgf5TRX3Fp1qqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdH2YC/btsMtOsON3M/x3FJkpBYBgf5TRX3Fp1qqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdH2YC%2FbtsMtOsON3M%2Fx3FJkpBYBgf5TRX3Fp1qqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1140&quot; height=&quot;365&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;365&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LogGPT는 학습데이터셋 크기에 대해 일관된 성능을 보여준다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;OC4Seq는 학습데이터셋이 클수록 성능이 오른다. 큰 데이터셋에 이점이 있다.&lt;/li&gt;
&lt;li&gt;DeepLog, Anomaly는 학습데이터셋 크기에 대해 민감하여 성능에 변동이 있을 수 있다.&lt;/li&gt;
&lt;li&gt;모델 특성에 따라 학습데이터셋 크기를 선택해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;7. 결론&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강화학습 전략으로 더욱 강화된 GPT 모델 기반으로 한 새로운 로그이상탐지 접근 방식인 LogGPT를 소개했다.&lt;br /&gt;다양한 데이터셋에서 실험해본 결과 LogGPT의 효과가 입증되었으며, 기존 방식보다 상당한 개선이 이루어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문리뷰</category>
      <category>AnomalyDetection</category>
      <category>loganomaly</category>
      <category>loggpt</category>
      <category>로그이상탐지</category>
      <category>이상탐지</category>
      <category>자연어</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/53</guid>
      <comments>https://hello-heehee.tistory.com/53#entry53comment</comments>
      <pubDate>Fri, 28 Feb 2025 12:56:34 +0900</pubDate>
    </item>
    <item>
      <title>[Word2Vec] CBOW - Python 코드</title>
      <link>https://hello-heehee.tistory.com/49</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. Word2Vec - &lt;a style=&quot;background-color: #c0d1e7;&quot; href=&quot;https://hello-heehee.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CBOW&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CBOW에 대한 정의는 아래 게시글 참조&lt;/p&gt;
&lt;figure id=&quot;og_1739937714236&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NLP] Word Embedding&quot; data-og-description=&quot;자연어처리 공부중입니다. 잘못된 부분은 편히 댓글 부탁드립니다.1. 워드 임베딩이란?단어를 인공신경망 학습을 통해 벡터화하는 하는 것즉 텍스트를 숫자로 변환하는 방법2. 희소 표현(Sparse Re&quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/12&quot; data-og-url=&quot;https://hello-heehee.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/blo1b3/hyYfXxCx6I/0uvWFq8P5tif5977UllKkK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/hwF1d/hyYfQZx6Uh/TqJRpOrD7A8N4kTUKekmT0/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/bM24TY/hyYfYJ2eQM/YKWpicdZlgN4DvQg1PIWDk/img.png?width=547&amp;amp;height=365&amp;amp;face=0_0_547_365&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/blo1b3/hyYfXxCx6I/0uvWFq8P5tif5977UllKkK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/hwF1d/hyYfQZx6Uh/TqJRpOrD7A8N4kTUKekmT0/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/bM24TY/hyYfYJ2eQM/YKWpicdZlgN4DvQg1PIWDk/img.png?width=547&amp;amp;height=365&amp;amp;face=0_0_547_365');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NLP] Word Embedding&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자연어처리 공부중입니다. 잘못된 부분은 편히 댓글 부탁드립니다.1. 워드 임베딩이란?단어를 인공신경망 학습을 통해 벡터화하는 하는 것즉 텍스트를 숫자로 변환하는 방법2. 희소 표현(Sparse Re&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. CODE&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;1) &lt;a style=&quot;background-color: #ffc1c8;&quot; href=&quot;https://radimrehurek.com/gensim/apiref.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gensim&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;figure id=&quot;og_1739938247841&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Gensim: topic modelling for humans&quot; data-og-description=&quot;Efficient topic modelling in Python&quot; data-og-host=&quot;radimrehurek.com&quot; data-og-source-url=&quot;https://radimrehurek.com/gensim/apiref.html&quot; data-og-url=&quot;https://radimrehurek.com/gensim/apiref.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oqgW8/hyYjMulM78/noLTGfFkAuoRxkkUd0uxE0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://radimrehurek.com/gensim/apiref.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://radimrehurek.com/gensim/apiref.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oqgW8/hyYjMulM78/noLTGfFkAuoRxkkUd0uxE0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Gensim: topic modelling for humans&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Efficient topic modelling in Python&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;radimrehurek.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 많이 사용되고 상용화되어있는 Gensim의 Word2Vec이다.&lt;/p&gt;
&lt;pre id=&quot;code_1739938354058&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from gensim.models import Word2Vec
from gensim.models.word2vec import Text8Corpus

# 예제 문장 데이터
documents = [
    [&quot;이&quot;, &quot;문장은&quot;, &quot;예제입니다&quot;],
    [&quot;자연어&quot;, &quot;처리는&quot;, &quot;흥미롭습니다&quot;],
    [&quot;딥러닝&quot;, &quot;기반의&quot;, &quot;자연어&quot;, &quot;처리&quot;],
    [&quot;word2vec&quot;, &quot;모델을&quot;, &quot;학습합니다&quot;],
    [&quot;CBOW&quot;, &quot;방식을&quot;, &quot;사용합니다&quot;]
]

# Word2Vec 모델 학습 (CBOW 방식)
model = Word2Vec(sentences=documents, vector_size=100, window=5, min_count=1, sg=0)  # sg=0이면 CBOW, sg=1이면 Skip-gram

# 단어 벡터 출력
word = &quot;자연어&quot;
if word in model.wv:
    print(f&quot;'{word}'의 벡터 표현:&quot;)
    print(model.wv[word])

# 유사한 단어 찾기
similar_words = model.wv.most_similar(word, topn=5)
print(f&quot;'{word}'와 유사한 단어들:&quot;, similar_words)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wikidocs.net/50739&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikidocs&lt;/a&gt; 에서도 Gensim을 활용한 Word2Vec이 설명되어있으니 참고&lt;/p&gt;
&lt;figure id=&quot;og_1739938534410&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;09-03 영어/한국어 Word2Vec 실습&quot; data-og-description=&quot;gensim 패키지에서 제공하는 이미 구현된 Word2Vec을 사용하여 영어와 한국어 데이터를 학습합니다. ## 1. 영어 Word2Vec 만들기 파이썬의 gensim 패키지&amp;hellip;&quot; data-og-host=&quot;wikidocs.net&quot; data-og-source-url=&quot;https://wikidocs.net/50739&quot; data-og-url=&quot;https://wikidocs.net/50739&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HBlMl/hyYji7US7I/flw5qIh31XrxG6C3R8yjP0/img.png?width=98&amp;amp;height=130&amp;amp;face=0_0_98_130,https://scrap.kakaocdn.net/dn/PfCuG/hyYjvTIObJ/ff5072haqSbGcUijKrFbKk/img.png?width=365&amp;amp;height=267&amp;amp;face=0_0_365_267&quot;&gt;&lt;a href=&quot;https://wikidocs.net/50739&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://wikidocs.net/50739&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HBlMl/hyYji7US7I/flw5qIh31XrxG6C3R8yjP0/img.png?width=98&amp;amp;height=130&amp;amp;face=0_0_98_130,https://scrap.kakaocdn.net/dn/PfCuG/hyYjvTIObJ/ff5072haqSbGcUijKrFbKk/img.png?width=365&amp;amp;height=267&amp;amp;face=0_0_365_267');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;09-03 영어/한국어 Word2Vec 실습&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;gensim 패키지에서 제공하는 이미 구현된 Word2Vec을 사용하여 영어와 한국어 데이터를 학습합니다. ## 1. 영어 Word2Vec 만들기 파이썬의 gensim 패키지&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;wikidocs.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;Gensim은 다른 개발자들이 정리해놓은 것들도 많으니 생략하겠습니다. 추후에 공부후 따로 작성하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) &lt;a href=&quot;https://github.com/ksang/word2vec&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github/Ksang&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739938423332&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ksang/word2vec: A word2vec CBOW and Skip-gram implementation in PyTorch&quot; data-og-description=&quot;A word2vec CBOW and Skip-gram implementation in PyTorch - ksang/word2vec&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ksang/word2vec&quot; data-og-url=&quot;https://github.com/ksang/word2vec&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/brCAXK/hyYfHuIMIT/IQKRFlGONqUqiTK4mRkUoK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/d9ybS8/hyYf2r8ZgY/XJ69veXkumveXYAAZ3lM1K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ksang/word2vec&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ksang/word2vec&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/brCAXK/hyYfHuIMIT/IQKRFlGONqUqiTK4mRkUoK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/d9ybS8/hyYf2r8ZgY/XJ69veXkumveXYAAZ3lM1K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ksang/word2vec: A word2vec CBOW and Skip-gram implementation in PyTorch&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A word2vec CBOW and Skip-gram implementation in PyTorch - ksang/word2vec&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pytorch로 사용할 수 있는 방식도 위 개발자가 구현해놔서 정리해보았다.&lt;br /&gt;이 Word2Vec은 특정 라이브러리가 있는 건 아니고, Ksang이라는 개발자가 직접 코드를 개발하였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;model.py&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1739938850308&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import torch
import torch.nn.functional as F
import numpy as np

TABLE_SIZE = 1e8

def create_sample_table(word_count):
    &quot;&quot;&quot; Create negative sample table for vocabulary, words with
        higher frequency will have higher occurrences in table.
    &quot;&quot;&quot;
    table = []
    frequency = np.power(np.array(word_count), 0.75)
    sum_frequency = sum(frequency)
    ratio = frequency / sum_frequency
    count = np.round(ratio * TABLE_SIZE)
    for word_idx, c in enumerate(count):
        table += [word_idx] * int(c)
    return np.array(table)

#Word2Vec의 SkipGram
class SkipGramModel(torch.nn.Module):
    &quot;&quot;&quot; Center word as input, context words as target.
        Objective is to maximize the score of map from input to target.
    &quot;&quot;&quot;
    def __init__(self, device, vocabulary_size, embedding_dim, neg_num=0, word_count=[]):
        super(SkipGramModel, self).__init__()
        self.device = device
        self.neg_num = neg_num
        self.embeddings = torch.nn.Embedding(vocabulary_size, embedding_dim)
        initrange = 0.5 / embedding_dim
        self.embeddings.weight.data.uniform_(-initrange, initrange)
        if self.neg_num &amp;gt; 0:
            self.table = create_sample_table(word_count)

    def forward(self, centers, contexts):
        batch_size = len(centers)
        u_embeds = self.embeddings(centers).view(batch_size,1,-1)
        v_embeds = self.embeddings(contexts).view(batch_size,1,-1)
        score  = torch.bmm(u_embeds, v_embeds.transpose(1,2)).squeeze()
        loss = F.logsigmoid(score).squeeze()
        if self.neg_num &amp;gt; 0:
            neg_contexts = torch.LongTensor(np.random.choice(self.table, size=(batch_size, self.neg_num))).to(self.device)
            neg_v_embeds = self.embeddings(neg_contexts)
            neg_score = torch.bmm(u_embeds, neg_v_embeds.transpose(1,2)).squeeze()
            neg_score = torch.sum(neg_score, dim=1)
            neg_score = F.logsigmoid(-1*neg_score).squeeze()
            loss += neg_score
        return -1 * loss.sum()

    def get_embeddings(self):
        return self.embeddings.weight.data

#Word2Vec의 CBOW
class CBOWModel(torch.nn.Module):
    &quot;&quot;&quot; Context words as input, returns possiblity distribution
        prediction of center word (target).
    &quot;&quot;&quot;
    def __init__(self, device, vocabulary_size, embedding_dim):
        super(CBOWModel, self).__init__()
        self.device = device
        self.embeddings = torch.nn.Embedding(vocabulary_size, embedding_dim)
        initrange = 0.5 / embedding_dim
        self.embeddings.weight.data.uniform_(-initrange, initrange) #Initialize
        self.linear1 = torch.nn.Linear(embedding_dim, vocabulary_size)
        
	# CBOW 앞단
    def forward(self, contexts):
        # input
        embeds = self.embeddings(contexts)
        # projection
        add_embeds = torch.sum(embeds, dim=1)
        # output
        out = self.linear1(add_embeds)
        log_probs = F.log_softmax(out, dim=1)
        return log_probs

	#Embeddings의 Weight값
    def get_embeddings(self):
        return self.embeddings.weight.data
        
    #추가) Linears의 Weight값
    def get_linears(self):
    	return self.linear1.weight.data&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Word2Vec의 CBOW와 SkipGram의 기본적인 모델부분이다.&lt;br /&gt;CBOW기준 코드설명을 적어놨고, Weight값을 보기 위해 코드를 추가한 부분도 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;inference.py&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1739939072039&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pickle

def save_embeddings(filename, embeddings, linears, dictionary):
    &quot;&quot;&quot;Embeddings and reverse dictionary serialization and dump to a file.&quot;&quot;&quot;
    data = {
        'emb':  embeddings,
        'lin' : linears, #추가
        'dict': dictionary
    }
    file = open(filename, 'wb')
    print(&quot;Saving embeddings to file:&quot;, filename)
    pickle.dump(data, file)

class Word2Vec(object):
    &quot;&quot;&quot;Inference interface of Word2Vec embeddings
        Before inference the embdedding result of a word, data need to be initialized
        by calling method from_file or from_object.
    &quot;&quot;&quot;
    def __init__(self):
        self.embeddings = None
        self.linears = None #추가
        self.dictionary = None
        
    def from_file(self, filename):
        file = open(filename, 'rb')
        data = pickle.load(file)
        self.embeddings = data['emb']
        self.linears = data['line'] #추가
        self.dictionary = data['dict']

    def from_object(self, embeddings, linears, dictionary):
        self.embeddings = embeddings
        self.linears = linears #추가
        self.dictionary = dictionary

    def inference(self, word):
        assert self.embeddings is not None and self.dictionary is not None,\
            'Embeddings not initialized, use from_file or from_object to load data.'
        word_idx = self.dictionary.get(word)
        # Unknown word returns UNK's word_idx
        if word_idx is None:
            word_idx = 0
        return self.embeddings[word_idx]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model을 Load하고 Inference하는 코드부분으로 model.py에서 추가한 weight function을 inference에서 사용할 수 있도록 일부 코드 수정이 되어있다.&lt;br /&gt;이 부분은 코드 설명이 쉬워서 따로 추가한 건 없고 기존 모델과는 달리 pickle로 모델을 저장하고 불러온다는게 조금 다른 특색이다. pickle이 압축하여 전송/저장 하고 불러와서 해당 압축을 푸는 방식인데, 아마 용량측면에서 사용한 것 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;word2vec.py&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1739939250422&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import argparse
import zipfile
import re
import collections
import numpy as np
from six.moves import xrange
import random
import torch
import timeit
from torch.autograd import Variable
from models import SkipGramModel
from models import CBOWModel
from inference import save_embeddings

model_list = ['CBOW', 'skipgram']

cmd_parser = argparse.ArgumentParser(description=None)
# Data arguments
cmd_parser.add_argument('-d', '--data', default='data/text8.zip',
                        help='Data file for word2vec training.')
cmd_parser.add_argument('-o', '--output', default='embeddings.bin',
                        help='Output embeddings filename.')
cmd_parser.add_argument('-s', '--size', default=50000, type=int,
                        help='Vocabulary size.')
# Model training arguments
cmd_parser.add_argument('-m', '--mode', default='skipgram', choices=model_list,
                        help='Training model.')
cmd_parser.add_argument('-bs', '--batch_size', default=128, type=int,
                        help='Training batch size.')
cmd_parser.add_argument('-ns', '--num_skips', default=2, type=int,
                        help='How many times to reuse an input to generate a label.')
cmd_parser.add_argument('-sw', '--skip_window', default=1, type=int,
                        help='How many words to consider left and right.')
cmd_parser.add_argument('-ed', '--embedding_dim', default=128, type=int,
                        help='Dimension of the embedding vector.')
cmd_parser.add_argument('-lr', '--learning_rate', default=0.001, type=float,
                        help='Learning rate')
cmd_parser.add_argument('-i', '--num_steps', default=10000, type=int,
                        help='Number of steps to run.')
cmd_parser.add_argument('-ne', '--negative_example', default=5, type=int,
                        help='Number of negative examples.')
cmd_parser.add_argument('-c', '--clip', default=1.0, type=float,
                        help='Clip gradient norm value.')

# Device
cmd_parser.add_argument('-dc', '--disable_cuda', default=False, action='store_true',
                        help='Explicitly disable cuda and GPU.')

def read_data(filename):
    &quot;&quot;&quot;Extract the first file enclosed in a zip file as a list of words.&quot;&quot;&quot;
    if filename.endswith('.zip'):
        with zipfile.ZipFile(filename) as f:
            text = f.read(f.namelist()[0]).decode('ascii')
    else:
        with open(filename, &quot;r&quot;) as f:
            text = f.read()
    return [word.lower() for word in re.compile('\w+').findall(text)]

def build_dataset(words, n_words):
    &quot;&quot;&quot;Process raw inputs into a dataset.
        Returns:
            data        list of codes (integers from 0 to vocabulary_size-1).
                        This is the original text but words are replaced by their codes
            count       list of words(strings) to count of occurrences
            dictionary  map of words(strings) to their codes(integers)
            reverse_dictionary  maps codes(integers) to words(strings)
    &quot;&quot;&quot;
    count = [['UNK', -1]]
    count.extend(collections.Counter(words).most_common(n_words - 1))
    dictionary = dict()
    for word, _ in count:
        dictionary[word] = len(dictionary)
    data = list()
    unk_count = 0
    for word in words:
        index = dictionary.get(word, 0)
        if index == 0:  # dictionary['UNK']
            unk_count += 1
        data.append(index)
    count[0][1] = unk_count
    reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
    return data, count, dictionary, reversed_dictionary

def generate_batch(device, data, data_index, batch_size, num_skips, skip_window):
    &quot;&quot;&quot;Generates a batch of training data
        returns:
            centers:      a list of center word indexes for this batch.
            contexts:     a list of contexts indexes for this batch.
            data_index: current data index for next batch.
    &quot;&quot;&quot;
    assert batch_size % num_skips == 0
    assert num_skips &amp;lt;= 2 * skip_window
    centers = np.ndarray(shape=(batch_size), dtype=np.int32)
    contexts = np.ndarray(shape=(batch_size, 1), dtype=np.int32)
    span = 2 * skip_window + 1  # [ skip_window target skip_window ]
    buffer = collections.deque(maxlen=span)
    if data_index + span &amp;gt; len(data):
        data_index = 0
    buffer.extend(data[data_index:data_index + span])
    data_index += span
    for i in range(batch_size // num_skips):
        context_words = [w for w in range(span) if w != skip_window]
        words_to_use = random.sample(context_words, num_skips)
        for j, context_word in enumerate(words_to_use):
            centers[i * num_skips + j] = buffer[skip_window]
            contexts[i * num_skips + j, 0] = buffer[context_word]
        if data_index == len(data):
            for word in data[:span]:
                buffer.append(word)
            data_index = span
        else:
            buffer.append(data[data_index])
            data_index += 1
    # Backtrack a little bit to avoid skipping words in the end of a batch
    data_index = (data_index + len(data) - span) % len(data)
    centers = torch.LongTensor(centers).to(device)
    contexts = torch.LongTensor(contexts).to(device)
    return centers, contexts, data_index

def get_deivice(disable_cuda):
    &quot;&quot;&quot;Get CPU/GPU device
    &quot;&quot;&quot;
    if not disable_cuda and torch.cuda.is_available():
        device = torch.device('cuda')
    else:
        device = torch.device('cpu')
    return device

def train(device, data, word_count, mode, vocabulary_size, embedding_dim, batch_size,
          num_skips, skip_window, num_steps, learning_rate, neg_num, clip):
    &quot;&quot;&quot;Training and backpropagation process, returns final embedding as result&quot;&quot;&quot;
    if mode == 'CBOW':
        model = CBOWModel(device, vocabulary_size, embedding_dim)
    elif mode == 'skipgram':
        model = SkipGramModel(device, vocabulary_size, embedding_dim, neg_num, word_count)
    else:
        raise ValueError(&quot;Model \&quot;%s\&quot; not supported&quot; % model)
    model.to(device)
    print(&quot;Start training on device:&quot;, device)
    optimizer = torch.optim.Adam(
        model.parameters(), lr=learning_rate)
    loss_function = torch.nn.NLLLoss()
    data_index = 0
    loss_val = 0
    for i in xrange(num_steps):
        # prepare feed data and forward pass
        centers, contexts, data_index = generate_batch(device, data, data_index,
                                                       batch_size, num_skips, skip_window)
        if mode == 'CBOW':
            y_pred = model(contexts)
            loss = loss_function(y_pred, centers)
        elif mode == 'skipgram':
            loss = model(centers, contexts)
        else:
            raise ValueError(&quot;Model \&quot;%s\&quot; not supported&quot; % model)
        # Zero gradients, perform a backward pass, and update the weights.
        optimizer.zero_grad()
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), clip)
        optimizer.step()
        # Print loss value at certain step
        loss_val += loss.item()
        if i &amp;gt; 0 and i % (num_steps/100) == 0:
            print('  Average loss at step', i, ':', loss_val/(num_steps/100))
            loss_val = 0

    return model.get_embeddings()


def tsne_plot(embeddings, num, reverse_dictionary, filename):
    &quot;&quot;&quot;Plot tSNE result of embeddings for a subset of words&quot;&quot;&quot;
    try:
        from sklearn.manifold import TSNE
        import matplotlib.pyplot as plt
    except ImportError as ex:
        print('Please install sklearn, matplotlib, and scipy to plot embeddings.')
        print(ex)
        return
    tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000, method='exact')
    low_dim_embs = tsne.fit_transform(final_embeddings[:num, :])
    low_dim_labels = [reverse_dictionary[i] for i in xrange(num)]
    assert low_dim_embs.shape[0] &amp;gt;= len(low_dim_labels), 'More labels than embeddings'
    plt.figure(figsize=(18, 18))  # in inches
    for i, label in enumerate(low_dim_labels):
        x, y = low_dim_embs[i, :]
        plt.scatter(x, y)
        plt.annotate(label,
                     xy=(x, y),
                     xytext=(5, 2),
                     textcoords='offset points',
                     ha='right',
                     va='bottom')
    print(&quot;Saving plot to:&quot;, filename)
    plt.savefig(filename)

if __name__ == '__main__':
    args = cmd_parser.parse_args()
    dev = get_deivice(args.disable_cuda)
    # Data preprocessing
    vocabulary = read_data(args.data)
    print('Data size', len(vocabulary))
    data, count, dictionary, reverse_dictionary = build_dataset(vocabulary,
                                                                args.size)
    vocabulary_size = min(args.size, len(count))
    print('Vocabulary size', vocabulary_size)
    word_count = [ c[1] for c in count]
    # Model training
    start_time = timeit.default_timer()
    final_embeddings = train(device=dev,
                             data=data,
                             word_count=word_count,
                             mode=args.mode,
                             vocabulary_size=vocabulary_size,
                             embedding_dim=args.embedding_dim,
                             batch_size=args.batch_size,
                             num_skips=args.num_skips,
                             skip_window=args.skip_window,
                             num_steps=args.num_steps,
                             learning_rate=args.learning_rate,
                             clip=args.clip,
                             neg_num=args.negative_example)
    print('Training time:', timeit.default_timer() - start_time, 'Seconds')
    # Save result and plotting
    save_embeddings(args.output, final_embeddings, dictionary)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;argument부분에서 parameter들을 설정할 수 있고, train function을 보면 train단에 backward(backpropagation)단이 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;plotting&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1739939274689&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;save_plot_name ='tsne.png' #Plotting output filename
plot_num=100 #Plotting data number

def tsne_plot(embeddings, num, reverse_dictionary, filename):
    &quot;&quot;&quot;Plot tSNE result of embeddings for a subset of words&quot;&quot;&quot;
    try:
        from sklearn.manifold import TSNE
        import matplotlib.pyplot as plt
    except ImportError as ex:
        print('Please install sklearn, matplotlib, and scipy to plot embeddings.')
        print(ex)
        return
    tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000, method='exact')
    low_dim_embs = tsne.fit_transform(final_embeddings[:num, :])
    low_dim_labels = [reverse_dictionary[i] for i in xrange(num)]
    assert low_dim_embs.shape[0] &amp;gt;= len(low_dim_labels), 'More labels than embeddings'
    plt.figure(figsize=(18, 18))  # in inches
    for i, label in enumerate(low_dim_labels):
        x, y = low_dim_embs[i, :]
        plt.scatter(x, y)
        plt.annotate(label,
                     xy=(x, y),
                     xytext=(5, 2),
                     textcoords='offset points',
                     ha='right',
                     va='bottom')
    print(&quot;Saving plot to:&quot;, filename)
    plt.savefig(filename)

if __name__==&quot;__main__&quot;:
	m=Word2Vec()
    model = m.from_file(&quot;embeddings.bin&quot;) #load model
    
    norm = torch.sqrt(torch.cumsum(torch.mul(model, model), 1))
    nomalized_embeddings = (model/norm).cpu().numpy()
    tsne_plot(embeddings=nomalized_embeddings,
              num=min(vocabulary_size, plot_num),
              reverse_dictionary=reverse_dictionary,
              filename=save_plot_name)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수치로는 어떤 단어가 거리가 먼지(score가 낮은지) 알 수 없기 때문에 plot chart를 만들어주는 function이다.&lt;/p&gt;</description>
      <category>DeepLearning/NLP</category>
      <category>cbow</category>
      <category>python</category>
      <category>word2vec</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/49</guid>
      <comments>https://hello-heehee.tistory.com/49#entry49comment</comments>
      <pubDate>Tue, 25 Feb 2025 13:03:01 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] DeepLearning-based System Log Analysis for Anomaly Detection</title>
      <link>https://hello-heehee.tistory.com/52</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2107.05908&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Experience Report: Deep Learning-based System Log Analysis for Anomaly Detection&lt;/a&gt; - 2022.01.11&lt;/p&gt;
&lt;figure id=&quot;og_1740310323268&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Experience Report: Deep Learning-based System Log Analysis for Anomaly Detection&quot; data-og-description=&quot;Logs have been an imperative resource to ensure the reliability and continuity of many software systems, especially large-scale distributed systems. They faithfully record runtime information to facilitate system troubleshooting and behavior understanding.&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2107.05908&quot; data-og-url=&quot;https://arxiv.org/abs/2107.05908v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bZk16K/hyYjKqleqg/r6ic0vkI1ZUD4J7nmAuolk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/vavHy/hyYjunA9kL/KCozb5DuNVwItyoIcwcrK0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2107.05908&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2107.05908&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bZk16K/hyYjKqleqg/r6ic0vkI1ZUD4J7nmAuolk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/vavHy/hyYjunA9kL/KCozb5DuNVwItyoIcwcrK0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Experience Report: Deep Learning-based System Log Analysis for Anomaly Detection&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Logs have been an imperative resource to ensure the reliability and continuity of many software systems, especially large-scale distributed systems. They faithfully record runtime information to facilitate system troubleshooting and behavior understanding.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. 목적&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 로그데이터는 방대하고 복잡한데 로그데이터 분석관련 논문은 종종 있지만 딥러닝 모델 비교에 관련된 연구는 없어서 &quot;비교&quot; 목적으로 시작하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 2가지의 Dataset과 6개의 딥러닝 모델비교를 통해서 이를 기반으로 미래에는 더 많은 발전이 이루어지길 바란다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. 본론 - 로그데이터 이상치 탐지 방법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b20ckB/btsMtFBEpfw/uJn6U0uqxmd0pAdJZl76fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b20ckB/btsMtFBEpfw/uJn6U0uqxmd0pAdJZl76fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b20ckB/btsMtFBEpfw/uJn6U0uqxmd0pAdJZl76fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb20ckB%2FbtsMtFBEpfw%2FuJn6U0uqxmd0pAdJZl76fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;474&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Log Collection&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Log Datas는 Label이 없는 경우가 많아서 Unsupervised Learning을 선호한다.&lt;br /&gt;이 논문에서는 HDFS, BGL을 사용하였다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Log Parsing&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 로그 데이터들은 일정 구조가 있기 때문에 Log Parsing을 하여&amp;nbsp; &lt;a href=&quot;https://hello-heehee.tistory.com/47&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Template&lt;/a&gt;을 만든다.&lt;/p&gt;
&lt;figure id=&quot;og_1740311402324&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NLP] 텍스트 데이터 전처리 - Log Template&quot; data-og-description=&quot;자연어인 로그 데이터를 딥러닝할 때 전처리는 어떻게 할까?보통 로그 데이터는 패턴이 존재한다. 이 패턴에 대해서 알고 있다면 공통 패턴이 되는 템플릿(Template)을 만들어 처리하면 되지만 만&quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/47&quot; data-og-url=&quot;https://hello-heehee.tistory.com/47&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/boLw3E/hyYjxExuOq/jbbVoMWzjScCckVYSGNwiK/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/c3lRcA/hyYjxExuS0/4lWJtwTWqEOkPujIevitn1/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/ba7sXv/hyYjqZOW2F/kYDZznLQuHTHiOeTntqkI1/img.png?width=941&amp;amp;height=451&amp;amp;face=0_0_941_451&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/47&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/47&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/boLw3E/hyYjxExuOq/jbbVoMWzjScCckVYSGNwiK/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/c3lRcA/hyYjxExuS0/4lWJtwTWqEOkPujIevitn1/img.png?width=800&amp;amp;height=383&amp;amp;face=0_0_800_383,https://scrap.kakaocdn.net/dn/ba7sXv/hyYjqZOW2F/kYDZznLQuHTHiOeTntqkI1/img.png?width=941&amp;amp;height=451&amp;amp;face=0_0_941_451');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NLP] 텍스트 데이터 전처리 - Log Template&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자연어인 로그 데이터를 딥러닝할 때 전처리는 어떻게 할까?보통 로그 데이터는 패턴이 존재한다. 이 패턴에 대해서 알고 있다면 공통 패턴이 되는 템플릿(Template)을 만들어 처리하면 되지만 만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Template을 만들어주는 방식은 여러가지가 있으나 대체적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://hello-heehee.tistory.com/48&quot;&gt;Drain&lt;/a&gt;이 손 쉽게 Template을 만들어준다.&lt;/p&gt;
&lt;figure id=&quot;og_1740311414195&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NLP] Drain3 - Python&quot; data-og-description=&quot;1. Drain3자연어로 이루어진 데이터들의 Template을 자동적으로 만들어주는 라이브러리# 라이브러리 설치pip install drain32. CODEGithub&amp;nbsp;GitHub - logpai/Drain3: A robust streaming log template miner based on the Drain algorith&quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/48&quot; data-og-url=&quot;https://hello-heehee.tistory.com/48&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bK2DXR/hyYjzCmw9M/E3pKFPjx87KjMct7K3uHOk/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450,https://scrap.kakaocdn.net/dn/bC6Yv0/hyYju2emhO/fOkheyWdngoD3Qc3HWGB90/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450,https://scrap.kakaocdn.net/dn/mY0dj/hyYjqrYcJN/6mvm3hgO2riwrkuOKjU7k0/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/48&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/48&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bK2DXR/hyYjzCmw9M/E3pKFPjx87KjMct7K3uHOk/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450,https://scrap.kakaocdn.net/dn/bC6Yv0/hyYju2emhO/fOkheyWdngoD3Qc3HWGB90/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450,https://scrap.kakaocdn.net/dn/mY0dj/hyYjqrYcJN/6mvm3hgO2riwrkuOKjU7k0/img.png?width=751&amp;amp;height=450&amp;amp;face=0_0_751_450');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NLP] Drain3 - Python&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1. Drain3자연어로 이루어진 데이터들의 Template을 자동적으로 만들어주는 라이브러리# 라이브러리 설치pip install drain32. CODEGithub&amp;nbsp;GitHub - logpai/Drain3: A robust streaming log template miner based on the Drain algorith&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) Log Partition and Feature Extraction&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Log Partition은 Log 별 Template id를 부여했을 때 Window Size에 따라 데이터를 쪼개는 방식이라고 생각하면 쉽다&lt;br /&gt;보통 Window Size는 홀수 갯수로 사용하는데, 여기 논문에서 window size는 4이다.&lt;br /&gt;Window Size와 관련하여 더 자세한 내용은 &lt;a href=&quot;https://hello-heehee.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Word2Vec의 CBOW쪽 예문&lt;/a&gt;을 보면 더 이해가 쉬울 것이다.&lt;/p&gt;
&lt;figure id=&quot;og_1740311910679&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NLP] Word Embedding&quot; data-og-description=&quot;자연어처리 공부중입니다. 잘못된 부분은 편히 댓글 부탁드립니다.1. 워드 임베딩이란?단어를 인공신경망 학습을 통해 벡터화하는 하는 것즉 텍스트를 숫자로 변환하는 방법2. 희소 표현(Sparse Re&quot; data-og-host=&quot;hello-heehee.tistory.com&quot; data-og-source-url=&quot;https://hello-heehee.tistory.com/12&quot; data-og-url=&quot;https://hello-heehee.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/D8X1a/hyYjvUl90o/k5g7P1209fmFKVViyIGdCK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/blEXss/hyYjF3EmTS/khkHKoque8fdXxzZ5JI8zK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/cQzEiW/hyYjiU07Ie/OsC6RWVNG9wRt1xqHXQvpk/img.png?width=547&amp;amp;height=365&amp;amp;face=0_0_547_365&quot;&gt;&lt;a href=&quot;https://hello-heehee.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hello-heehee.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/D8X1a/hyYjvUl90o/k5g7P1209fmFKVViyIGdCK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/blEXss/hyYjF3EmTS/khkHKoque8fdXxzZ5JI8zK/img.png?width=495&amp;amp;height=234&amp;amp;face=0_0_495_234,https://scrap.kakaocdn.net/dn/cQzEiW/hyYjiU07Ie/OsC6RWVNG9wRt1xqHXQvpk/img.png?width=547&amp;amp;height=365&amp;amp;face=0_0_547_365');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NLP] Word Embedding&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자연어처리 공부중입니다. 잘못된 부분은 편히 댓글 부탁드립니다.1. 워드 임베딩이란?단어를 인공신경망 학습을 통해 벡터화하는 하는 것즉 텍스트를 숫자로 변환하는 방법2. 희소 표현(Sparse Re&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hello-heehee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Fixed Partitioning&lt;/b&gt;: 한 번 사용한 log는 묶어주지 않는 방식 (No overlap)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sliding Partitioning&lt;/b&gt;: 한 칸씩 옮겨가면서 window size만큼 묶어주는 방식&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Identifier-based Partitioning&lt;/b&gt;: 다른 Template ID가 나오기 전 동일한 Template ID로 묶어주는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Feature Extraction은 Log Partition 후 Machine Learning이나 Deep Learning을 이용하여 특징을 추출한다.&lt;br /&gt;로그데이터들은 복잡하기 때문에 Word2Vec, FastText, GloVe를 사용하여 Embedding 후 단순한 Vector로 만들어 사용한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) Anomaly Detection&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Traditional Machine Learning 이나 Deep Learning method를 사용하여 정상 로그 패턴을 학습하여 로그가 Normal인지 Abnomal인지 판별한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 특성에 따라 Loss Function을 사용해야하는데, 논문에서는 3가지의 Loss Function에 대해 설명한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt; Forecasting Loss&lt;/b&gt;: 정상로그만을 학습하여 미래의 로그에 대해 예측하는 것을 의미한다.&lt;br /&gt;ex) t시점에 t+1 혹은 t+N시점에 대해 로그가 normal인지 abnormal인지 예측한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reconstrunction Loss&lt;/b&gt;: Autoencoder에서 사용한다. 복원된 로그(예측결과)가 정상 로그와 차이가 크다면 Abnormal, 차이가 적다면 Normal을 뜻한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Supervised Loss&lt;/b&gt;: Supervised Learning에서 주로 사용하는 Cross Entropy나 MSE(Mean Squared Error)등을 뜻한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;3. 본론 - 6가지 모델 비교&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6가지 모델은 Reference 논문에 나온 모델들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Unsupervised Learning&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DeepLog&lt;/b&gt;: Forecasting 기반으로 Log Anomaly Detection과 관련한 최초 연구이다. 로그데이터들을 순차적으로 학습하며 Template ID만 학습한 방식(?)이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LogAnomaly&lt;/b&gt;: LSTM모델을 사용한 Forecasting기반으로 DeepLog보다 성능이 더 향상 가능한지 평가하였다. &lt;br /&gt;Template2Vec을 이용한 단어의 동의어와 반의어를 고려한 의미기반 학습모델이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Logsy&lt;/b&gt;: Transformer Model로 정상로그와 비정상로그 데이터를 구분하기 위한 분류기반 학습방법이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Autoencoder&lt;/b&gt;: Isolation Forest를 결합한 Autoencoder로 Autoencoder는 특징을 추출하고 Isolation Forest는 추출한 특징으로 이상탐지를 한다. 정상로그만 학습한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Supervised Learning&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LogRobust&lt;/b&gt;: 실제 로그데이터 이상탐지시 예상과 달리 성능이 매우 떨어지는 것을 발견하여 이를 해결하기 위해 제안하였다.&lt;br /&gt;성능이 떨어진 이유는 Noise나 데이터의 불안정성을 배제했기 때문으로 Bi-LSTM과 Attention을 결합한 모델이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CNN&lt;/b&gt;: CNN모델을 사용하기 때문에 input data가 2차원이어야 한다. 여기서는 2차원 Feature Input을 위해 Logkey2Vec이라는 Embedding 기법을 제안하였다. 로그 시퀀스를 이미지 데이터처럼 처리하여 CNN기반 분류를 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 모델들을 통합한 ToolKit이 없어서 논문 저자들은 OpenSource &lt;a href=&quot;https://github.com/logpai/deep-loglizer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ToolKit&lt;/a&gt;을 제공하고 있다.&lt;br /&gt;해당 ToolKit은 Autoencoder, CNN, LSTM, Transformer를 제공한다.&lt;/p&gt;
&lt;figure id=&quot;og_1740313745532&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - logpai/deep-loglizer: A deep learning toolkit for log-based anomaly detection&quot; data-og-description=&quot;A deep learning toolkit for log-based anomaly detection - logpai/deep-loglizer&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/logpai/deep-loglizer&quot; data-og-url=&quot;https://github.com/logpai/deep-loglizer&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bndYIA/hyYjLCL1VS/g2eSBK3Aa0l2mJJPBPUCKK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bBeq1b/hyYjITBXNJ/jpLetuGWhZVQCvZi8PSle0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/logpai/deep-loglizer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/logpai/deep-loglizer&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bndYIA/hyYjLCL1VS/g2eSBK3Aa0l2mJJPBPUCKK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bBeq1b/hyYjITBXNJ/jpLetuGWhZVQCvZi8PSle0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - logpai/deep-loglizer: A deep learning toolkit for log-based anomaly detection&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A deep learning toolkit for log-based anomaly detection - logpai/deep-loglizer&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;4. 본론 - 결과 정리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논문은 3가지 관점으로 모델 성능을 분석하였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Accuracy&lt;/b&gt;: 정상로그와 비정상 로그 구별능력이다. Accuracy가 높다면 모델은 정상과 비정상 로그를 잘 분류한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Robustness&lt;/b&gt;: 학습데이터에 없던 다른 로그가 생겼을 때 이상탐지 방법능력이다. Robustness가 높을수록 모델이 견고하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Efficiency&lt;/b&gt;: 모델의 속도를 의미한다. Efficiency가 높다면 모델 속도가 빨라 효율성이 높다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;267&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XO4WG/btsMtQpChAa/FkuxrgL6SVNBDiogn8Ombk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XO4WG/btsMtQpChAa/FkuxrgL6SVNBDiogn8Ombk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XO4WG/btsMtQpChAa/FkuxrgL6SVNBDiogn8Ombk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXO4WG%2FbtsMtQpChAa%2FFkuxrgL6SVNBDiogn8Ombk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1092&quot; height=&quot;267&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;267&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 셋에 따라 6가지 모델에 대해 성능평가를 진행하였다.&lt;br /&gt;데이터 셋에 따라 모델 성능이 다르므로 여러가지 모델을 적용해본 후 선택하는 것이 용이하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;* Log Semantics (로그 의미론)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 Log Anomaly Detection은 단순한 Template Matching을 이용한 이상탐지이다. 맥락을 고려하지 않기 때문에 로그 의미 해석능력이 떨어졌고, 새로운 로그 패턴에 취약했다. 이를 위해 Log Semantics가 출현하였다.&lt;br /&gt;Log Semantics는 새로운 로그패턴 처리가 가능해졌고, 유사한 의미를 가진 로그를 효과적으로 그룹화가 가능하여 더욱 정밀한 이상탐지가 가능하게 되었다.&lt;br /&gt;&lt;span style=&quot;background-color: #99cefa; color: #000000;&quot;&gt;ex) 디스크 공간 부족 ≒ 하드디스크 가득 참 &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/edym1o/btsMtISH5Pb/slbFdn56l8c4tQYKDQKJS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/edym1o/btsMtISH5Pb/slbFdn56l8c4tQYKDQKJS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/edym1o/btsMtISH5Pb/slbFdn56l8c4tQYKDQKJS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fedym1o%2FbtsMtISH5Pb%2FslbFdn56l8c4tQYKDQKJS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;402&quot; height=&quot;217&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Traditional Machine Learning과 Table2의 Deep Learning에 대한 성능 비교이다.&lt;br /&gt;대체적으로 Deep Learning이 Traditional Machine Learning보다 성능이 높지만 Machine Learning이 높은 경우도 있다고 한다.&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 부분은 참고용으로만 보고 DeepLearning 기법을 사용하는게 더 낫다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;729&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc6DLu/btsMsn9LJ9O/m1Ng26BIohXzI3lYjMTKD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc6DLu/btsMsn9LJ9O/m1Ng26BIohXzI3lYjMTKD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc6DLu/btsMsn9LJ9O/m1Ng26BIohXzI3lYjMTKD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc6DLu%2FbtsMsn9LJ9O%2Fm1Ng26BIohXzI3lYjMTKD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;569&quot; height=&quot;729&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Supervised Learning이 Unsupervised Learning보다 더 성능이 우수하여 Label이 있다면 Supervised Learning을 권장한다.&lt;br /&gt;Log Semantics 유무와 관련 없이 Supervised Learning이 Robustness도 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Forecasting-based method는 학습데이터에 이상치가 있다면 성능이 급격하게 저하되고 Reconsturction-based method가 더 Robustness가 높다.&amp;nbsp;&lt;br /&gt;&amp;gt; Fig2. LSTM, Transformer보다 Autoencoder가 Injection Ratio가 높을수록 Robustness가 더 적게 떨어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepLearning이 Machine Learning보다 학습 소요시간이 더 오래 걸렸다. 일부 Machine Learning이 Efficiency가 더 뛰어난 경우도 있다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;하지만 Deep Learning을 사용하도록 하자&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;5. 결론&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 성능 85% &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;화웨이에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 사용중이고 연구 초기이기 때문에 이 논문을 base로 더 발전이 이루어 지리라 생각된다.&lt;br /&gt;&amp;gt; Industrial Practices 와 Real-World Challenges 내용은 생략하니, 궁금하다면 논문을 읽어보길 추천한다.&lt;br /&gt;로그데이터 이상치 탐지를 처음 시작하는 사람들에게 논문을 읽기를 추천한다.&lt;/p&gt;</description>
      <category>논문리뷰</category>
      <category>Anomaly</category>
      <category>detection</category>
      <category>loganomalydetection</category>
      <category>logdata</category>
      <category>Papers</category>
      <category>논문</category>
      <category>논문리뷰</category>
      <category>로그데이터</category>
      <category>이상치탐지</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/52</guid>
      <comments>https://hello-heehee.tistory.com/52#entry52comment</comments>
      <pubDate>Sun, 23 Feb 2025 21:55:22 +0900</pubDate>
    </item>
    <item>
      <title>[ADP] 분산데이터 저장기술 - 데이터베이스 클러스터</title>
      <link>https://hello-heehee.tistory.com/50</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;분산데이터 저장기술&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분산파일시스템&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;클러스터&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;데이터베이스&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. 데이터베이스 클러스터&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 데이터베이스를 여러개의 서버상에 구축하는 것&lt;/li&gt;
&lt;li&gt;데이터를 통합할 때,&lt;span style=&quot;background-color: #f6e199;&quot;&gt; 성능과 가용성의 향상을 위해 데이터베이스 차원의 파티셔닝 또틑 클러스터링을 이용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터베이스 파티셔닝: 데이터베이스를 여러부분으로 분할하는 것을 의미&lt;/li&gt;
&lt;li&gt;파티션: 분할된 각 요소. 각 파티션은 여러 노드로 분할 배치되어 여러 사용자가 각 노드에서 트랜잭션을 수행할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 효과&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;병렬처리&lt;/span&gt;&lt;/b&gt;: 파티션 사이의 병렬처리를 통한 빠른 데이터 검색 및 처리 성능을 얻을 수 있음&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;&lt;/span&gt;: 특정 파티션에서 장애가 발생하더라도 서비스가 중단되지 않음&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;성능향상&lt;/b&gt;&lt;/span&gt;: 성능의 선형적인 증가 효과를 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 데이터베이스 클러스터 구분&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구성형태에 따라 단일서버 내의 파티셔닝/ 다중서버 사이의 파티셔닝으로 구분&lt;/li&gt;
&lt;li&gt;리소스 공유관점에서 공유디스크(shared Disk)/무공유(shared Nothing)로 구분&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;nbsp; i) 무공유 디스크&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무공유 클러스터에서 각 데이터베이스 인스턴스는 자신이 관리하는 데이터 파일을 자신의 로컬 디스크에 저장하며, 이 파일들은 노드간 공유하지 않음&lt;/li&gt;
&lt;li&gt;각 인스턴스나 노드는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;완전히 분리된 데이터의 서브집합에 대한 소유권을 가지고 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;각 데이터는 소유권을 갖고 있는 인스턴스가 처리함&lt;/li&gt;
&lt;li&gt;한 노드가 데이터 처리 요청을 받으면 해당 노드는 처리할 데이터를 갖고 있는 노드에 신호를 보내 데이터 처리를 요청&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Oracle RAC(Real Application Cluster)를 제외한 대부분의 데이터베이스 클러스터가 무공유 방식을 채택함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;노드 확장에 제한이 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;각 노드에 장애가 발생할 경우를 대비해&lt;span style=&quot;background-color: #f6e199;&quot;&gt; 별도의 Fault-Tolerance를 구성해야 함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;* Fault-Tolerance: 시스템 고장이 발생하더라도 모든 기능 혹은 기능의 일부를 기존과 같이 유지하는 기술&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;&amp;nbsp; ii) 공유 디스크&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공유디스크 클러스터에서 데이터 파일은 논리적으로 모든 데이터베이스 인스턴스 노드들은 데이터 파일을 논리적으로 공유&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;각 인스턴스는 모든 데이터에 접근할 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;데이터를 공유하려면&lt;span style=&quot;background-color: #f6e199;&quot;&gt; SAN(Storage Area Network)와 같은 네트워크가 반드시 있어야 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;모든 노드가 데이터를 수정&lt;/span&gt;할 수 있기 때문에 노드간 동기화 작업수행을 위한 별도의 커뮤니케이션 채널이 필요&lt;/li&gt;
&lt;li&gt;높은 수준의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Fault-Tolerance를 제공&lt;/span&gt;하므로 클러스터를 구성하는 노드 중 하나의 노드만 살아 있어도 서비스가 가능&lt;/li&gt;
&lt;li&gt;클러스터가 커지면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;디스크 영역에서 병목현상 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. 데이터 베이스 클러스터 종류&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) Oracle RAC &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;(Real Application Cluster)&lt;/span&gt; 데이터베이스 서버&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공유 클러스터로 클러스터의 모든 노드에서 실행되며 데이터는 공유 스토리지에 저장&lt;/li&gt;
&lt;li&gt;클러스터의 모든 노드는 데이터베이스의 모든 테이블에 동등하게 엑세스&lt;/li&gt;
&lt;li&gt;특정 노드가 데이터를 '소유'하는 개념이 없음&lt;/li&gt;
&lt;li&gt;데이터를 파티셔닝할 필요가 없지만 성능향상을 위해 파티셔닝 할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;가용성&lt;/b&gt;: 높은 수준의 fault tolerance를 제공하므로 클러스터를 구성하는 노드 중 하나의 노드만 살아있어도 서비스가 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확장성&lt;/b&gt;: 추가 처리 성능이 필요하면 응용 프러그램이나 데이터베이스를 수정할 필요 없이 새 노드를 클러스터에 쉽게 추가 가능&lt;br /&gt;클러스터의 모든 노드간에 균형이 유지되도록 로드가 다시 분산됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비용 절감&lt;/b&gt;: 표준화된 소규모 저가형 상용 하드웨어의 클러스터에서도 고가의 SMP 시스템 만큼 효율적으로 응용 프로그램을 실행함으로써 하드웨어 비용 절감&lt;/li&gt;
&lt;li&gt;도입비용 때문에 확장성이 중요한 데이터보다 고가용성을 요구하는 데이터에 많이 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) IBM DB2 ICE(Integrated Cluster Environment)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU, Memory, Disk를 파티션별로 독립적으로 운영하는 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;무공유방식 클러스터링 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;데이터와 사용자가 증가하면 애플리케이션의 수정없이 기존 시스템에 노드를 추가하고 데이터를 재분배함으로써 시스템의 성능과 용량을 일정하게 유지가능&lt;/li&gt;
&lt;li&gt;하나의 노드에 장애가 발생할 경우 해당 노드에서 서비스하는 데이터에 대한 별도의 failover 메커니즘이 필요하므로, DB2로 클러스터링을 구성할 때는 공유디스크 방식을 사용하여 가용성 보장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;* Failover: 데이터베이스의 최신 버전을 백업해두어, 1차 시스템에 장애가 발생하였을 경우 대체 시스템을 작동시켜 장애를 극복하는 기능&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 마이크로소프트 SQL Server&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연합(Federated) 데이터 베이스형태로 여러 노드로 확장할 수 있는 기능을 제공&lt;/li&gt;
&lt;li&gt;연합 데이터베이스는 디스크 등을 공유하지 않는 독립된 서버에서 실행되는 서로 다른 데이터 베이스들의 논리적인 결합이며, 네트워크를 이용하여 연결됨&lt;/li&gt;
&lt;li&gt;데이터는 관련된 서버들로 수평 분할되며 테이블을 논리적으로 분리해 물리적으로는 분산된 각 노드에 생성&lt;/li&gt;
&lt;li&gt;Failover 메커니즘을 제공하지만 Active-Active가 아닌 Active-Stanby 방법 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; i) 서버구성 문제점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DBA나 개발자가 파티셔닝 정책에 맞게 테이블과 뷰를 생성해야하고 전역 스키마 정보가 없기 때문에 질의 수행을 위해 모든 노드를 액세스해야 함&lt;/li&gt;
&lt;li&gt;노드의 개수가 작으면 간단하게 구성할 수 있지만, 노드가 많아지거나 노드의 추가/삭제가 발생하는 경우 파티션을 새로 구성해야 함&lt;/li&gt;
&lt;li&gt;Failover에 대해서 별도 구성해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) MySQL&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;비공유형&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;메모리(최근에는 디스크도 제공)기반 데이터베이스의 클러스터링 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;특성 하드웨어 및 소프트 웨어를 요구하지 않고 병렬 서버구조로 확장이 가능&lt;/li&gt;
&lt;li&gt;관리노드, 데이터노드, MySQL 노드로 구성됨
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;관리노드&lt;/b&gt;&lt;/span&gt;:&lt;span style=&quot;background-color: #f6e199;&quot;&gt; 클러스러를 관리&lt;/span&gt;하는 노드. 클러스터 시작과 재구성시에만 관여&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;데이터노드&lt;/b&gt;&lt;/span&gt;: 클러스터의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;데이터를 저장&lt;/span&gt;하는 노드&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;MySQL 노드&lt;/b&gt;&lt;/span&gt;: 클러스터 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;데이터에 접근&lt;/span&gt;을 지원하는 노드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터 가용성을 높이기 위해 데이터를 다른 노드에 복제시키며, 특정 노드에 장애가 발생하더라도 지속적인 데이터 서비스가 가능&lt;/li&gt;
&lt;li&gt;데이터는 동기화 방식으로 복제되며 이런 작업을 위해 일반적으로 데이터 노드간에는 별도의 네트워크가 구성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; i) 제한사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;파티셔닝은 LINEAR KEY 파티셔닝만 사용가능&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;클러스터에 참여하는 노드(SQL노드, 데이터노드 등) 255로 제한. 데이터 노드는 최대 48개 까지만 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;트랜잭션 수행 중에 롤백을 지원하지 않으므로 작업 수행 중 문제가 발생했다면 전체 트랜잭션 이전으로 롤백해야 함&lt;/li&gt;
&lt;li&gt;하나의 트랜잭션에 많은 데이터를 처리하는 경우 메모리 부족 문제가 발생할 수 있음&lt;/li&gt;
&lt;li&gt;칼럼명 길이는 31자, 데이터베이스의 테이블 길이는 122자까지 제한. 메타 데이터는 2만 320개까지 가능&lt;/li&gt;
&lt;li&gt;모든 클러스터의 기종은 동일해야 함. 기종에 따른 비트 저장방식이 다르면 문제 발생가능성 있음&lt;/li&gt;
&lt;li&gt;운영중 노드를 추가/삭제 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>통계학/ADP</category>
      <category>공유디스크</category>
      <category>데이터베이스</category>
      <category>데이터베이스클러스터</category>
      <category>무공유디스크</category>
      <category>클러스터</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/50</guid>
      <comments>https://hello-heehee.tistory.com/50#entry50comment</comments>
      <pubDate>Fri, 21 Feb 2025 17:02:23 +0900</pubDate>
    </item>
    <item>
      <title>[ADP] 분산데이터 저장기술 - 분산파일시스템</title>
      <link>https://hello-heehee.tistory.com/38</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;분산데이터 저장기술&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;분산파일시스템&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;클러스터&lt;/li&gt;
&lt;li&gt;데이터베이스&lt;/li&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. 구글파일시스템(GFS, Google FIle System)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일을 고정된 크기(64mb)의 chunk들로 나누고, 각 chunk에 대한 여러 개의 복제본과 chunk를 청크서버에 분산 및 저장&lt;/li&gt;
&lt;li&gt;chunk는 마스터에 의해 생성/삭제 될 수 있으며, 유일한 식별자에 의해 구별됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) GFS 설계의 가정&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저가형 서버로 구성된 환경으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;서버의 고장이 빈번히 발생 할 수 있다고 가정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;대부분 파일은 대용량이라고 가정하고 효과적으로 관리할 수 있는 방법 요구됨&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;파일에 대한 쓰기 연산은 주로 순차적으로 이루어짐&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;낮은 응답지연시간보다 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;높은 처리율이 더 중요&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) GFS의 구성요소&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Client&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;파일에 대한 읽기/쓰기 동작을 요청하는 애플리케이션&lt;/li&gt;
&lt;li&gt;파일 시스템 인터페이스와 유사한 자체 인터페이스를 지원&lt;/li&gt;
&lt;li&gt;여러 클라이언트에서 원자적인 데이터추가연산을 지원하기 위한 인터페이스 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Maste&lt;/b&gt;r
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;단일마스터구조&lt;/span&gt;로 파일시스템의 이름공간, 파일과 chunk의 매핑정보 등에 해당하는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;모든 메타데이터를 메모리상에서 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;하나의 chunk 서버를 primary로 지정하여 복제본의 갱신 연산을 일관되게 처리할 수 있도록 보장&lt;/li&gt;
&lt;li&gt;chunk들의 상태에 따라 chunk를 재복제하거나 재분산하는 것과 같은 회복동작 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chunk Server&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;로컬디스크에 chunk를 저장 및 관리하면서 클라이언트로부터의 chunk입출력 요청 처리&lt;/li&gt;
&lt;li&gt;heartbeat 메시지를 통해 청크서버의 상태에 대한 정보를 주기적으로 마스터에 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. 하둡 분산 파일시스템 (HDFS, hadoop Distributed File System)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Apache Nutch 웹 검색 엔진의 파일 시스템으로 개발됨&lt;/li&gt;
&lt;li&gt;GFS의 마스터와 유사한 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;하나의 Name node&lt;/span&gt;&lt;/b&gt;와 GFS의 Chunk server와 유사한 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;다수의 DataNode&lt;/b&gt;&lt;/span&gt;로 구성됨&lt;/li&gt;
&lt;li&gt;파일데이터는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Block(Chunk)단위&lt;/b&gt;&lt;/span&gt;로 나뉘어 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;여러 DataNode에 분산/복제/저장됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;기본적으로 파일은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;한번 쓰이면 변경되지 않는다고 가정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(2.0 알파버전부터는 저장됨 파일에 append가 가능)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;순차적 스트리밍 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;배치&lt;/span&gt;작업에 적합하도록 설계&lt;/li&gt;
&lt;li&gt;낮은 데이터 접근 지연시간보다 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;높은 데이터 처리량에 중점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Client, NameNode, DataNode 간의 통신을 위하여 TCP/IP 네트워크상에서 RPC(Remote Procedure Call)사용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) HDFS의 구성요소&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;NameNode&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;HDFS상 모든 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;메타데이터를 관리&lt;/span&gt;하며 마스터/슬레이브 구조에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;마스터의 역할&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;파일이 어떤 형태의 block단위로 나누어져 있고, 어떤 node에 특정 block이 있는지 등 시스템 전반의 상태 모니터링&lt;/li&gt;
&lt;li&gt;데이터를 저장하거나 매플리케이션을 실행하는 작업은 수행안함&lt;/li&gt;
&lt;li&gt;클라이언트로부터 파일접근 요청처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DataNode&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;GDFS의 SalveNode&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;클라이언트로부터 데이터 입출력요청 처리&lt;/li&gt;
&lt;li&gt;데이터 유실방지를 위한 block을 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;3중 복제하여 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;block을 저장할 떄 해당 block에 대한 파일의 checksum정보를 별도로 저장&lt;/li&gt;
&lt;li&gt;주기적으로 datanode 상태를 나타내는 heartbeat와 자신이 관리하는 block의 목록인 blockreport를 NameNode에 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보조네임노드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;HDFS상태 모니터링 보조&lt;/li&gt;
&lt;li&gt;주기적으로 NameNode의 파일시스템 이미지를 SnapShot해 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBb1WI/btsMmKYH6Kc/fyvFdDFrYgvLAi81MM0vq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBb1WI/btsMmKYH6Kc/fyvFdDFrYgvLAi81MM0vq1/img.png&quot; data-alt=&quot;HDFS 파일저장 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBb1WI/btsMmKYH6Kc/fyvFdDFrYgvLAi81MM0vq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBb1WI%2FbtsMmKYH6Kc%2FfyvFdDFrYgvLAi81MM0vq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;757&quot; height=&quot;359&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HDFS 파일저장 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6d89D/btsMo66oTyz/H81iPrTGrfkSetH0gurPtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6d89D/btsMo66oTyz/H81iPrTGrfkSetH0gurPtk/img.png&quot; data-alt=&quot;HDFS 파일읽기 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6d89D/btsMo66oTyz/H81iPrTGrfkSetH0gurPtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6d89D%2FbtsMo66oTyz%2FH81iPrTGrfkSetH0gurPtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;747&quot; height=&quot;389&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HDFS 파일읽기 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;3. 러스터(Luster)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cluster File System Inc.에서 개발한 객체 기반의 클러스터 파일시스템&lt;/li&gt;
&lt;li&gt;고속네트워크로 연결된 클라이언트 파일시스템, 메타데이터 서버, 객체저장서버들로 구성됨&lt;/li&gt;
&lt;li&gt;계측화된 모듈구조로 TCP/IP, Infiniband, Myrinet과 같은 네트워크를 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 구성요소&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Client File System&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Linux VFS(Virtual FIle System)에서 설치할 수 있는 파일 시스템&lt;/li&gt;
&lt;li&gt;메타데이터 서버와 객체 저장 서버들과 통신하면서 클라이언트 응용에 파일시스템인터페이스 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메타데이터 서버&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;파일시스템의 이름공간과 파일에 대한 메타에이터 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체저장서버&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;파일데이터를 저장하고, 클라이언트로부터 객체 입출력 요청 처리&lt;/li&gt;
&lt;li&gt;데이터는 세그먼트라는 작은 데이터 단위로 분할해서 복수의 디스크 장치에 분산시키는 기술인 '스트라이핑 방식'으로 분산 및 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 구동방식&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유닉스 시맨틱을 제공하면서 파일 메타데이터에 대해서는 WirteBack Cache를 지원&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;클라이언트에서 메타데이터 변경에 대한 갱신 레코드를 생성하고 나중에 메타데이터 서버에 전달&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;데타데이터 서버는 전달된 갱신 레코드를 재수행하여 변경된 메타데이터 반영&lt;/li&gt;
&lt;li&gt;파일의 메타데이터와 파일 데이터에 대한 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;동시성 제어를 위해 별도의 잠금을 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;클라이언트와 메타데이터 서버 간의 네트워크 트래픽을 최소화하기 위하여 메타데이터에 대한 잠금 요청 시에 메타데이터 접근 의도를 같이 전달하는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;intent 기반 잠금 프로토콜 사용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;4. 파일시스템 비교&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 192px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: center; height: 21px;&quot;&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 21px;&quot;&gt;&lt;b&gt;GFS&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 21px;&quot;&gt;&lt;b&gt;하둡 DFS&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 21px;&quot;&gt;&lt;b&gt;러스터&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 18px;&quot;&gt;&lt;b&gt;Open SOurce&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 18px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 18px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 18px;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Chenk Based&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Support Replication&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Multiple metadata server supported&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Locks used to maintain atomicity&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Uses a DB for storing metadata&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 34px;&quot;&gt;&lt;b&gt;Adding nodes &lt;br /&gt;without shutting down the system&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 34px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 34px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 34px;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;POSIX support&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.2558%; text-align: right; height: 17px;&quot;&gt;&lt;b&gt;Supports file modification&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4884%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.3953%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: center;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 21.8605%; text-align: center; height: 17px;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>통계학/ADP</category>
      <category>GFS</category>
      <category>HDFS</category>
      <category>luster</category>
      <category>분산파일시스템</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/38</guid>
      <comments>https://hello-heehee.tistory.com/38#entry38comment</comments>
      <pubDate>Thu, 20 Feb 2025 16:06:39 +0900</pubDate>
    </item>
    <item>
      <title>[NLP] Drain3 - Python</title>
      <link>https://hello-heehee.tistory.com/48</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;1. Drain3&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자연어로 이루어진 데이터들의 Template을 자동적으로 만들어주는 라이브러리&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1739931698396&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 라이브러리 설치
pip install drain3&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;2. CODE&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://github.com/logpai/Drain3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github&lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1739931875557&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - logpai/Drain3: A robust streaming log template miner based on the Drain algorithm&quot; data-og-description=&quot;A robust streaming log template miner based on the Drain algorithm - logpai/Drain3&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/logpai/Drain3&quot; data-og-url=&quot;https://github.com/logpai/Drain3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kYQGO/hyYjv7fugY/0FJ9LWF3H9KT9MUih0umV1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/c8tqPf/hyYjo76SBs/KVjrDtArkez7JyZqXW8e00/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/logpai/Drain3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/logpai/Drain3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kYQGO/hyYjv7fugY/0FJ9LWF3H9KT9MUih0umV1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/c8tqPf/hyYjo76SBs/KVjrDtArkez7JyZqXW8e00/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - logpai/Drain3: A robust streaming log template miner based on the Drain algorithm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A robust streaming log template miner based on the Drain algorithm - logpai/Drain3&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;examples 폴더의 drain3.ini와 drain_bigfile_demo.py, drain_stdin_demo.py만 봐도 기본적인 drain3가 사용가능&lt;/li&gt;
&lt;li&gt;위를 바탕으로 아래에 코드 재 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;1) LogTemplate을 구하여 저장&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739932417073&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import json
import logging
import os, sys, time

from os.path import dirname
from drain3 import TemplateMiner
from drain3.template_miner_config import TemplateMinerConfig
from drain3.file_persistence import 


filename = &quot;./logdata.txt&quot;
save_bin = &quot;./save_bin.bin&quot; #bin파일로 저장
save_json = &quot;./save_json.json&quot; #bin파일은 압축하여 저장하기 때문에 시각적으로 보고싶다면 사용

# logdata 불러오기
with open(filename) as f:
    log_lines =f.readlines()

logger=logging.getLogger(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(message)s')
persistence=FilePersistence(save_bin)

# Initialize
config=TemplateMinerConfig() 
template_miner=TemplateMiner(persistence,config=config)


line_count=0
start_time=time.time()
batch_start_time=start_time
batch_size=10000

for line in log_lines:
    line=line.rstrip()
    result=template_miner.add_log_message(line)
    line_count+=1
    if result[&quot;change_type&quot;]!=&quot;none&quot;:
        result_json=json.dumps(result)
        template=result[&quot;template_mined&quot;]

time_took=time.time()-start_time
rate=line_count/time_took
logger.info(f&quot;--- Done processing file in {time_took:.2f} sec. Total of {line_count} lines, rate {rate:.1f} lines/sec, &quot;
        f&quot;{len(template_miner.drain.clusters)} clusters&quot;)

#sorted_clusters = sorted(template_miner.drain.clusters, key=lambda it: it.size, reverse=True)

#Log Template 저장 - 시각적으로 보기 위한 용도
with open(save_json, &quot;w&quot;) as f:
    template_miner.drain.print_tree(f)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;2) 저장한 LogTemplate 불러오기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739933244496&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import json
import logging
import os, sys, time
from os.path import dirname

from drain3 import TemplateMiner
from drain3.template_miner_config import TemplateMinerConfig
from drain3.file_persistence import FilePersistence

filename = &quot;./logdata2.txt&quot;
load_bin = &quot;./save_bin.bin&quot;
save_txt = &quot;./save_txt.txt&quot; 

# logdata 불러오기
with open(filename) as f:
    log_lines =f.readlines()
    
# 저장한 bin파일 불러오기
persistence=FilePersistence(load_bin)

#Initialize
config=TemplateMinerConfig()
template_miner=TemplateMiner(persistence, config=config)

# Template Matching
for line in log_lines:
    cluster=template_miner.match(line)
    template=cluster.get_template()
    with open(save_txt, &quot;a+&quot;) as f:
    	f.write('{},{}'.format(cluster.cluster_id, template)) # Template ID와 Template 저장
        f.write(','.join(template_miner.get_parameter_list(template,line))) # Masking 된 원소 추출
        f.write('\n')&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;3. Initialize&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;1) Default&amp;nbsp; Initialize&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1739933672684&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;drain_depth =4
drain_extra_delimiters =[]
drain_max_children =100
drain_max_clusters =None
drain_sim_th =0.4
mask_prefix ='&amp;lt;'
mask_suffix ='&amp;gt;'
masking_instructions =[]
parameter_extraction_cache_capacity =3000
parametrize_numeric_tokens =True
profiling_enabled =False
profiling_report_sec =60
snapshot_compress_state =True
snapshot_interval_minutes =5&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;drain depth : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;max depth levels of log clusters. Minimum is 3.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;extra_delimiters : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;delimiters to apply when splitting log message into words (in addition to whitespace). &lt;br /&gt;Format is a Python list e.g.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;['_', ':']&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;max_children : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;max number of children of an internal node&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;max_clusters : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;max number of tracked clusters&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;sim_th : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;similarity threshold&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;mask_prefix, mask_suffix : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;the wrapping of identified parameters in templates.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;masking_instructions : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;arameters masking&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;parameter_extraction_cache_capacity :&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;parameterize_numeric_tokens L&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;profiling_enabled : Added time prifiling (True/False)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;profiling_report_sec : profiling report second&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;snapshot_compress_state : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;whether to compress the state before saving it.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;snapshot_interval_minutes : &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;time interval for new snapshot&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;2) 사용자가 직접 만들 수 있음&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1739932096469&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[SNAPSHOT]
snapshot_interval_minutes = 10
compress_state = True

[MASKING]
masking = [
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)(([0-9a-f]{2,}:){3,}([0-9a-f]{2,}))((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;ID&quot;},
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;IP&quot;},
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)([0-9a-f]{6,} ?){3,}((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;SEQ&quot;},
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)([0-9A-F]{4} ?){4,}((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;SEQ&quot;},
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)(0x[a-f0-9A-F]+)((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;HEX&quot;},
          {&quot;regex_pattern&quot;:&quot;((?&amp;lt;=[^A-Za-z0-9])|^)([\\-\\+]?\\d+)((?=[^A-Za-z0-9])|$)&quot;, &quot;mask_with&quot;: &quot;NUM&quot;},
          {&quot;regex_pattern&quot;:&quot;(?&amp;lt;=executed cmd )(\&quot;.+?\&quot;)&quot;, &quot;mask_with&quot;: &quot;CMD&quot;}
          ]
mask_prefix = &amp;lt;:
mask_suffix = :&amp;gt;

[DRAIN]
# engine is Optional parameter. Engine will be &quot;Drain&quot; if the engine argument is not specified.
# engine has two options: 'Drain' and 'JaccardDrain'.
# engine = Drain
sim_th = 0.4
depth = 4
max_children = 100
max_clusters = 1024
extra_delimiters = [&quot;_&quot;]

[PROFILING]
enabled = True
report_sec = 30&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;masking은 &lt;a href=&quot;https://hamait.tistory.com/342&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;정규표현식 구조&lt;/a&gt;로 사용하면 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1739934212422&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;정규표현식 (Regex) 정리&quot; data-og-description=&quot;정규표현식은 아주 가끔 쓰기때문에 항상 다시 볼때마다 헷갈리곤 하기에 주요 사용예를 내가 나중에 다시 봤을 때 편하도록 정리하여 보았다. 정규 표현식의 용어들정규 표현식에서 사용되는 &quot; data-og-host=&quot;hamait.tistory.com&quot; data-og-source-url=&quot;https://hamait.tistory.com/342&quot; data-og-url=&quot;https://hamait.tistory.com/342&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BgJWU/hyYfELvKi0/ELeWyxatkpzZowbm06tlN0/img.jpg?width=699&amp;amp;height=315&amp;amp;face=0_0_699_315,https://scrap.kakaocdn.net/dn/cX3jS6/hyYjvGaFUU/D8TkcBEKrfNoKJz7WhLI6k/img.jpg?width=699&amp;amp;height=315&amp;amp;face=0_0_699_315,https://scrap.kakaocdn.net/dn/pTpqQ/hyYfNV1wZo/Sf72XdZcsfDYbRhPXhvryK/img.jpg?width=600&amp;amp;height=506&amp;amp;face=0_0_600_506&quot;&gt;&lt;a href=&quot;https://hamait.tistory.com/342&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hamait.tistory.com/342&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BgJWU/hyYfELvKi0/ELeWyxatkpzZowbm06tlN0/img.jpg?width=699&amp;amp;height=315&amp;amp;face=0_0_699_315,https://scrap.kakaocdn.net/dn/cX3jS6/hyYjvGaFUU/D8TkcBEKrfNoKJz7WhLI6k/img.jpg?width=699&amp;amp;height=315&amp;amp;face=0_0_699_315,https://scrap.kakaocdn.net/dn/pTpqQ/hyYfNV1wZo/Sf72XdZcsfDYbRhPXhvryK/img.jpg?width=600&amp;amp;height=506&amp;amp;face=0_0_600_506');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;정규표현식 (Regex) 정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;정규표현식은 아주 가끔 쓰기때문에 항상 다시 볼때마다 헷갈리곤 하기에 주요 사용예를 내가 나중에 다시 봤을 때 편하도록 정리하여 보았다. 정규 표현식의 용어들정규 표현식에서 사용되는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hamait.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;315&quot;&gt;&lt;a href=&quot;https://hamait.tistory.com/342&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dE3Emy/btsMn7kjDOV/MuaDIFXgCSapwjWpK6a2jK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdE3Emy%2FbtsMn7kjDOV%2FMuaDIFXgCSapwjWpK6a2jK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;699&quot; height=&quot;315&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDgvZK/btsMmIlTECv/Lf6b6T65Zh41rR39umIWB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDgvZK/btsMmIlTECv/Lf6b6T65Zh41rR39umIWB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDgvZK/btsMmIlTECv/Lf6b6T65Zh41rR39umIWB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDgvZK%2FbtsMmIlTECv%2FLf6b6T65Zh41rR39umIWB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;751&quot; height=&quot;450&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;3. 저장한 Initialize 사용하기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1739934372140&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;config=TemplateMinerConfig()
config.load(&quot;./drain3.ini&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;4. Drain3 결과&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Template 저장시 json파일을 열어보면 아래와 같이 저장된다.&lt;/p&gt;
&lt;pre id=&quot;code_1739934671033&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;root&amp;gt;
	&amp;lt;L=24&amp;gt;
		&quot;&amp;lt;TEST&amp;gt;&quot; (cluster_count=1)
			ID=1     : size=4610      : &amp;lt;TEST&amp;gt;  &amp;lt;:DATE:&amp;gt; &amp;lt;:TIME:&amp;gt;  &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt;  System  &amp;lt;:HEX:&amp;gt;  MAIN  &amp;lt;:*:&amp;gt;
		&quot;&amp;lt;ERROR&amp;gt;&quot; (cluster_count=1)
			ID=4     : size=23381     : &amp;lt;ERROR&amp;gt;  &amp;lt;:DATE:&amp;gt; &amp;lt;:TIME:&amp;gt;  &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt;
		&quot;&amp;lt;WARNING&amp;gt;&quot; (cluster_count=1)
			ID=73    : size=193       : &amp;lt;WARNING&amp;gt;  &amp;lt;:DATE:&amp;gt; &amp;lt;:TIME:&amp;gt;  &amp;lt;:*:&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;ID: Cluster ID로 Template ID로 보면 됨&lt;/li&gt;
&lt;li&gt;Size: 이 Template에 해당하는 데이터 갯수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 예시 데이터로 테스트 해보면&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739935029102&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;TEST&amp;gt;	2020-01-01 00:00:00	It is a test!	System	1234	MAIN	1234&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 결과를 얻는다.&lt;/p&gt;
&lt;pre id=&quot;code_1739934812144&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1,&amp;lt;TEST&amp;gt;  &amp;lt;:DATE:&amp;gt; &amp;lt;:TIME:&amp;gt;  &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt; &amp;lt;:*:&amp;gt;  System  &amp;lt;:HEX:&amp;gt;  MAIN  &amp;lt;:*:&amp;gt;
2020-01-01,00:00:00,It,is,a,test!,1234,1234&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DeepLearning/NLP</category>
      <category>drain3</category>
      <category>logtemplate</category>
      <category>nlp</category>
      <category>python3</category>
      <author>헬로희</author>
      <guid isPermaLink="true">https://hello-heehee.tistory.com/48</guid>
      <comments>https://hello-heehee.tistory.com/48#entry48comment</comments>
      <pubDate>Wed, 19 Feb 2025 12:23:08 +0900</pubDate>
    </item>
  </channel>
</rss>