diff --git a/README.md b/README.md index b6c7d402d23..b4e4d561f74 100644 --- a/README.md +++ b/README.md @@ -1,134 +1,3 @@ -# Lanyon +# TaeHwanYoun GitHub -Lanyon is an unassuming [Jekyll](http://jekyllrb.com) theme that places content first by tucking away navigation in a hidden drawer. It's based on [Poole](http://getpoole.com), the Jekyll butler. - -![Lanyon](https://f.cloud.github.com/assets/98681/1825266/be03f014-71b0-11e3-9539-876e61530e24.png) -![Lanyon with open sidebar](https://f.cloud.github.com/assets/98681/1825267/be04a914-71b0-11e3-966f-8afe9894c729.png) - - -## Contents - -- [Usage](#usage) -- [Options](#options) - - [Sidebar menu](#sidebar-menu) - - [Themes](#themes) - - [Reverse layout](#reverse-layout) -- [Development](#development) -- [Author](#author) -- [License](#license) - - -## Usage - -Lanyon is a theme built on top of [Poole](https://github.com/poole/poole), which provides a fully furnished Jekyll setup—just download and start the Jekyll server. See [the Poole usage guidelines](https://github.com/poole/poole#usage) for how to install and use Jekyll. - - -## Options - -Lanyon includes some customizable options, typically applied via classes on the `` element. - - -### Sidebar menu - -Create a list of nav links in the sidebar by assigning each Jekyll page the correct layout in the page's [front-matter](http://jekyllrb.com/docs/frontmatter/). - -``` ---- -layout: page -title: About ---- -``` - -**Why require a specific layout?** Jekyll will return *all* pages, including the `atom.xml`, and with an alphabetical sort order. To ensure the first link is *Home*, we exclude the `index.html` page from this list by specifying the `page` layout. - - -### Themes - -Lanyon ships with eight optional themes based on the [base16 color scheme](https://github.com/chriskempson/base16). Apply a theme to change the color scheme (mostly applies to sidebar and links). - -![Lanyon with red theme](https://f.cloud.github.com/assets/98681/1825270/be065110-71b0-11e3-9ed8-9b8de753a4af.png) -![Lanyon with red theme and open sidebar](https://f.cloud.github.com/assets/98681/1825269/be05ec20-71b0-11e3-91ea-a9138ef07186.png) - -There are eight themes available at this time. - -![Available theme classes](https://f.cloud.github.com/assets/98681/1817044/e5b0ec06-6f68-11e3-83d7-acd1942797a1.png) - -To use a theme, add any one of the available theme classes to the `` element in the `default.html` layout, like so: - -```html - - ... - -``` - -To create your own theme, look to the Themes section of [included CSS file](https://github.com/poole/lanyon/blob/master/public/css/lanyon.css). Copy any existing theme (they're only a few lines of CSS), rename it, and change the provided colors. - - -### Reverse layout - -![Lanyon with reverse layout](https://f.cloud.github.com/assets/98681/1825265/be03f2e4-71b0-11e3-89f1-360705524495.png) -![Lanyon with reverse layout and open sidebar](https://f.cloud.github.com/assets/98681/1825268/be056174-71b0-11e3-88c8-5055bca4307f.png) - -Reverse the page orientation with a single class. - -```html - - ... - -``` - - -### Sidebar overlay instead of push - -Make the sidebar overlap the viewport content with a single class: - -```html - - ... - -``` - -This will keep the content stationary and slide in the sidebar over the side content. It also adds a `box-shadow` based outline to the toggle for contrast against backgrounds, as well as a `box-shadow` on the sidebar for depth. - -It's also available for a reversed layout when you add both classes: - -```html - - ... - -``` - -### Sidebar open on page load - -Show an open sidebar on page load by modifying the `` tag within the `sidebar.html` layout to add the `checked` boolean attribute: - -```html - -``` - -Using Liquid you can also conditionally show the sidebar open on a per-page basis. For example, here's how you could have it open on the homepage only: - -```html - -``` - -## Development - -Lanyon has two branches, but only one is used for active development. - -- `master` for development. **All pull requests should be to submitted against `master`.** -- `gh-pages` for our hosted site, which includes our analytics tracking code. **Please avoid using this branch.** - - -## Author - -**Mark Otto** -- -- - - -## License - -Open sourced under the [MIT license](LICENSE.md). - -<3 +Hi diff --git a/_config.yml b/_config.yml index 45bc1ac8463..78e3149c9d4 100644 --- a/_config.yml +++ b/_config.yml @@ -1,17 +1,18 @@ # Setup -title: Lanyon -tagline: 'A Jekyll theme' +title: You& +tagline: 'Data_Science & Life' description: 'A reserved Jekyll theme that places the utmost gravity on content with a hidden drawer. Made by @mdo.' -url: http://lanyon.getpoole.com +url: https://taehwanyoun.github.io baseurl: '' paginate: 5 permalink: pretty +# category_dir: category/ # About/contact author: - name: Mark Otto - url: https://twitter.com/mdo - email: markdotto@gmail.com + name: TaeHwan Youn + # url: https://twitter.com/mdo + email: youn4576@gmail.com # Gems plugins: @@ -20,3 +21,26 @@ plugins: # Custom vars version: 1.1.0 google_analytics_id: #UA-XXXX-Y + + +# Math equation +markdown: kramdown +highlighter: rouge +lsi: false +excerpt_separator: "\n\n" +incremental: false + + + +# # comments +# disqus_url : http://disqus.com/by/disqus_NqcV1O9wdy +# disqus_id : 'taehwanyoun.github.io' +disqus_shortname: taehwanyoun.github.io/ +discus-identifier: taehwanyoun.github.io/ # add your discus identifier + + +# comments: true +# provider : "disqus" # 블로그 댓글 기능 false (default), "disqus", "discourse", "facebook", "staticman", "staticman_v2", "utterances", "custom" +# disqus: +# shortname : 'taehwanyoun-github-io' +# # 블로그 댓글 기능 https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname- shortname : "devinlife-github-io" # 블로그 댓글 기능 https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname- diff --git a/_includes/disqus.html b/_includes/disqus.html new file mode 100644 index 00000000000..b2c09a5931b --- /dev/null +++ b/_includes/disqus.html @@ -0,0 +1,20 @@ +
+ + diff --git a/_includes/head.html b/_includes/head.html index 44e3f5d6fb2..656eda38727 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -1,5 +1,5 @@ - + @@ -19,10 +19,14 @@ - + + + + + - + @@ -36,4 +40,28 @@ ga('send', 'pageview'); {% endif %} + + + diff --git a/_includes/mathjax_support.html b/_includes/mathjax_support.html new file mode 100644 index 00000000000..ec077ed53c9 --- /dev/null +++ b/_includes/mathjax_support.html @@ -0,0 +1,23 @@ + + diff --git a/_includes/sidebar.html b/_includes/sidebar.html index 762202aab7b..74c951b2c75 100644 --- a/_includes/sidebar.html +++ b/_includes/sidebar.html @@ -25,8 +25,8 @@ {% endif %} {% endfor %} - Download - GitHub project + + Currently v{{ site.version }} diff --git a/_layouts/post.html b/_layouts/post.html index c4bc2533557..7c9a31e1464 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -5,6 +5,7 @@

{{ page.title }}

+ {{ content }}
@@ -25,3 +26,10 @@

{% endif %} + +{% if site.disqus-shortname %}{% include disqus.html %}{% endif %} + {% if page.comments %} +
+ {% include disqus.html %} +
+{% endif %} diff --git a/_posts/2020-04-01-whats-jekyll.md b/_posts/2020-04-01-whats-jekyll.md deleted file mode 100644 index 515b87333ef..00000000000 --- a/_posts/2020-04-01-whats-jekyll.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -layout: post -title: What's Jekyll? ---- - -[Jekyll](https://jekyllrb.com) is a static site generator, an open-source tool for creating simple yet powerful websites of all shapes and sizes. From [the project's readme](https://github.com/mojombo/jekyll/blob/master/README.markdown): - - > Jekyll is a simple, blog aware, static site generator. It takes a template directory [...] and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub. - -It's an immensely useful tool and one we encourage you to use here with Lanyon. - -Find out more by [visiting the project on GitHub](https://github.com/mojombo/jekyll). diff --git a/_posts/2020-04-02-example-content.md b/_posts/2020-04-02-example-content.md deleted file mode 100644 index 81e474879a3..00000000000 --- a/_posts/2020-04-02-example-content.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -layout: post -title: Example content ---- - - -
- Howdy! This is an example blog post that shows several types of HTML content supported in this theme. -
- -Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. *Aenean eu leo quam.* Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum. - -> Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit. - -Etiam porta **sem malesuada magna** mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur. - -## Inline HTML elements - -HTML defines a long list of available inline tags, a complete list of which can be found on the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTML/Element). - -- **To bold text**, use ``. -- *To italicize text*, use ``. -- Abbreviations, like HTML should use ``, with an optional `title` attribute for the full phrase. -- Citations, like — Mark otto, should use ``. -- Deleted text should use `` and inserted text should use ``. -- Superscript text uses `` and subscript text uses ``. - -Most of these elements are styled by browsers with few modifications on our part. - -## Heading - -Vivamus sagittis lacus vel augue rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. - -### Code - -Cum sociis natoque penatibus et magnis dis `code element` montes, nascetur ridiculus mus. - -{% highlight js %} -// Example can be run directly in your JavaScript console - -// Create a function that takes two arguments and returns the sum of those arguments -var adder = new Function("a", "b", "return a + b"); - -// Call the function -adder(2, 6); -// > 8 -{% endhighlight %} - -Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa. - -### Lists - -Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. - -* Praesent commodo cursus magna, vel scelerisque nisl consectetur et. -* Donec id elit non mi porta gravida at eget metus. -* Nulla vitae elit libero, a pharetra augue. - -Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. - -1. Vestibulum id ligula porta felis euismod semper. -2. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. -3. Maecenas sed diam eget risus varius blandit sit amet non magna. - -Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. - -
-
HyperText Markup Language (HTML)
-
The language used to describe and define the content of a Web page
- -
Cascading Style Sheets (CSS)
-
Used to describe the appearance of Web content
- -
JavaScript (JS)
-
The programming language used to build advanced Web sites and applications
-
- -Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Nullam quis risus eget urna mollis ornare vel eu leo. - -### Tables - -Aenean lacinia bibendum nulla sed consectetur. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameUpvotesDownvotes
Totals2123
Alice1011
Bob43
Charlie79
- -Nullam id dolor id nibh ultricies vehicula ut id elit. Sed posuere consectetur est at lobortis. Nullam quis risus eget urna mollis ornare vel eu leo. - ------ - -Want to see something else added? Open an issue. diff --git a/_posts/2020-04-03-introducing-lanyon.md b/_posts/2020-04-03-introducing-lanyon.md deleted file mode 100644 index 13e7ce4854d..00000000000 --- a/_posts/2020-04-03-introducing-lanyon.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: post -title: Introducing Lanyon ---- - -Lanyon is an unassuming [Jekyll](http://jekyllrb.com) theme that places content first by tucking away navigation in a hidden drawer. It's based on [Poole](http://getpoole.com), the Jekyll butler. - -### Built on Poole - -Poole is the Jekyll Butler, serving as an upstanding and effective foundation for Jekyll themes by [@mdo](https://twitter.com/mdo). Poole, and every theme built on it (like Lanyon here) includes the following: - -* Complete Jekyll setup included (layouts, config, [404](/404), [RSS feed](/atom.xml), posts, and [example page](/about)) -* Mobile friendly design and development -* Easily scalable text and component sizing with `rem` units in the CSS -* Support for a wide gamut of HTML elements -* Related posts (time-based, because Jekyll) below each post -* Syntax highlighting, courtesy Pygments (the Python-based code snippet highlighter) - -### Lanyon features - -In addition to the features of Poole, Lanyon adds the following: - -* Toggleable sliding sidebar (built with only CSS) via **☰** link in top corner -* Sidebar includes support for textual modules and a dynamically generated navigation with active link support -* Two orientations for content and sidebar, default (left sidebar) and [reverse](https://github.com/poole/lanyon#reverse-layout) (right sidebar), available via `` classes -* [Eight optional color schemes](https://github.com/poole/lanyon#themes), available via `` classes - -[Head to the readme](https://github.com/poole/lanyon#readme) to learn more. - -### Browser support - -Lanyon is by preference a forward-thinking project. In addition to the latest versions of Chrome, Safari (mobile and desktop), and Firefox, it is only compatible with Internet Explorer 9 and above. - -### Download - -Lanyon is developed on and hosted with GitHub. Head to the GitHub repository for downloads, bug reports, and features requests. - -Thanks! diff --git a/_posts/2020-07-04-Hello.md b/_posts/2020-07-04-Hello.md new file mode 100644 index 00000000000..d0cbddb773a --- /dev/null +++ b/_posts/2020-07-04-Hello.md @@ -0,0 +1,96 @@ +--- +layout: post +title: Profile +date : 05 Jul 2020 +category : Archive +comments : true +--- +## Profile :p +### TaeHwan Youn +#### Birth : 92.01.07 +#### Loc : Dongdaemun-gu, Seoul, Republic of Korea +#### KeyWord + + Data_Science + + Data_Preprocess + + MachineLearning + + DeepLearning + + + +```python +from datetime import datetime + +def calc_age(DOB) : + today = datetime.today() + return today.year - DOB.year - ((today.month, today.day) < (DOB.month, DOB.day)) + +# data setting +DOB = datetime(1992, 1, 7) +age = calc_age(DOB) +work_exprience = {'NGO_Director' : 2, + 'Marketer' : 1, + 'DataScientist' : 1.3} +skill = {'ML' : 5, + 'DeepLearning' : 2, + 'Analysis' : 4, + 'Presentaion' : 3, + 'Communication' : 4} +language = {'python' : 5, + 'R' : 4, + 'SQL' : 2} +``` +```python + + +df_vis_tmp = pd.DataFrame.from_dict( + work_exprience, orient='index' +).rename(columns={0:'year'}) +plt.bar(df_vis_tmp.index, df_vis_tmp.year, color = ['cornflowerblue', 'lightseagreen', 'pink']) + +``` +```python +# drow plot +import numpy as np +import matplotlib.pyplot as plt + +def make_radar_plot(target_dict, target_color) : + label = list(target_dict.keys()) + label = [*label, label[0]] + score = list(target_dict.values()) + score = [*score, score[0]] + + # theta + label_loc = np.linspace(start= 0, stop= 2* np.pi, num = len(label)) + + _ = plt.figure(figsize = (6, 6.)) + ax = plt.subplot(polar = True) + _ = plt.xticks(label_loc, labels= label) + _ = ax.plot(label_loc, score, linestyle = 'dashed', color = target_color) + _ = ax.fill(label_loc, score, color = target_color, alpha = 0.3) + plt.show() + + return +``` +```python +df_vis_tmp = pd.DataFrame.from_dict( + work_exprience, orient='index' + ).rename(columns={0:'year'}) + plt.bar(df_vis_tmp.index, df_vis_tmp.year, color = ['cornflowerblue', 'lightseagreen', 'pink']) + +``` +```python +skill = {'ML' : 5, + 'DeepLearning' : 2, + 'Analysis' : 4, + 'Presentaion' : 3, + 'Communication' : 4} +make_radar_plot(target_dict = skill , target_color = 'skyblue') + +language = {'python' : 5, + 'R' : 4, + 'SQL' : 2} +make_radar_plot(target_dict = language , target_color = 'violet') + +``` +

+*"기억하기보다, 기록하기"* diff --git a/_posts/2020-08-22-book_1_nobody.md b/_posts/2020-08-22-book_1_nobody.md new file mode 100644 index 00000000000..a735b6bd0bd --- /dev/null +++ b/_posts/2020-08-22-book_1_nobody.md @@ -0,0 +1,139 @@ +--- +layout: post +title: book_archive_아무도 아닌 +date : 22 Aug 2020 +category : Archive +comments : true +--- +# 아무도 아닌
+- author : 황정은 + +
+아무도 아닌, 을 사람들은 자꾸 아무것도 아닌, 으로 읽는다. +
+ +### 上行 + +시골에서 살면 좀 나을까 싶어서 알아보러 내려온 거거든. 나, 도시에서 사는 건 이제 싫다. 육 개월 단위로 계약서 써가며 일해봤냐. 사람을 말린다. 옴짝달싹 못하겠어. 마땅하지 않은 일이 생겨도 직장에서 한마디 할 수 있기를 하나. 눈치만 보게 되고 보람도 없다. 계약서 갱신할 날이 다가오면 가슴만 이렇게 뛴다. 다 때려치우고 이런 곳에서 한적하게 살아볼까 싶었는데 만만치 않네. 시골에서도 뭐가 있어야 산다잖냐. 내가 참, 뭐가 없는 놈이구나, 이런 생각만들고, 괜히 왔다. + -27p- + +노부인이 내 얼굴을 바짝 들여다보고 말했다. +자고 가. +밥 줄게. +누군가 도와줬으면 해서 둘러보았지만 오제도 오제의 어머니도 짐을 확인하느라고 바빴다. 뭐라 대답해야 할지 몰라 서 있다가 다음에 와서 자고 갈게요, 라고 말했다. 몇 겹으로 왜곡된 안경 속에서 노부인의 눈이 슬프게 일그러졌다. +다음에 오냐. +네. +정말로 오냐. +네. +나 죽기 전에 정말로 올테냐. +..... +오긴 뭘오냐 니가, 라고 토라진 듯 중얼거리는 노부인 앞에서 안하느니만 못한 말이자 약속도 안니 약속을 해버린 나는 얼굴을 붉혔다. +-33p- + +나는 잠자코 조수석에 앉은 채로 월식을 생각했다. 한 번도 그걸 본 적이 없었다. 보자고 굳게 마음을 먹어도 언제나 잊었다. 이번에야말로, 라고 나는 다짐했으나 막상 그 시간이 되면 내가 어디서 무엇을 하고 있을지, 나도 알 수 없었다. +-35p- + + +### 양의 미래 + +호재의 곁에서 나는 몇 번인가 내 아버지 이야기를 했다. 묵묵히 어머니를 돌보는 아버지. 남성성이 완전히 사라진 듯한 모습으로, 아버지라기보다는 할머니 같은 모습으로 집안 살림을 하는 왜소한 체구의 아버지. +어머니가이제 죽었으면 좋겠어. +아버지도. +이런 이야기를 내가 했을가. 내가 정말로 했을까. 둘 가운데 어느 이야기를 했고 어느 것을 하지 않았는지는 확실하지 않다. 둘 다를 하지는 않았어도 둘 가운데 하나는 했을 것이다. 평생 아이를 만들지 않을 거라고 내가 말했을 때 호재는 왜냐고 묻지 않았으니까. +-46p- + +화단엔 늘 고양이가 몇 마리 있었다. 고양이들은 사라졌다가 다시 나타나고는 하며 밥을 먹고 갔다. 화단에서 밥을 먹고 자란 암컷들은 새끼를 배면 화단으로 돌아왔다. 어미 고양이와 새끼들. 그들이 바꿔가며 어디론가 갔다가 돌아오곤 하는 동안 호재의 우산은 그대로 관목 위에 펼쳐져 있었다. 낡은 우산살 위로 우산 천이 말려 올라간 모습으로 말이다. +-48p- + +...마침내 중간 선반에서 바짝 마른 걸레로 덮인 망치를 찾아냈다. 그걸 쥐고 그 벽 앞에 섰다. 습기와 곰팡이가 덩굴무늬처럼 번진 벽 귀퉁이를 바라보았다. 그러고 있는 와중에도 벽 너머에서 불어오는 바람이 느껴졌다. 그가 모를 뿐 터널은 있다. 봐. 바람이 분다. 터널을 관통하는 바람이 이렇게. 나는 그걸 확인할 수 있었다. 망치를 들어서 몇 번 휘두르면 가능했다. 어쩌면 계란 껍데기를 뚫는 것처럼 쉬울 수도 있었다. 그리고 바로 그때문에 나는 그렇게 할 수 없었다. +터널이 있는 것과 터널이 없는 것. +... +나는 그걸 알 수 없었고 아마 앞으로도 알 수 없을 것이다. 나는 그냥 망치를 쥔 채로 벽 앞에 서 있다가 내 도시락이 놓인 박스 곁으로 돌아갔다. +-58p- + +가난하고 돌보아줄 인연 없는 늙은 자로서 병들어 죽어가는 것처럼 비참한 일이 있을, 생각한다. 저자는 이런 죽음을 두고 여태껏 인류가 발명한 어느 무기도 그런 형태의 자연사만큼 사람을 강력하게 비참하게 만드는 것은 없었다고 말하고 있었다. 때문에 그는 늙어 죽는 것을 소망한 것이 아니고 길 가다 우연하게, 느닷없이 죽고 싶다고 써두었다. 나는 그의 문장 곁에 그렇다, 라고 적은 뒤 연필 끝으로 종이를 꾹꾹 누르고 있다가 이렇게 덧붙였다. +-60p- + + +### 상류엔 맹금류 +그러나 어느 엉뚱한 순간, 예컨대 텔레비전을 보다가 어떤 장면에서 그가 웃고 내가 웃지 않을 때, 그가 모는 차의 조수석에앉서 부쩍부쩍 다가오는 도로를 바라볼 때, 어째서 이 사람인가를 골똘히 생각한다. +어쩌서 제희가 아닌가. +그럴 땐 버려졌다는 생각에 외로워진다. 제희와 제희네. 무뚝뚝해보이고 다소간 지쳤지만, 상냥한 사람들에게. + + +### 명실 +그녀에게는 갓난아기의 도톰한 발을 쥐고 엄지로 발바닥을 문지르며 감탄한 기억이 있었다. 굳은살이라고는 조금도 없는 말랑한 살에 관한 기억이었다. 직립과 보행을 아직 경험하지 않은 인간의 발. 누구나 이런 발을 가지고 태어나는데.... 일단 일어서서 걸음을 걸음을 배우게 되면 달라지지. 완전히 다른 조직인 것처럼 발바닥도 뒤꿈치도 딱딱해져... 그게 너무 서글프다고 생각하며 그 작은 발을 한참 만닌 기억이 있었다. +-95p- + +그녀가 가진 것은 파편들이었다. 문장이라기보다는 목소리였고 모으려고 할수록 멀어지고 흩어지는 메아리들이었다. 실리의 이야기들은 책이 되지 못했다. +-99p- + +실리는 늘 다루곤 하는 사물에 특별한 애착을 품었고 종종 그런 사물들에 정서가 있다고 우겼다. .... 혹시나 그런 장소에서 물건을 잃어버리는 일이 생기면 낯선 곳에서 그 물건이 무엇을 느낄지, 그래 정말 무엇을 느낄지, *그 조그만 사물이 난데없이 그 자리에 홀로 남아 얼마나 애가 타고 허탈할지, 그런 것을 다 속상해하고는 했다.* 본인이 혼자가 되는 것을 두려워했기 때문이지, 하고 그녀는 생각했다. 실리는 외로움을 많이 타는 사람이었으므로 무언가를 혼자 남겨두는 것에 예민한게 반응했다. +-103p- + +그건 꼭 .... 죽은 사람들에 관한 이야기 같다고 그녀가 말하자 실리는 그런가, 라고 대답했다. 죽은 사람이 죽은 사람을 기다리는 이야기. 실리는 그걸 완성하지 못하고 죽었다. 그를 언제 까지고 벌판에 내버려둔 채로 죽고 말았다. 실리의 화자는 내내 벌판에 있는 것이다. 마리코가 ....알아보지 못하고 지나갈까봐 앉지도 못하고 서서. +-105p- + +그게 필요했다. 모든 것이 사라져가는 이때. +어둠을 수평선으로 나누는 불빛 같은 것. 저기 그게 있다는 지표 같은 것이. +그 아름다운 것이 필요했다. +그녀는 노트에 만년필을 대고 잉크가 흐르기를 기다렸다. 제목을 적고 쉼표를 그리고 이름을 적었다. + +겨울이 얼마 남지 않았다고 그녀는 생각했다. +-111p- + + +### 누가 + +노인이 오 년 동안 머물렀던 방은 벽지도 바닥재도 그대로였다. 바싹 마른 벽에 둥글게 자국이 남아 있었고 그녀는 바로 그 자리에 노인이 머리를 대고 앉았을 거라고 생각했다. 노랗다못해 붉은색을 띤 기름 얼룩. 거기에 머리를 대고 노인은 도대체 뭘 보았을까. +... +그런데 이상하기도 하지. 나는 정당하게 세를 내고 이 집으로 들어왔을 뿐인데 노인을 내쫓았다가는 기분이 든다..... 여기서 나가서 노인은 아마 더 좋지 않은 곳으로 갔을 것이다... 잘 모르면서 그녀는 생각했다. 다른 가능성도 있을 수 있었지만 다른 어떤 가능성보다도 그것이 그녀에게는 더 리얼하게 여겨졌으므로 그게 유일한 가능성인 것처럼 생각되었다. 그렇다고 하더라도... 그게 내 탓인가. 내가 내쫓았나. 그녀는 이불을 발로 차며 돌아누웠다. 노인은 방을 유지할 능력이 없엇을뿐이고 내게는 있었을 뿐. 그냥 그것뿐. 만사가 그뿐. +-127p- + +그제는 건너 자리의 상담원이었던 선배의 계약이 해지되었다. + *정말로 진심으로 곤란하고 미안하고 당신의 고통에 공감한다는 것처럼 말했지. 안 그랬더라면 좋았을 것이다. 안 그러니까. 안 그러니까 안그랬더라면 좋았을 건데.* 그는 그러지 않았지 . 재수없는 새끼 ... 고객 같은 놈... 선배가 고개를 숙이고 자기 자리로 돌아갔을 때 그녀는 그 선배의 자리에서 자기 자리까지 남은 거리를 생각하지 않을 수강 없었고 안됐다고 생각했다. 안됐다....거기까지. 그 너머는 벼랑이니까. + + +### 누구도 가본적 없는 +안장은 어디에 있을까. 세상이 아이에게서 통째로 들어낸 것, 멋대로 떼어내 자취 없이 감춰버린 것. 이제 시작이겠지, 하고 나는 생각했지... 이렇게 시작되어서 앞으로도 이 아이는 지독한 일들을 겪게 되겠지. 상처투성이가 될 것이다. 거듭 상처를 받아가며 차츰 무심하고 침착한 어른이 되어갈 것이다. 그런 생각을 했지.... + +그 밖에 내가 뭘 더 부탁한 게 있어? 그 거 챙기라고 ... 가방에 넣으라고 말하지 않았나? 그거 잊지 말라고 .. 그냥 그거 하나 ... 당신은 괜찮지 걱정이 없지 내가 다 하니까... 당신은 잘 먹고 잘 자고...어디서든 ...호텔에서든 비행기에서든...어떻게 그럴 수가 있지? 어떻게 그렇게 비위가 좋냐 그렇게 멀쩡하게 괜찮을 거라고? 당신은 어떻게 그렇게 쉬워 모든게... +그는 문득 입을 다물고 고개를 돌려 그녀를 바라보았다. 그녀가 서글픈 얼굴로 그를 보고 있었다. 그는 다시 울화가 치밀어 고개를 저었다. 그 얼굴. 지긋지긋하다고 말하는 대신, 그렇게 보지 말라고 그는 말했다. 그런 식으로 보지 마. 사람 빤히 관찰하지 마. 너는 아무 잘못 없는데 내가 때리기라도 한 것처럼 그렇게. + + +### 웃는 남자 + 나는 이해한다는 말을 신뢰하지 않는 인간이었다. 이해한다는 말은 복잡한 맥락을 무시한 채 편리하고도 단순하게 그것을, 혹은 너를 바라보고 있다는 무신경한 자백 같은 것이라고 나는 생가가하고 있었다. 나 역시 남들처럼 습관적으로 아니면 다른 마땅한 말을 찾지 못해 그 말을 할 때가 있었고 그러고 나면 낭패해 고개를 숙이곤 했다. + + 그런데 그 밤에 그가 내 등을 두드리며 너를 이해할 수 있다고 말했을 때 나는 진심으로 놀랐고 그 말에 고리를 걸듯 매달렸다. 이 사람이 나를 이해할 수 있다면 나도 해볼 수 있지 않을까. 저날의 나를 내가 이해해 볼 수 있지 않을까. 그것을 할 수 있으려면 무엇부터 하면 좋을까.내가 이제 무엇이 되는 게 좋을까. + 단순해 지자. + 가급적 단순 한 것이 되자고 나는 생각했다. + -165p- + + 디디는 부드러웠지 . 껴안고 있으면 한없이 부드러워서 나도 모르게 있는 힘껏 안아버릴 때도 있었어. 이 사람을 행복하게 해주고 싶다고 나는 생각했다. 처음으로 내가 아닌 다른 사람을 행복하게 만들고 싶다고 생각했고, 그 행복으로 나 역시 행복해질 수 있다고 생각했다. + -171p- + + + 디디는 제때 나를 발견하려고 내가 도착할 무렵엔 자주 고개를 들어야 했을 것이다. 한 줄을 읽고 고개를 들어 비탈을 바라보고. 더 행복해지자, 담배와 소변 냄새가 나는 가파른 계단을 올라가며 나는 다짐하고는 했다. 행복하다. 이것을 더 가지자. 더 행복해지자. 다른 것은 아무것도 샏ㅇ각하지 말고 그것 한 가지를 생각하자. 그런 생각을 하며 마지막 계단에 이르면 디디가 햇빛에 빨갛게 익은 얼굴을 하고 마중나와 있었다. + -176p- + + + 디디를 먹어치운 거리. 디디의 목을 부러뜨리고 머리를 터뜨린 거리. 거기엔 의미도 희망도 없어. 죽은 것이나 다름없다. 그러나 여기는 다른가. 내가 지금 머물고 있는 곳, 여기 무엇이 있나. 벌거벗은 벽이 있고 내가 있고 의자가 있고 내 잡동사니가 있다. ..... + +내가 여기 틀어박혔다는 것을 아는 이 누구인가. +아무도 나를 구하러 오지 않을 것이다. +아무도 나를 구하러 오지 않을 것이므로 나는 내 발로 걸어나가야 할 것이다. + +오랫동안 나는 그것을 생각해왔다. +-185p- + + +### 복경 +다시는 그렇게, 그 남자와 그의 누나처럼 초췌하게 그렇게, 되고 싶지 않다. 살려내고 싶어도 살릴 수 없는 사람이 죽음을 앞두고 고통으로 괴로워하는데 진통조차 해줄 수 없는 형편이라면 그 마음은 뭐가 되겠습니까. 짐슴 아니겠습니까. 짐승이 되어버린 것과 같지 않겠습니까. 그래서 나는 돈을 벌어. 그 짐승이 되지 않으려고 돈을 법니다. +-194p- + + +도게자. +이렇게 인간이 인간의 발 앞에 무릎을 꿇고 머리를 숙이는 자세를 도게자라고 해. 사람들은 이걸 사과하는 자세라고 알고 있지만 이것은 사과하는 자세가 아니다. 이것은 그 자체야. 이 자세가 보여주는 그 자체. +매장에서 난리치는 사람들은 사과를 바라는 게 아니야. 사과가 필요하다면 죄송합니다 고객님, 으로 충분하잖아? 그런데 그렇게 해도 만족하지 않지. 더 난리지. +실은 이게 필요하니까. 필요하고 바라는 것은 이 자세 자체. 어디나 그래 자기야. 모두 이것을 바란다. 꿇으라면 꿇는 존재가 있는 세계. 압도적인 우위로 인간을 내려다볼 수 있는 인간으로서의 경험. 모두가 이것을 바라니까 이것은 필요해 모두에게. 그러니까 나한테도 그게 필요해. 그게 왜 나빠? +-201p- diff --git a/_posts/cate_01_Statistics/2020-12-28-Relation_Causality.md b/_posts/cate_01_Statistics/2020-12-28-Relation_Causality.md new file mode 100644 index 00000000000..2f619b8980b --- /dev/null +++ b/_posts/cate_01_Statistics/2020-12-28-Relation_Causality.md @@ -0,0 +1,68 @@ +--- +layout: post +title: Relation & Causality +date : 28 Dec 2020 +category : Statistics +comments : true +--- + +``` + [KEY WORD] + #상관관계, #PearsonCorrelation, + #관계강도, #Spearman, + #자기상관, #autocorrelation, + #인과관계, #GrangerCausality +``` + + + +## Pearson 상관관계 +### 1) 변수 사이의 '선형' 관계 조사(pearson) +: 두 계량형 변수 사이의 선형 관계의 강도방향을 확인 + +## Spearman & Kendall 단조 상관관계 +### 1) 선형관계와 단조관계 차이 +: 앞선 pearson의 상관관계는 선형관계만을 표현 할 수 있을 뿐, 두 변수간의 관계가 곡선일 경우 Pearson의 상관관계는 이를 표현하지 못하게 되므로 관계성만을 표현해주는 Spearman 또는 Kendall의 단조관계 필요. + +### 2) Spearman & Kendall + - 변수값 대신 순위로 바꿔서 용하는 상관계수(학교 등급, 졸업 학위) + - 비모수 검정 + - Spearman : 데이터 내 편차와 애러에 민감하며, 일반적으로 켄달의 상관계수보다 높은 값을 가짐. + - Kendall : 샘플 사이즈가 적거나, 데이터의 동률이 많을 때 유용 + + +
+ + + +선형관계라면 단조관계이지만, +단조관계라고 선형관계는 아니다. + +
+ + + +## 자기상관(autocorrelation) + 자기 회귀 +### 1) 자기상관(autocorrelation) +: 시간 또는 공간적으로 연속된 일련의 관측치들간에 존재하는 상관관계로, 현재의 상태가 과거와 미래의 상태에 밀접한 연관을 지니는 경우. + +### 2) 자기회귀(autoregression) +: 회귀분석에서 시계열의 관측값이 선행된 관측값에 의존하여 상관관계를 보일 때, 즉 관측값이 선행관측값들의 회귀관계를 갖는 현상을 자기회귀 (autoregression)이라 한다. +자기 회귀 현상이 발생하면, OLS방식에 의하여 추정된 회귀계수가 비록 불편성(편향이 발생하지 않은)을 만족할지라도 최적합치일 수 없다. 또한 자기회귀가 발생하는 경우, 일반적으로 t값과 f값 및 $R^2$값이 실제보다 증가하는 경향이 있음. + + [자기상관(autocorrelation)](https://m.blog.naver.com/PostView.nhn?blogId=nlboman&logNo=23353211&proxyReferer=https:%2F%2Fwww.google.com%2F) + + + + + +# 인과 관계 + : A와 B사이의 '원인' - '결과' 분석을 하고 싶다면, '회귀분석' 또는 'GrangerCausality' 분석 진행 + + + +#### Reference +[1] [자기상관(autocorrelation)](https://m.blog.naver.com/PostView.nhn?blogId=nlboman&logNo=23353211&proxyReferer=https:%2F%2Fwww.google.com%2F) +[2] [상관관계 분석(correlation analysis)](https://m.blog.naver.com/istech7/50153047118) +[3] [공분산과 상관관계(covariance_correlation)](http://elearning.kocw.net/contents4/document/lec/2013/konkuk/leegiseong/3.pdf) +[4] [인과관계_elearning(GrangerCausality)](http://elearning.kocw.net/contents4/document/lec/2013/Konkuk/Leegiseong/10.pdf) diff --git a/_posts/cate_01_Statistics/2022-01-25-Probability_Sampling.md b/_posts/cate_01_Statistics/2022-01-25-Probability_Sampling.md new file mode 100644 index 00000000000..f871d04dba1 --- /dev/null +++ b/_posts/cate_01_Statistics/2022-01-25-Probability_Sampling.md @@ -0,0 +1,46 @@ +--- +layout: post +title: 설문데이터 활용하기1 - 확률적 표본 추출(Probability Sampling) +date : 25 Jan 2022 +category : Statistics +comments : true +--- + +``` + [KEY WORD] + #설문조사, #확률, #통계, #확률적 표본 추출 +``` + +설문데이터 활용에 앞서서, 해당 설문 자체가 얼만큼 모집단을 대표할 수 있는가를 알기 위해서는 설문 대상이 "확률적 표본 추출"을 따랐는지 확인해보아야한다. +이에 "확률적 표본 추출"이 구체적으로 무엇을 뜻하는지 살펴보자. + +## 확률적 표본추출 +: 큰 모집단으로부터 작은 샘플그룹을 랜덤하게 선택하는 통계 방법으로, 샘플의 응답이 모집단의 경향성을 대표. 이때 모집단을 대표하기 위해서는 2가지 중요한 조건이 필요. + +### 1) Non-Zero chance of being selected +: 모든 모집단의 유저가 뽑힐 확률이 있어야 함 (체계적으로 설문을 수행할 수 없는 사용자가 존재해서는 안됨) + - ex) 특정 언어로만 작성되어, 이외 언어사용자는 설문참여가 불가능한 경우 + - ex) 설문 진행 시점이, 특정 행동 수행 이후로 한정됨(의도적으로 특정 유저만을 설문하는 경우라면 가능) + +### 2) Know the chance of being selected for each person +: 구체적으로 뽑힐 확률이 각자에게 얼마나 되는지 알아야함. 이때 모집단의 특성을 반영하기 위해 적절한 전략을 선택. + +#### (1) 단순 무작위 표집 (Simple random sampling) +: 추출은 무작위로 진행되며, 모든 유저가 동일한 추출확률을 갖음. + - 장점 : 쉬움. + - 단점 : 표본이 모집단에 비해 작을 시, bias가 발생할 확률이 높아져 신뢰도가 낮아짐. + +#### (2) 층화 표집 (Stratified sampling) +: 모집단을 서로 배타적이며, 모두 합쳤때 전체가 되는 집단으로 나누고, 각 집단별로 추출될 확률을 서로 다르게 부여함. (ex. by gender, age, ethnicity, etc) + - 장점 : 모든 층화에서 설계된 확률만큼 무작위로 표본추출된다면, 모집단을 대표할 수 있음 + +#### (3) Cluster sampling +: 서로다른 클러스터(ex. 지역)을 임의로 선택한 다음, 선택한 클러스터의 일부 또는 모든 구성원을 조사함 + - 장점 : 시간 & 비용 절감 + + + + + +#### Reference +[1] [확률적표본추출](https://ko.surveymonkey.com/mp/probability-sampling/) diff --git a/_posts/cate_01_Statistics/2022-01-26-ConfidenceLevel_MarginError.md b/_posts/cate_01_Statistics/2022-01-26-ConfidenceLevel_MarginError.md new file mode 100644 index 00000000000..77687518f78 --- /dev/null +++ b/_posts/cate_01_Statistics/2022-01-26-ConfidenceLevel_MarginError.md @@ -0,0 +1,225 @@ +--- +layout: post +title: 설문데이터 활용하기2 - 신뢰수준과 표본오차 +date : 25 Jan 2022 +category : Statistics +comments : true +--- + +``` + [KEY WORD] + #설문조사, #확률, #통계, #신뢰구간, #표본오차 +``` + + 설문 표본이 실제 모집단의 특성을 왜곡하지 않고 무작위 또는 층화 표집으로 추출되었더라도, 너무 적은 표본은 편향 및 오차를 포함할 수 있다. + 따라서 통상 95% 신뢰수준하에서, 표본의 크기에 따른 표본 오차가 얼마나 발생하는지 측정하여야 설문 결과로 얻은 값이 우연의 일치인지, 아니면 통계적으로 유의미한 차이인지 확인할 수 있다. + +------------------ +## 1. 일반 관점, 신뢰수준과 표본오차 +: 아래와 같은 여론조사가 있다고 할때, '신뢰수준'과 '표본오차'는 무엇일까. +``` +1000명을 대상으로 조사한 결과, 38%는 A후보, 26%는 B후보, 24%는 C후보를 지지한다고 응답하였다. (95% 신뢰수준에 표본오차 ±3%) +``` + +### 1) 신뢰수준 95% + : 동일 조사 100번 수행시, 오차범위내 동일한 결과가 나올 횟수가 95번. + +### 2) 표본오차 (신뢰수준 95%일 때) + : 동일 조사 100번 수행시, 95번은 오차가 ±3% 포인트 안에 있음. + - (1) 모집단 또는 표본의 표준편차를 알 때 : $\epsilon$ = $z \times \sqrt{\sigma^2\over n}$ + - (2) 모집단 또는 표본의 표준편차를 모를 때 : $\epsilon$ = $z \times \sqrt{p(1-p)\over n}$ + - (3) 모집단 또는 표본의 표준편차를 모르며, 모집단이 충분히 크지 않을 경우 : $\epsilon$ = $z \times \sqrt{p(1-p)(N-n)\over n((N-1))}$ + * p : 특정 결과 발생 확률 (0.5가 가장 불확실성이 높기에, 표본 오차를 극대화 하기 위해선 0.5로 통상 설정) + * n : 표본 크기(Sample Size) + * N : 모집단(Population) + + +### 3) 해석 + - A후보는 B,C 오차범위 밖에서 큰 차이로 앞선다. + → 95% 신뢰수준으로, A가 B,C보다 높다고 할 수 있다. + - B와 C 후보는 오차범위 내에 있다. + → 95% 신뢰수준으로, B가 C보다 높다고 할 수 없다. + + +------------------ + +## 2. 통계 관점, 신뢰수준과 표본오차 + * https://kuduz.tistory.com/1220 게시글 '오차범위(표본오차)란 무엇인가를 공부한 글입니다.' + +### 1) 이항분포 (동전던지기) +#### (1) 2회 시행시, 앞면(H)이 N번 나올 확률 분포 + - H, 0회 확률 : 1/4 [T,T] + - H, 1회 확률 : 2/4 [T,H], [H,T] + - H, 2회 확률 : 1/4 [H,H] + +#### (2) 3회 시행시, 앞면(H)이 N번 나올 확률 분포 + - H, 0회 확률 : 1/8 [T,T,T] + - H, 1회 확률 : 3/8 [T,T,H], [T,H,T], [H,T,T] + - H, 2회 확률 : 3/8 [T,H,H], [H,T,H], [H,H,T] + - H, 3회 확률 : 1/8 [H,H,H] + +#### (3) 100회 시행시, 앞면(H)이 N번 나올 확률 분포 +
+ +
+ + - 100번 던질 때, 앞면이 49~51회 나올 확률 : 23.6% (7.8% + 8% + 7.8%) + - 100번 던질 때, 앞면이 40~60회 나올 확률 : 95.4% + 무려 95%의 확률이 가운데 20회의 경우에 발생한다...!?!? 정규분포의 형태를 띄어감! +
+ + "이항분포의 정규근사" + 시행 횟수가 많을수록 그리고 확률이 1/2에 가까울 수록, + 이항분포는 정규분포에 가까워진다. +
+ +### 2) 정규분포 + : 앞서 동전던지기를 통해, 이항분포가 정규분포를 띄고 있음을 보았다. 따라서 정규분포의 특징을 정리하면 아래와 같다. + - 평균이 가장 볼록하고, 평균에서 멀어질 수록 높이가 낮아지는 분포 + - 평균($\mu$) & 표준편차($\sigma$)에 따라 모양이 변함 +
+ +
+ +### 3) "표준"정규분포 + : 위 정규분포는 평균과 표준편차에 따라서, 모두 모양이 제각각이다보니, 특정 확률(ex.95%)를 규정하려면 정규분포마다 서로 다른 표준편차값이 설정될 것이다. + → 때문에 정규분포에서 평균을 빼고, 표준편차로 나눠 ($Z$ = $(X - \mu)\over\sigma$) 평균이 0이고, 표준편차가 1인 '표준'정규분포로 변환하여 규격화해보자. + - 평균($\mu$) : 0 + - 표준편차($\sigma$) : 1 + +
+ +
+ + + +### 4) 신뢰구간(confidence_interval) +: 이렇게 '표준정규분포'를 얻었고, 우리는 대략 2표준편차, 정확히는 $\pm$1.96$\sigma$ 안에 전체 사례의 95%가 포함됨을 앞서 동전사례를 통해 알고 있습니다. +따라서 95% 신뢰구간이라하면 +1.96$\sigma$ ~ +1.96$\sigma$로 표현 하며, 오차범위 & 표본오차라고도 부릅니다. + + +### 5) 신뢰수준(confidence_level) +: 그렇다면 '신뢰수준'의 의미는 무엇일까. + - 평균이 0, 표준편차가 1인 (표준)정규분포를 따르는 모집단이 있을 때, + - 샘플(표본) 50개를 뽑고, 이 샘플의 평균과 표준편차를 계산하면, + - 각 샘플의 신뢰구간 100개 가운데, 95개(95%)는 샘플의 신뢰구간안에 모집단의 평균(0)이 위치할 것이라는 것.(물론 정확히 95%는 아니겠지만 95%에 수렴) + - 즉, 신뢰수준 95%는 100번 조사했을 때, 95번은 모집단의 값을 예측할 수 있지만, 5번 정도는 틀릴 수 있다는 뜻이 됩니다. + + +### 6) 샘플(표본)로 모집단 유추하기 +: 앞서 신뢰수준을 이야기할 때, 우리는 모집단의 평균(모평균)이 0이라고 가정했기에, 표본 95개의 신뢰구간안에 모평균이 위치함을 알 수 있었습니다. 그러나 현실 및 여론조사에서 모집단의 평균을 알 수 없습니다. 이럴 때는 어떻게 신뢰수준 95%를 확인 할 수 있을까요. +샘플을 활용하여, 모집단의 평균을 추정할 수 있는지 확인해 봅시다. + +#### (a) 모집단 + - 모집단 : [1,2,3] + - 모평균($\mu$) : 2 + - 모분산($\sigma^2$) : $2\over3$ = ( $(1-2)^2 + (2-2)^2 + (3-2)^2)\over3$ ) + - 모표준편차($\sigma$) : $\sqrt{2\over3}$ + +#### (b) 표본 +: 2개의 샘플을 추출(반복추출 허용)할 때 모든 경우의 수는 아래 테이블과 같음. + +|표집|표본 평균|오차(표본평균 - 모평균)|오차 제곱| +|:-:|:-:|:-:|:-:| +|[1,1]| 1 | 1 | 1 | +|[1,2]| 1.5 | 0.5 | 0.25 | +|[1,3]| 2 | 0 | 0 | +|[2,1]| 1.5 | 0.5 | 0.25 | +|[2,2]| 2 | 0 | 0 | +|[2,3]| 2.5 | -0.5 | 0.25 | +|[3,1]| 2 | 0 | 0 | +|[3,2]|2.5 | -0.5 | 0.25 | +|[3,3]| 3 | -1 | 1 | +|평균| 2 | 0 | $1\over3$ | + + - 표본 평균의 평균($\bar{X}$) : 2 + - 표본 분산($S^2$) : $1\over3$ + - 표본 표준편차 -> 표준오차($S$) : $\sqrt{1\over3}$ + +#### (c) 표본평균과 모집단의 관계 + : 우리는 표본평균으로부터 위와 같은 통계치들을 얻을 때, 아래와 같은 사실을 확인 할 수 있습니다. + + - 표본평균의 평균은 모평균과 같다. → [$\bar{x} = \mu$] + - 표본평균의 오차 제곱의 평균 즉 분산은, 모분산을 표본의 크기로 나눈값과 같다. → [$S^2$ = $\sigma^2\over n$] + - 표본평균의 표준편차(= 표준오차) → [$S$ = $\sqrt{\sigma^2\over n}$] + +
"이는 즉 표본의 평균과 분산을 알면,
+모집단의 평균과 분산도 알 수 있다는 이야기!"
+ +#### (d) 모분산을 모른다면? + 특정 관측치가 나타날 확률을 p라고 할 때, + 기댓값($E(X)$) = 관측값 x 발생확률 = "n X p"라고 표현 할 수 있습니다. + + 그렇다면 다시 동전으로 돌아가 + 앞면에 1, 뒷면을 0에 값으로 부여 할때, 각면의 발생 확률(p) = $1\over2$입니다. + + 1) 따라서 기댓값은 아래와 같이 쓸 수 있고, +
+ + 기댓값($E(X)$) = $1\over2$ = 0 $\times$ $1\over2$ + 1 $\times$ $1\over2$ +
+ + 2) 분산은 편차의 제곱에 평균이기에, 편차의 제곱값에 각 편차의 발생확률을 곱해준것과 같습니다. +
+ + 분산($\sigma^2$) = $\left( 0 - \frac{1}{2} \right)^2 \times \frac{1}{2}$ + $\left( 1 - \frac{1}{2} \right)^2 \times \left(1 - \frac{1}{2}\right)$ +
+ + 3) 위 식을 일반화 시키면 아래와 같습니다. +
+ + $\begin{matrix} + \sigma^2 &=& (1-p)^2 \times p + (0-p)^2 \times (1-p) \\ + &=& p(1-p) + \end{matrix}$ +
+ + 4) 앞서 표본의 표준편차(표준오차)($S$)은 아래 공식과 같았습니다. +
+ + $S$ = $\sqrt{\sigma^2\over n}$ +
+ + 5) 위 표준오차의 분산($\sigma^2$)자리에, 위에서 찾은 `발생확률 p로 계산한 분산`을 대입하면 아래와 같습니다. +
+ + $S$ = $\sqrt{p(1-p)\over n}$ +
+ + 6) 자 이제, 모집단의 분산을 모르더라도 표준오차를 계산할 수 있게되었습니다. + 1표준오차가 위 공식과 같을 때, 우리는 앞서 95% 신뢰수준하에서 표준오차의 범위(오차범위[$\epsilon$])를 알고 싶습니다. + 양측으로 2표준편차(정확히 1.96표준편차)에서 95%의 값을 포함하고 있기에, 표준오차 공식에 1.96이라는 z-score를 곱해줍니다. + (2표준편차라고 이야기할 때 '2'가 z-score이며, 95%는 1.96이됩니다.) +
+ + $\epsilon$ = $z \times \sqrt{p(1-p)\over n}$ +
+ +### 7) 표준오차를 활용하여, 실제 통계치 비교하기 +: 이제 설문조사 결과를, 표준오차를 활용한 신뢰구간의 범위로 확장하여 다시 살펴보겠습니다. +- 표본 오차 3.1%포인트일때, 긍정평가 49%의 신뢰구간 = 45.9% ~ 52.1% +- 표본 오차 3.1%포인트일때, 부정평가 45%의 신뢰구간 = 41.9% ~ 48.1% +$\therefore$ 두 응답의 오차범위가 서로 중첩되기에, 긍정평가가 더 높다는 설문결과는 95%신뢰수준을 만족하지 못하고 결과가 뒤집힐 수 있습니다. + +
+ +
+ + +- 표본 오차 3.1%포인트일때, 긍정평가 49%의 신뢰구간 = 45.9% ~ 52.1% +- 표본 오차 3.1%포인트일때, 부정평가 41%의 신뢰구간 = 37.9% ~ 44.1% +$\therefore$ 두 응답의 오차범위가 서로 벗어나 있기에, 긍정평가가 더 높다는 설문결과는 신뢰도 95% 기준으로 차이가 있다고 할 수 있습니다. +
+ +
+ +
+"표본오차보다 작은 변동에 대한 의미 부여는,
+해설이 아니라 소설이다." +
+ + +### Reference +[1] [오차범위(표본오차)란 무엇인가?](https://kuduz.tistory.com/1220) +[2] [표준오차, 표본오차, 오차한계 개념 구분](https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=jieun0441&logNo=220908395420) +[3] [Standard Normal Distribution, Standard Gaussian Distribution](http://www.ktword.co.kr/test/view/view.php?m_temp1=1995) diff --git a/_posts/cate_02_ML/recommend/2020-07-18-recommend-AIRS_recommend_modeling.md b/_posts/cate_02_ML/recommend/2020-07-18-recommend-AIRS_recommend_modeling.md new file mode 100644 index 00000000000..243935e0be3 --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-07-18-recommend-AIRS_recommend_modeling.md @@ -0,0 +1,194 @@ +--- +layout: post +title: Recommend AIRS 모델링 & 시스템 +date : 18 Jul 2020 +category : ML +comments : true +--- + +: 자세한 추천 시스템 공부에 앞서, 네이버 뉴스 추천 시스템인 AIRS개발과정을 토대로, 추천시스템의 주요 골자와 현황, 예상되는 문제점등을 살펴보자. + +## 1. 추천 모델링이란? +### 1-1) 추천 모델링 정의 + : 특정 '시점'에 유저가 '좋아할' 만한 아이템의 리스트를 찾는 것 + - 추천 모델링 [유저(나이 / 성별)정보 + 로그(관람 이력) 데이터 + 아이템(영화) 정보]
+ 특정 영화할 좋아할 만한 사람 & 그 사람이 영화를 보고 싶은 시점 + +### 1-2) 추천 모델링 고려사항 +- 유저수(관객수) +- 아이템 수 +: 추천해야 하는 아이템(영화)의 수
+ (1) 과거 영화 → 학습의 목표
+ (2) 신규 영화 → 최종 목표 +- 업데이트 양 / 주기 +: 새로운 아이템(영화)이 출시되는 양과 주기 +- 모델 복잡도 +- 시스템 성능 +: 모델 복잡도와 시스템 성능간의 trade-off관계(우도할거) + +### 1-3) 추천 모델링 난제 +- **Sparsity Problem** +: 유저와 아이템 개수가 급증할 수록, + ***유저가 실제 소비한 아이템의 비율은 점점 줄어듦***
+→ 추천 피드백 정보가 희박해짐
+→ 영화 데이터의 경우, 유저가 실제 소비한 아이템이 더욱 적어 현재 Sparsitiy Problem이 가장 크게 우려됨. + +### 1-4) 추천 모델링 프로세스 +1. log 분석 +2. 모델 선정 +3. 모델 학습 +4. 품질 평가 +5. A\|B 테스트 +6. 서비스 적용
+→ 위 단계가 Loop를 돌며 반복됨 + +--- + +## 2. 추천 모델의 종류 + Q. 유저가 좋아할 만한 아이템의 정의가 뭐지?
+ A. 추천 모델마다 정의가 달라진다. +- Statistics Based +- Collaborative Filtering +- Deep Learning + +→ 이는 추천 알고리즘이라고 해서, 무조건 협업필터링이 좋은 것이 아니라, 적용하려는 서비스에 가장 잘 어울리는 '좋아할 만한'의 의미 그리고, 시스템 부하값 등을 고려해서 모델을 선택하는 과정이 우선적으로 필요.
+ + +### 2-1) Statistics Based +"좋아할 만한 = ***통계적으로 유의미한*** 아이템" +- **Chi-squared (category)** + $ : X^2 = sum{(x_i - m_i)^2/m_i}$ + - 원래 모집단과 표본이 있을 때, 모집단과 표본이 얼만큼 다른가를 검증하는 방법. + - 유저가 소비한 아이템의 예측치(m_i)와 실제로 소비한 관측치(x_i)의 차이를 이용 + - 절대적인 값보다는 상대적인 변화량에 주목해 하나의 새로운 feature로 활용 + + +- **Cross-Entropy & KL-divergence (Continuous Variable)** + $: H(p,q) = - \sum_{k=1}^N p(x)log q(x)$ + - p(x) : 관측치 , q(x) : 예측치 + - KLD : 두개의 분포(p&q)가 있을 때, p분포가 q분포로 얼만큼 설명될 수 있는가(=분포의 차이가 얼만큼 큰가). + → 정보 손실량을 측정하기 위한 방법
+ +ML) 관측 엔트로피 = 학습(train set)의 엔트로피 —> 모델 구축시 모델의 하이퍼 파라미터를 결정할 때, 관측 데이터의 엔트로피는 필요없음(모델이 얼마나 더 좋은지를 알기 위해서는 예측분포와 관측분포간 차이만 알면 되기에 그래서 보통 관측엔트로피를 뺀부분만 loss function으로 사용하게 됨. + +RC) 그러나 추천 모델에선 예측 분포와 관측 분포간 얼마나 차이가 나는가에 따라, 차이가 난다는 것은 의외성이 있는 추천을 해줄 수 도 있음을 의미함 + +--- + +### 2-2) Collaborative Filtering + +"좋아할 만한 = 나와 ***비슷한*** 유저가 좋아한 아이템" + +### (1) Neighborhood models + : 유저-유저 / 아이템-아이템 간의 similarity(유사도) 계산 +- **User-based** : 함께 본 문서 수 +- **Item-based** : 함께 본 유저 수 +: but User-based & Item-based 둘다 유사도 계산 과정에서 반대편 정보를 압축하는 과정이 발생하기에 정보 손실이 발생 + +- 유사도 측정 방법 + - **Cosi ne Similarity** + \: 벡터의 내적 + - **Jaccard Index** + \: 교집합 + - **PMI(pointwise Mutual Information)** + \: 함께 발생한 빈도와 함께 각 이벤트가 발생할 확률을 함께 고려한 정보량(빈도만 고려하는 앞서 두 방법보다, 확률을 고려하기에 더 좋은 성능) + +### (2) Matrix Factorization Models +: 유저와 아이템간의 상호작용 데이터를 기반으로 은닉인자를 찾아냄 +→ item-vector와 user-vector간 내적으로 계산 +- **Prediction** + $ \hat{r}_{ui} = x_u^T \cdot y_i $ + + + +- **Loss function** + $L = \sum(r_{ui} - x_u^T \cdot y_i)^2 +( \lambda_x\sum_u ||x_u||^2 +\lambda_x\sum_u ||y_i||^2) $ + 오차 = (관측치 - 예측치) + (L2 regularization) + +- **Limitations** + - 계산량이 많고 학습 속도가 느림 + - missing data를 negative 샘플로 사용하기에 + +- **wALS** +: 계산량 및 학습 속도 문제 해결을 위해 한쪽의 파라미터를 고정하고 반대편 파라미터를 추정하는 방법 +→ 이때도, 위에서 언급한 *missing data를 어떻게 튜닝할 것인가에 따라 성능이 달라진다.* +--- + +## **2-3) Deep Learning** +"좋아할 만한 = 나와 *컨텍스트 벡터* 와 가까운 아이템을 찾는 것" + \: 유저와 아이템이 벡터로 표현될 수 있을 때, 인공신경망을 통해 유저-아이템 관계 추론 + - \+Non Linear Models..!! + +### (1) RNN +: 유저의 문서 소비 패턴을 보고 추천 + 1. 신규 뉴스의 경우 유저 로그가 없는 상태임 + 2. RNN을 통해 학습된 유저 임베딩 정보를 활용 + 3. 유저-문서간 벡터연산을 통해 뉴스를 추천 +(→ 신규 영화 개봉작 역시 유저로그가 없음) +![RNN 도식화](/assets/RNN_process.png) + +### (2) CNN + +: 문서내 단어들의 배열을 보고 주제를 추론 + +### (3) Deep CF Models + +: Deep Learning과 CF를 함께 고려하는 방법 +![Deep CF model 도식화](/assets/Deep_CF.png) + +--- +### **2-4) 추천 모델 특징 비교** + +1. **Statistics Based** + - chi-squared : Categorical + - KL-Divergence : Continuous + + → 통계&확률 + +2. **Collaborative Filtering** + - Neighborhood : Similarity(PMI) + - Matrix Factorization : Missing Data issue + + → 선형과 비선형 + +3. **Deep Learning** + - RNN / CNN : Non-linearity + - Deep CF : Neural Network +--- + +## 3. 추천 품질 평가 요소 +### 1) 추천의 만족도 +- Accuracy : 유저가 실제 소비한 아이템이 상위에 추천되는지 → 추천 모델의 성능 +- Diversity : 다양한 주제/유형의 아이템이 잘 추천되는지 +- Novelty : 새로 나온 최신의 아이템이 잘 추천되는지 + +### 2) 추천 모델 평가 방법 +- 오프라인 정량평가 +- low cost +- 전체 모델간 비교 +- 유저 관심사 고정 +→ But 현실에서 실제 추천된 결과가 좋은 성능을 유지할 지 알 수 없음 +- 온라인 A/B 테스트 +- High Cost +- 특정 모델간 비교 평가 가능 +- 유저 관심사 변화 +→ 실서비스 적용 여부 결정가능 + +### 3) 추천 모델 평가 방법 +- 추천모델 정확도 평가 지표 + - precision / **Recall@N** + : 추천의 경우 정해진 정답이 없는 경우도 많기에 하나의 정답값만을 확인하는 precision보다는 + 총 정답 문서중에, 모델이 얼만큼의 정답 문서를 찾아주는가를 확인하는 Recall을 주로 사용 + - F-score / **AUROC** + : Recall이 임계치에따라 얼마나 robust하게 결과를 내는지 확인하기 위해 AUROC사용 + - **nDCG / MRR (normalized Discouted cumulative Gain / Mean Reciprocal Rank)** + : 상위에 얼마나 정답값이 랭크가 되는지를 점수화하는 방법 +*→ 모델 평가시 위의 방법론 활용* +- 실서비스 만족도 평가지표 +- 유저별 클릭수 +- 유저별 총 체류시간 +- 신규 아이템 회전율 +*→ A/B Test 실행시 평가지표로 고민해 보면 좋을 듯* + +#### Reference +[1] https://www.youtube.com/watch?v=oTuM8WDI3nA diff --git a/_posts/cate_02_ML/recommend/2020-07-24-recommend-1_intro.md b/_posts/cate_02_ML/recommend/2020-07-24-recommend-1_intro.md new file mode 100644 index 00000000000..d0e8a839aec --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-07-24-recommend-1_intro.md @@ -0,0 +1,62 @@ +--- +layout: post +title: Recommend 1_Intro +date : 24 Jul 2020 +category : ML +comments : true +--- + +# 1. 추천 알고리즘 종류 +**1) Contents Based Filtering** + \: 유저 및 아이템의 정보를 기반해 추천해주는 방식으로, 유저(또는 아이템)의 나이, 성별 등을 토대로 유사한 유저를 찾고 해당 유저의 관람 이력을 추천해준다. 이때 유사도를 확인하기 위해 코사인 유사도, 자카드 유사도등을 활용할 수 있다. + +**2) Collaborative Filtering** + \: 실제 행동을 기반으로 추천하는 모델로, 컨텐츠 베이스보다 높은 성능을 보인다. + 그러나 행동 데이터가 축적되기전에는 정확도가 떨어진다는 "cold-start" 문제를 갖고 있다. + - **최근접 이웃 기반(nearest neighbor based collaborative filtering)** + - **잠재요인 협업 필터링 (latent factor based collaborative filtering) - SVD** + +※ Deep Learning을 활용한 방식이 최근 핫하지만, 여기선 기초적인 추천시스템 내용의 정리를 위해 배제하였다. + + --- +#### \<데이터 종류\> +*Explict Data* + - 평점등 선호와 비선호가 명확하게 구분 + - 아직 평점을 매기지 않은 데이터는 활용불가 + +*Impolicit Data* + - 선호와 비선호 구분없이 행동의 빈도수만 기록 + - 모든 데이터를 사용하여 분석 가능 + --- + +

+# 2. Contents Based Filtering +
+ + : 위 그림 처럼 예를들어 '장르'라는 변수를 활용해 비슷한 영화를 묶고, 동일한 장르내에서 유사한 영화를 추천해줄 수 있다. + +

+# 3. Collaborative Filtering + +## 3-1. Neighborhood CF Model +: 주어진 평점 데이터를 가지고 서로 비슷한 유저 혹은 아이템 찾기
 +
+ + - pearson correlation : 1에 가까울 수록 유사한 선호
 + - ‘User-oriented Neighborhood’ & ‘Item-oriendted Negiborhood’ +
 - 양/음의 관계를 계산하기에 선호와 비선호가 구분되어 있는 Explicit Dataset에 적합 + + + +## 3-2. latent factor based CF Model(feat.SVD) +### 잠재요인 협업 필터링 + : 주어진 사용자 평점(또는 관람) 데이터를 잠재요인을 기준으로 '사용자 정보 행렬'과 '아이템 정보 행렬'로 분해하여 각각의 행렬을 사용해 사용자간 유사도와 아이템간 유사도를 계산할 수 있다. 또한 두 행렬을 다시 내적하여 이전에 사용자가 선호를 남기지 않은 항목에 대해서도 예측값을 제공해 줄 수있다. +
+ - U('사용자-잠재요인') & Sigma(잠재요인) & vT('아이템-잠재요인') + + + + +#### Reference +[1] https://dc7303.github.io/python/2019/08/06/python-memory/
+[2] https://yeomko.tistory.com/6?category=805638 diff --git a/_posts/cate_02_ML/recommend/2020-07-25-recommend-2_latent_factor_CF.md b/_posts/cate_02_ML/recommend/2020-07-25-recommend-2_latent_factor_CF.md new file mode 100644 index 00000000000..84ffc6c383a --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-07-25-recommend-2_latent_factor_CF.md @@ -0,0 +1,197 @@ +--- +layout: post +title: Recommend 2_Latent Factor CF(feat. SVD) +date : 25 Jul 2020 +category : ML +comments : true +--- + +: Latent Factor Based Collaborative Filtering은 행렬 분해(Matrix Facotrization)에 기반한 알고리즘으로, +사용자 행렬과 아이템 행렬을 각각 잠재요인 기준으로 생성한 후 이를 다시 내적하여 사용자가 아직 선호를 나타내지 않은 아이템에 대해서도 선호를 예측 + + +## Basic Concept +#### 1. 행렬 분해 + : 행렬 분해는 주어진 사용자-아이템 행렬을 '사용자-잠재요인'행렬 , '아이템-잠재요인' 행렬로 분해. + 여기서 우리가 설정하게 되는 '잠재요인'이란, '영화'를 분류하는데 있어서 액션/로맨스/코미디 등과같이 서로 다른 '장르'라고 대략적으로 생각. +
+ + +
+ + - $U$ (사용자-잠재요인) : 사용자별 어떤 장르(잠재요인) 선호를 갖고 있는지 분해 + - $\sum$ (잠재요인) + - $V^T$ (아이템-잠재요인) : 영화별 어떤 장르(잠재요인) 성격을 갖고 있는지 분해 + + +
+#### 2. 행렬 결합 +
+ + + 앞선 분해된 행렬을 다시 내적으로 곱해주면, + 초기 '사용자-아이템'과 유사한 원본행렬이 생성되면서, + 기존에 관람(평가)하지 않았던 아이템에 대해서도 점주를 매길 수 있게 됩니다. + + + +
+ + + +# 2. 구현하기 +```python +from sklearn.decomposition import TruncatedSVD +from scipy.sparse.linalg import svds + +import matplotlib.pyplot as plt +import seaborn as sns +import pandas as pd +import numpy as np +import warnings +warnings.filterwarnings("ignore") +``` +피봇 테이블을 이용해, 영화명이 컬럼으로 들어가 있는 데이터 프레임 생성한다. + +```python +# Data Import +# src : https://www.kaggle.com/sengzhaotoo/movielens-small +rating_data = pd.read_csv('./datas/movie_lens/ratings.csv') +movie_data = pd.read_csv('./datas/movie_lens/movies.csv') + +# preprocess +rating_data.drop('timestamp', axis = 1, inplace = True) +movie_data.drop('genres', axis = 1, inplace = True) +user_movie_data = pd.merge(rating_data, movie_data, on = 'movieId') +user_movie_rating = user_movie_data.pivot_table('rating', index = 'userId', columns='title').fillna(0) +``` + +우선, 영화간 유사도를 계산하여 특정 영화를 입력할 때, 해당 영화와 유사한 영화를 추출해내는 모델을 만들어 보자. 영화간 유사도를 계산하기 위해, 사용자 기준이었던 행렬을 영화중심으로 변환해준다. +- input : item +- output : similar item + + +## 1) 유사 영화 추천 +```python +# 영화-사용자 행렬 생성 +movie_user_rating = user_movie_rating.values.T # 영화 - 사용자 행렬 +``` + +### (1) 행렬 분해 & 결합 +영화 기준의 행렬을 TruncatedSVD 함수를 행렬분해를 진행하였다. +일반 SVD의 결과는 원본 행렬과 동일한 shape을 갖춰야 하지만, TruncatedSVD는 행렬곱의 결과를 시그마 행렬의 특이값 가운데 상위 n개만으로 압축해서 출력해준다. 이로 인해 정보량의 손실이 발생하기는 하지만, 거의 유사한 행렬을 얻으면서 메모리를 절약할 수 있다. +(결과 행렬은 0이 거의 존재하지 않는 Dense Matrix이기에 영화간 유사도만을 계산하기 위한 행렬에 굳이 사용자의 모든 선호를 출력해주는 컬럼을 유지할 필요가 없지 않았을까 한다.) +```python +# 행렬 분해 +SVD = TruncatedSVD(n_components=12) +matrix = SVD.fit_transform(movie_user_rating) +matrix.shape # 9064 x 12 +``` + + +### (2) 상관계수 계산 +```python +# 상관계수 계산 +corr = np.corrcoef(matrix) +corr.shape # (9064 * 9064) + +# Matrix index에 영화명 연결 +movie_title = user_movie_rating.columns +movie_title_list = list(movie_title) + +# 유사 영화 출력 +movie_name = "Guardians of the Galaxy (2014)" +coffey_hands = movie_title_list.index(movie_name) +corr_coffey_hands = corr[coffey_hands] +list(movie_title[(corr_coffey_hands >= 0.9)])[:50] +``` + + + +## 2) 사용자 개인 추천 +위에서 영화간 유사도 통해 유사한 아이템을 확인해 보았으나, 실제 개인화 추천모델이라면 사용자를 input값으로 넣었을 때, 사용자에게 적합한 아이템 리스트가 output으로 출력되는 형태가 좀더 자연스러울 것이다. 그렇기에 이번엔 사용자 사용자 개인을 기준으로한 matrx 활용해보자. + - input : user_id + - output : item + +```python +# 사용자-영화 행렬 +user_movie_rating.head() +``` +이때 각 사용자별 사용자 평점을 빼주는 작업은 사용자 별 평점을 주는 정도가 다름을 반영하기 위함이다. 누군가는 굉장히 재미있게 본 영화도 3점을 주는 반면 누군가는 5점을 주는 등 개인의 선호가 다르기에 이를 개인화 시켜주기 위해 평균을 빼준다.(평점 데이터가 아닌, 단순 관람 데이터인 경우 필요치 않음) +```python +matrix = df_user_movie_ratings.as_matrix() # matrix는 pivot_table 값을 numpy matrix로 만든 것 +user_ratings_mean = np.mean(matrix, axis = 1)# user_ratings_mean은 사용자의 평균 평점 +matrix_user_mean = matrix - user_ratings_mean.reshape(-1, 1) # R_user_mean : 사용자-영화에 대해 사용자 평균 평점을 뺀 것. +``` + + +### (1) 행렬 분해 +TruncatedSVD함수와는 달리, scipy패키지에서 제공해주는 svds함수는 Output으로 분해된 3개의 행렬을 그대로 출력해준다. +```python +#scipy에서 제공해주는 svd. +# U 행렬, sigma 행렬, V 전치 행렬을 반환. +U, sigma, Vt = svds(matrix_user_mean, k = 12) + +print(U.shape) +print(sigma.shape) +print(Vt.shape) + +#(671, 12) +#(12,) +#(12, 9066) + +# 이때 sigma 행렬은 현재 1차원 행렬로 되어있기에, 0을 포함한 대각행렬로 만들어줌 +sigma = np.diag(sigma) +sigma.shape +``` + + + +### (2) 행렬 결합 +위 행렬을 내적하는 과정에서, TruncatedSVD와 달리 모든 컬럼을 그대로 출력해주기에 메모리 이슈에 주의해야 한다. +```python +# U, Sigma, Vt의 내적을 수행하면, 다시 원본 행렬로 복원이 된다. +# 거기에 + 사용자 평균 rating을 적용한다. +svd_user_predicted_ratings = np.dot(np.dot(U, sigma), Vt) + user_ratings_mean.reshape(-1, 1) + +# 생성된 matrix를 데이터 프레임 형태로 변환 +df_svd_preds = pd.DataFrame(svd_user_predicted_ratings, columns = df_user_movie_ratings.columns) +df_svd_preds.head() +``` + + + +```python +def recommend_movies(df_svd_preds, user_id, ori_movies_df, ori_ratings_df, num_recommendations=5): + + #현재는 index로 적용이 되어있으므로 user_id - 1을 해야함. + user_row_number = user_id - 1 + + # 최종적으로 만든 pred_df에서 사용자 index에 따라 영화 데이터 정렬 -> 영화 평점이 높은 순으로 정렬 됌 + sorted_user_predictions = df_svd_preds.iloc[user_row_number].sort_values(ascending=False) + + # 원본 평점 데이터에서 user id에 해당하는 데이터를 뽑아낸다. + user_data = ori_ratings_df[ori_ratings_df.userId == user_id] + + # 위에서 뽑은 user_data와 원본 영화 데이터를 합친다. + user_history = user_data.merge(ori_movies_df, on = 'movieId').sort_values(['rating'], ascending=False) + + # 원본 영화 데이터에서 사용자가 본 영화 데이터를 제외한 데이터를 추출 + recommendations = ori_movies_df[~ori_movies_df['movieId'].isin(user_history['movieId'])] + # 사용자의 영화 평점이 높은 순으로 정렬된 데이터와 위 recommendations을 합친다. + recommendations = recommendations.merge( pd.DataFrame(sorted_user_predictions).reset_index(), on = 'movieId') + # 컬럼 이름 바꾸고 정렬해서 return + recommendations = recommendations.rename(columns = {user_row_number: 'Predictions'}).sort_values('Predictions', ascending = False).iloc[:num_recommendations, :] + + + return user_history, recommendations +already_rated, predictions = recommend_movies(df_svd_preds, 330, df_movies, df_ratings, 10) +``` + + + +#### Reference +[1] https://dc7303.github.io/python/2019/08/06/python-memory/ +[2] https://yeomko.tistory.com/5?category=805638 +[3] https://scvgoe.github.io/2017-02-01-%ED%98%91%EC%97%85-%ED%95%84%ED%84%B0%EB%A7%81-%EC%B6%94%EC%B2%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C-(Collaborative-Filtering-Recommendation-System)/ + * 본 포스트는 이수진님의 블로그를 참조하며 공부하기 위해 작성하였습니다. diff --git a/_posts/cate_02_ML/recommend/2020-08-01-recommend-3_Matrix_Factorization_step_by_step.md b/_posts/cate_02_ML/recommend/2020-08-01-recommend-3_Matrix_Factorization_step_by_step.md new file mode 100644 index 00000000000..04f9caa0a92 --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-08-01-recommend-3_Matrix_Factorization_step_by_step.md @@ -0,0 +1,75 @@ +--- +layout: post +title: Recommend 3_Matrix Factorization step by step +date : 01 Aug 2020 +category : ML +comments : true +--- + +## 추천 시스템 : Matrix Factorization +#### (1) 개요 +: 유저와 아이템간의 상호작용 데이터(거래 데이터)를 기반으로 ‘잠재요인’을 찾아내고, +찾아낸 잠재요인을 기반으로 유저가 관람하지 않은 아이템에 대해서 평가하는 알고리즘 + +#### (2) 목표 +: 특정 고객의 과거 관람 이력을 토대로 , 아직 관람하지 않은 신규 영화의 선호 예측 + +
+ +
+ + +### Step ① 유저 잠재 행렬 & 아이템 잠재 행렬 생성 + +: 주어진 거래데이터(입력 데이터)를 활용해, 유저별로 어떤 *장르 취향을 지니고 있는지 & 영화별로는 어떤* 장르 특성을 지니고 있는지 학습하고자 합니다. + +
+ +
+ +##### ① <유저 잠재 행렬> +: 위 예시에서 ‘SF요인’과 ‘멜로요인’ 두 가지로 학습을 진행해, 고객별로 ‘SF 취향’과 ‘멜로 취향’ 점수를 계산합니다. + +e.g. A고객은 [테넷, 인셉션, 클로저] 영화를 관람하였고 그 결과, “A고객은 ‘SF 취향’ 은 0.8로 높으며, '멜로 취향’은 0.3점으로 낮다”고 고객의 선호를 정의할 수 있습니다. + +또한, 유저 잠재 행렬을 통해서 고객 A와 고객C가 서로 유사한 취향을 갖고 있다고도 알 수 있습니다. + +##### ② <아이템 잠재 행렬> +:영화도 동일한 방식으로, 영화별로 ‘SF 특성’과 ‘멜로 특성’ 점수를 계산하고, 영화의 특성을 정의합니다. + + +### Step ② 예측값 생성 +: <유저 잠재 행렬> & <아이템 잠재 행렬>을 토대로, + “고객의 선호”와 ”아이템의 특성”을 2가지 요인(SF & 멜로)으로 정의 했습니다. + +
+이는 즉, +우리는 고객의 선호를 알고 있고, +동시에 영화의 특성을 알고 있다는 의미입니다. + +따라서, 고객이 관람하지 않은 영화라고 하더라도, +계산되어 있는 ‘고객의 선호’와 ‘영화의 특성’을 결합하면, +해당 영화를 고객이 얼마나 선호할지 계산 할 수 있습니다. + +이제, 우리가 해결하고자 했던, 고객 C의 영화 ‘클로저’에 대한 선호점수를 계산해봅시다. +
+ +
+ + + + + +이처럼 고객의 선호값에 영화의 특성값을 곱하면, +고객이 관람하지 않은 영화에 대한 선호를 예측할 수 있습니다. + +동일한 방법으로 모든 고객의 취향값에 모든 영화의 특성값을 계산하면, +최종 예측 행렬을 얻을 수 있습니다. + + + +
+ +#### Reference +[1] [추천 시스템 – 잠재 요인 협업 필터링](https://lsjsj92.tistory.com/564?category=853217) +[2] [갈아먹는 추천 알고리즘 3 Matrix Factorization](https://yeomko.tistory.com/5?category=805638) diff --git a/_posts/cate_02_ML/recommend/2020-08-22-ALS_paper_review.md b/_posts/cate_02_ML/recommend/2020-08-22-ALS_paper_review.md new file mode 100644 index 00000000000..d672fb19a36 --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-08-22-ALS_paper_review.md @@ -0,0 +1,120 @@ +--- +layout: post +title: ALS Paper_review +date : 25 Jul 2020 +category : ML +comments : true +--- +# Collaborative Filtering for Implicit Feedback Datasets + +## 0. Abstract + : 추천 시스템의 기본 목표는 사용자가 과거에 생성한 암시적인 피드백 정보를 활용하여 개인화된 추천을 제공해주는 것입니다. 그러나, like & dislike가 명확히 표현되어 있지 않은 데이터에 있어서는 사용자가 어떤 아이템을 싫어하는지를 판단하는 것은 쉬운일이 아니게 됩니다. + 때문에 이 논문에서 제시하는 방법론은, 다양한 신뢰 수준(confidence level)에서 긍정과 부정적 선호를 다루고자 합니다. 이는 특히 긍정&부정 선호가 명확하지 않은 Implicit Feedback Datasets에서 중요한 모델로 활용됩니다. + + +## 1. Introduction +#### 1) Contents Based + : 영화의 장르, 감독, 배우, 흥행도 등을 사용해 유사한 작품군을 생성하고, 이를 기반하여 추천 모델을 구축합니다. 그러나 위와 같은 자세한 데이터 자체를 구축하기가 현실적으로 여렵다는 문제를 갖고 있습니다. + +#### 2) CF(Collaborative Filtering) + : 선호가 남아있지 않은 user와 item간의 관계를 파악하기 위해, '고객 유사도'와 '아이템 유사도'를 계산합니다. 과거 거래내역 또는 평가 데이터를 활용하며, 정확도 또한 앞서 Contents Based보다 뛰어나 가장 많이 활용되는 방법입니다. + +#### 3) Implicit Data 특징 + : Implicit data는 구매이력, 검색이력, 마우스 클릭 등의 선호가 명확하게 표현되어있지않은 데이터를 말합니다. Implicit data의 주요 특징은 몇가지를 살펴보면 아래와 같습니다. + - **(1) No Negative feedback** + : 구매하지 않은 데이터는, 선호하지 않은 것이지 혹은 해당 아이템의 존재를 알지 못한 것인지 알 수 없음. + + - **(2) Implict feedback is inferently noisy** + : 소비내역을 토대로 '선호' 아이템이라고 단정 지을 수 없습니다. 구매 이후에 해당 제품에 대해서 만족하지 못했을 가능성이 존재. + + - **(3) 명시적 수치 = 선호 / 암시적 수치 = 신뢰성** + : 암시적 데이터는 명확하게 선호와 비선호를 확인할 수는 없지만, 단순 binary가 아닌, 수치값으로 동일한 데이터를 중복해서 구매 했다면, 이는 높은 신뢰수준에서 선호. + + - **(4) Evaluation** + : explicit data는 MSE를 활용해 선호가 존재하는 데이터에 한하여 정확도를 비교할 수 있으나, implicit data에서는 0으로 남아있는 비구매 데이터를 제외하지 않으며 이를 구매하지 않았다고 싫어한다고 이야기 할 수 없어 단순 MSE를 사용하기 어렵. + + + +## 2. Preliminaries + - users : u, v + - items : i, j + - $r_ui$ : number of times u purchased item(original rating) + + +## 3. Previous work +#### 1) Latent factor model + : 대표적 잠재 요인 모델인 SVD모델은 "유저-유저 잠재요인"과 "아이템-아이템 잠재요인" 행렬을 생성하고, 이 두 행렬을 내적하여 예측결과를 제공합니다. + + - $x_u$ : user(u) & user factor($x_u$) + - $y_i$ : item(i) & item factor($y_i$) + - $\hat r_{ui} = x^T_u y_i$ + + + +**SVD object** +
+ +$min_{xy} \sum (r_{ui} - x^T_u y_i)^2 + \lambda(||x_u||^2 + ||y_i||^2)$ + +
+ +: 명시적 데이터 셋에서는 선호가 남아있는 값에 한하여 MSE를 진행하고, 과적합을 피하기 위해에 정규화항을 두었습니다. 이때 $\lambda$ 는 정규화를 위해 사용되는 파라미터로 SGD(stochastic gradient descent)를 활용해 계산합니다. + + +## 4. Our model +#### (1) Raw observation($r_{ui}$) into two separate magnitudes($p_{ui}, c_{ui}$) + - $p_{ui}$ = { 1 $r_{ui}$ > 0 | 0 $r_{ui}$ = 0} + : 유저의 선호를 0과 1로 나타낸 set (preference of user $u$ to item $i$) + ex) 유저($u$)가 아이템($i$) 소비시 $r_{ui}$ > 0 이며, $p_{ui}$ = 1 + + - $c_{ui} = 1 + \alpha r_{ui}$ + : implicit 데이터에서 선호를 나타내는 $p_{ui}$만으로는 선호를 확정할 수 없기에 다야한 수준에서 신뢰도를 나타낼 수 있는 지표가 필요하다. 신뢰도의 개념으로 기존 '0'이던 값들도 최소한의 신뢰도 수준에서 값을 지닐 수 있게 되며, preference가 존재하는 값은 $\alpha$에 비례해 커지게 된다.($\alpha$ = 40) + +#### (2) **ALS object** + : 목표는 기존의 MF와 동일하게 user-factor & item-factor의 잠재요인을 찾아내, $p_{ui}$를 계산하는 과정이다. 그러나 이때 아래의 다음 두 가지 차이점이 존재한다. + (1) 다양한 신뢰수준($c_{ui}$ 설명(계산)하기 + (2) 관찰되지 않은 모든 데이터 쌍($u,i$)에 대해서 optimization을 진행 + + +
+ + $min_{xy} \sum_{u,i} c_{ui}(p_{ui} - x^T_u y_i)^2 + \lambda(\sum||x_u||^2 + \sum||y_i||^2)$ + +
+ : item or user factor가 고정되면 cost function은 quadratic 방정식이되어 global minimum을 계산할 수 있게 된다.(Alternating-Least-Squares optimization process) + + - step 1 + : 아이템 latent factor 행렬을 고정하고, 사용자의 latent factor를 계산합니다. + 위 loss funcition에서 $y_i$를 상수로 취급한 다음 미분을 진행하면 되며, 미분 결과 유저 행렬 $x_u$는 다음과 같이 산출됩니다.
+ $x_u = (Y^TC^uY + \lambda I)^{-1}Y^TC^up(u)$
+ 다음 초기 랜덤하게 설정된 유저 행렬을 위에서 계산된 값으로 업데이트 해줍니다. + + - step 2 + : 다음으로 사용자 행렬($x_u$)을 고정하고 아이템의 latent factor를 계산합니다. + $y_i = (X^TC^iX + \lambda I)^{-1}X^TC^ip(i)$
+ 마찬가지로 랜덤하게 설정된 아이템 행렬을 업데이트 시켜줍니다. + + - step 3 + : 위의 과정을 통해 최적의 user & item 행렬을 찾아내며 보통 이때의 loop 횟수는 10~15회 정도로 설정됩니다.
+ ALS 결과 업데이트 된 $x_u, y_i$를 곱해 고객 u의 아이템 i에 대한 선호 $\hat p_{ui}$를 계산 할 수 있게 됩니다. +
+ +$\hat p_{ui} = x_u^T y_i$ +
+ + +
+ +[github link : ALS_test_code Link](https://github.com/TaeHwanYoun/taehwanyoun.github.io/blob/master/test_code/ALS%20Implementation.ipynb) + +
+ + + + + + + +#### Reference +[1] [Yifan Hu et al. Collaborative Filtering for Implicit Feedback](http://www.Datasetshttp://yifanhu.net/PUB/cf.pdf) +[2] [갈아먹는 추 알고리즘 [4] Alternating Least Squares](https://yeomko.tistory.com/4?category=805638) diff --git a/_posts/cate_02_ML/recommend/2020-09-27-wide&deep_youtubeRanking.md b/_posts/cate_02_ML/recommend/2020-09-27-wide&deep_youtubeRanking.md new file mode 100644 index 00000000000..2414f48b542 --- /dev/null +++ b/_posts/cate_02_ML/recommend/2020-09-27-wide&deep_youtubeRanking.md @@ -0,0 +1,107 @@ +--- +layout: post +title: YouTube Recommendations Paper_review +date : 27 sep 2020 +category : ML +comments : true +--- +# Deep Neural Networks for YouTube Recommendations + +## 0. Abstract + : 이 글은 딥러닝을 활용한 드라마틱한 성능의 추천 시스템에 대한 논문이다. 해당 방식은 2가지로 나뉘게 되는데, 첫번째는 '후보생성 모델(deep candidate generation model)'이며, 두번째는 '랭킹 모델(deep ranking model)'이다. + *(필자는 현재 주어진 컨텐츠에 대해서 누가 높은 레이팅을 줄 것인지만 다루고 있기에 두가지 모델중 랭킹 모델에 관련된 컨텐츠만을 읽었다...)* + + +## 1. Introduction + : youtube는 세계에서 가장 큰 영상 플렛폼으로, 개인화된 영상을 제공해 주는데 있어 아래와 같은 3가지 주요 쟁점을 갖고 있다. +- **(1) Scale** +: 적당히 적은 규모에서 잘 작동하던 증명된 추천 알고리즘들도, youtube의 거대한 스케일의 데이터에서는 성능이 나오지 못했다. 이 때문에 매우 특별하게 분산된 학습 알고리즘 및 효율적인 서비스 시스템은 필수적이었다. + +- **(2) Freshness** +: YouTube는 매초 수십시간의 영상이 새롭게 업데이트되기에, 각 유저의 최근 행동에 따라 새로운 컨텐츠도 벨런스 맞게 추천해줄 수 있어야 했다. + +- **(3) Noise** +: 사용자의 행동을 예측하는 것은 관측되지 않은 외부 요인들에 대한 sparsity와 variety 때문에 근본적인 어려움을 갖고 있다. 때문에 + + +## 2. System Overview + : 전반적인 시스템은 두가지 neural Networks으로 구성된다. + + - **candidate generation** + - input : events from the user's YouTube activity history + - output : samll subset(hundreds) of videos from a large corpus + + : 후보 생성 모델은 CF(Collaborative Filtering)를 통해 제공된 넓은 의미의 개인화된 목록을 제공 + 이때 유저간 유사도는 시청된 영상의 ID값, 검색 토큰, 인구통계 등의 굵직한 특징을 활용해 생성된다. + + + - **ranking** + : 주어진 리스트내에서 'best' 추천을 위해서는 적당한 수준에서 각 후보들의 중요성을 'recall'값을 기반으로 구별할 수 있어야 한다. '랭킹 모델'은 영상과 유저를 표현하는 특징(ex. latent facor)과 목적함수를 사용해 각 영상에 점수를 부여함으로써 이를 수행한다. +위 두가지 단계는 방대한 영상속에서 아주 적은 개인화된 영상을 추천해야하는 문제를 가능하게끔 만들어주었다. 개발단계에서 다양한 metrics(precision, recall, ranking loss, etc)을 사용했으나 최종 결정단계에 있어서는 live 실험을 통한 A|B testing을 진행했다. 실제 테스팅 과정에서 클릭 전환율, 시청 시간, 유저 개입도, 기타 평가 방법등의 미묘한 차이를 측정할 수 있었다. 실제 test와 offline 실험은 굉장히 다르기에, 위의 미묘한 차이들은 굉장히 중요한 시사점을 지닌다. + + + +## 4. Ranking + : ranking 모델의 주요 목표는 데이터를 specialize & calibrate(눈금을 매기다) 시키는 것입니다. + 랭킹 모델을 통해서 우리는 후보 생성 모델을 통해 걸러진 몇백개의 영상에 대해서 유저와 사용자간 더 많은 특징들에 주목했습니다. 랭킹 모델은 또한 서로 다른 후보의 출처들은 각 점수를 직접 비교할 수 없기에 이를 앙상블하는 것에도 중요하게 생각했습니다. + +
+ +
+ + +#### 4-1) Feature Representation + : 우리의 Feature들은 전통적인 categorical & continuos/ordinal변수 분류법들과는 차별적인 방식을 지닙니다. + - categorical : binary(e.g. 로그인 여부) or millions of multi class(e.g. 검색 기록) + - single value => univalent (e.g. 비디오 구분값) + - set of values => multivalent (e.g. 유저가 시청한 N개의 비디오 ID값들의 목록) + +우리는 또한 변수가 아이템을 묘사하는 것인지 또는 사용자/context('query')를 묘사하는지에 따라 구분했습니다. + +##### (1) Feature Engineering + : 비록 딥러닝이 수많은 변수를 수동으로 핸들링 하지 않아도 되는 장점을 지니고 있으나, 우리가 갖고 있는 데이터를 그대로 input으로 넣어 feedforward neural network를 진행하기엔 무리가 있었다. + 가장 중요한 문제는 Temporal sequence of user actions에 대한 표현과 이를 어떻게 스코어로 연결짓는 것인가였다. + [e.g. of Temporal sequence of user action] + - channel : 해당 채널에서 얼마나 많은 영상을 사용자가 시청했는가(like 구독 여부) + - the last time the user watched on this topic : 해당 이슈에 대해서 언제 마지막으로 시청했는가 + - candidate generation : 어떤 소스들이 이 영상을 후보군에 포함시키는데 일조하였는지 + - frequency of past video impression : 과거 시청 빈도를 통해 이탈(churn)예 + => 위의 사항들이 고려된 feature engineering이 필요함 + +#### (2) Embedding Categorical Features + : sparse한 categorical feature를 neural network에 적합한 dense형태로 변화하기 위해 Embedding을 활용. + +*Embedded unique ID space('vocabulary')* + - number of Dimension : 각 고유 ID 공간은 별도의 학습된 임베딩 공간을 갖으며, 이때 공간의 차원수는 유니크한 고유 값(number of unique)수의 로그에 대략 비례하여 증가하는 차원수를 갖는다.(e.g. 1000개의 유니크한 단어가 존재할 시, log1000을 차원수로 설정) + - Top N : 매우 큰 ID space를 줄이기 위해, 클릭수를 기준으로 Top N개의 단어 id만 사용 + - 사전에서 찾을 수 없는 단어는 0으로 임베딩 처리 + - 다중값 범주형 임베딩(multivalent)은 네트워크에 들어가기전에 평균값 처리 + - 동일한 ID space 공간내의 카테고리 변수는 동일한 embedding공간에 놓인다. + e.g. 독특한 특징을 지닌 영상의 Id들은 단일 글로벌 임베딩(video ID of the imporessio, last video ID watched by the user, video ID that 'seeded' the recommendation) + * 동일한 임베딩을 공유하더라도, 각각의 feature는 네트워크에 들어갈 때 독립적으로 들어가, 레이가 각 feature들에 특화되어 학습할 수 있도록 한다. + * 임베딩을 공유하는 것은 모델의 일반화(generalization)를 위해 중요하며, 학습 속도를 향상시키고 더 많은 메모리를 절약할 수 있다.(32차원에 임베딩된 100만 id고유값은 2048개의 fully connected layer보다 7배 이상 많은 파라미터를 갖는다.) + + +#### (3) Normalizing Continuous Features + : 신경망은 input값의 분포와 스케일 문제에 민감하기로 악명이 높은 반면, 대안적 접근법인 의사결정나무(decision trees)는 개별 feature의 스케일 문제에 둔감하다. + 우리는 적절한 평준화(Normalization)가 연속변수의 수렴에 있어서 굉장히 중요하다는 걸 알게 되었다. + f분포를 갖고 있는 연속변수 $x$는 누적 분포를 활용해 value의 스케일에 따라 0~1사이 동등한 분포를 갖는 $\tilde{x}$로 변환된다. + 더불어 원본인 $\tilde{x}$에 $\tilde{x^2}$ or $\sqrt{\tilde{x}}$등을 적용해 더욱 강력한 네트워크를 만들기도 하였으며, 이때 제곱항을 적용하는 것이 오프라인 성능을 향상시키기도 하였다. + + + + + +
+ +[ALS_test_code Link](https://github.com/TaeHwanYoun/taehwanyoun.github.io/blob/master/test_code/ALS%20Implementation.ipynb) + +
+ + + + +#### Reference + +[1] [Yifan Hu et al. Collaborative Filtering for Implicit Feedback](http://www.Datasetshttp://yifanhu.net/PUB/cf.pdf) +[2] [갈아먹는 추 알고리즘 [4] Alternating Least Squares](https://yeomko.tistory.com/4?category=805638) diff --git a/_posts/cate_02_ML/timesereies/2021-03-18-acf_pacf.md b/_posts/cate_02_ML/timesereies/2021-03-18-acf_pacf.md new file mode 100644 index 00000000000..a72eb3ebc22 --- /dev/null +++ b/_posts/cate_02_ML/timesereies/2021-03-18-acf_pacf.md @@ -0,0 +1,134 @@ +--- +layout: post +title: ACF & PACF +date : 19 Mar 2021 +category : ML +comments : true +--- + + : ARIMA또는 Prophet등 데이터의 과거 패턴만을 활용한 시계열 분석에 있어서 중요한 개념 중 하나가 자기상관함수(ACF : Aucto Correlation Function)와 편자기상관함수(PACF : Partial autocorrelation Fucntion)이다. 특히 Arima의 경우, 위 두가지 함수를 그려보며, 데이터의 자기상관성을 검토하여 파라미터(p,d,q)를 설정하니 각 개념에 대하여 살펴보자. + +## 1. 자기상관함수(ACF : Aucto Correlation Function) + - ACF : $y_t$와 $y_{t+k}$사이의 Correlation을 측정하는 것 + +
+ +
+ + - 분자 : $var(y_t)$ : $N-K$관측값을 대상으로 계산하기에 K가 커지면 줄어듦. + - 분모 : $cov(y_t, y_{t+k})$ : 모든 N개의 관측치에 대해서 측정하기에 고정됨 + + ∴ K가 커지면, 분자의 SUM값이 줄어들어 ACF(k)는 줄어든다. 다시말해 K가 커지면 오늘을 기점으로 먼 미래의 상관관계를 측정하는 것이기에, 자기상관계수는 줄어들게 된다. +

+ +#### + 자기상관계수 vs 상관계수(PACF : Partial autocorrelation Fucntion) + +
+ +
+ +

+ + +## 2. 편자기상관함수(PACF : Partial autocorrelation Fucntion) +: 앞서 ACF만으로는 자기상관성(AR:Autocorrelation)모델과 이동평균(MA:MovingAverage)모델을 선택하거나, 얼만큼의 시차(lag)를 적용할지 결정하기 어렵다. 이에 추가로 PACF를 활용한 분석이 필요하다. + + - PACF는 $y_t$와 $y_{t+k}$사이의 Correlation을 측정하는 것은 동일하나, + $t$와 $t_{+k}$사이의 다른 $y$값들의 영향력을 배제하고 측정한다. + 'ACF가' '미분'이라면, 'PACF'는 '편미분'과 유사해 보인다. + +
+
+ +이때, $e_{t}$는 아래와 같으며, + +온전한 $y_{t}$와 $y_{t+k}$만을 남겨놓고, 둘 사이의 상관계수를 계산한다. +
+ + +## 3. 차분(Differencing) +: ACF와 PACF는 시계열적인 특성만을 이야기한다. 때문에, 그래프 자체가 전체적으로 우상향/우하향 하는 선형적인 추세가 있다면, 시계열이 비정상(non-stationary)으로 작동하여 ACF와 PACF를 정확하게 살펴 볼 수 없다. +이러한 점을 해결하기위해, 데이터에 차분을 적용해 선형적인 추세를 없애 줄 수 있다. + * 정상성 : 평균이 일정 -> 모든 시점에 대해서 일정한 평균을 갖음(평균이 일정하지 않은 시계열은 차분을 통해 정상화 가능) + + +- 1) 로그 변환을 통해 데이터의 스케일을 눌러줌 +- 2) 이후 차분을 적용하여 선형적인 패턴 제거 +- 3) ACF와 PACF를 진행하여 AR & MA 결정 + + +```python +df_time = pd.DataFrame(df_merge_fin[y_col]) + +# 2) 차분(1&2차) 확인 +def time_series_diff(df_time_target, y_col) : + # 차분 -> 시계열 정상성 확인 + df_time_target[y_col].plot( + figsize = (12,5),title = str(APP_KEY +' : orginal Non Stationary Data')).autoscale(axis = 'x', tight = True) + plt.show() + + ## 1차 차분 + diff_1 = df_time_target[y_col]-df_time_target[y_col].shift(1) # 판다스의 shift메소드를 이용해 차분하는 방 + plt.figure(figsize = (12,5)) + plt.plot(diff_1) + plt.title(str(APP_KEY + ' : First Order of Non Stationary Data')) + plt.show() + + ## 2차 차분 + diff_2 = np.diff(df_time_target[y_col], 2) + plt.figure(figsize = (12,5)) + plt.plot(diff_2) + plt.title(str(APP_KEY + ' : Seconde Order of Non Stationary Data')) + plt.show() +time_series_diff(df_time, y_col) +``` +
+
+ +1차 차분 +
+ +2차 차분 + +
+ + + +## 4. ACF와 PACF를 통한 모델(AR & MA) 및 시차 결정 + +- 1) ACF + : 자기 상관 함수는 k 시간 단위로 구분된 시계열의 관측치(yt 및 yt–k) 간 상관의 측도입니다. +
+ + + + + 이 그림에서는 시차 1에 유의한 상관이 있고 몇 시차 후에 감소합니다. + 이 패턴은 자기 회귀 항을 나타냅니다. 자기 회귀 항의 차수를 확인하려면 편 자기 상관 함수를 사용해야 합니다. +
+ + +- 2) PACF + : 편 자기 상관 함수는 다른 모든 짧은 시차 항에 따라 조정한 후 k 시간 단위로 구분된 시계열(yt–1, yt–2, ..., yt–k–1)의 관측치(yt 및 yt–k) 간 상관의 측도입니다. + +
+ + + + + 이 그림에서는 시차 1에 유의한 상관이 있고 그 뒤에 유의하지 않은 상관이 있습니다. + 이 패턴은 1차 자기회귀 항을 나타냅니다. + +
+ +- [자기 상관 함수(ACF)](https://support.minitab.com/ko-kr/minitab/18/help-and-how-to/modeling-statistics/time-series/how-to/autocorrelation/interpret-the-results/autocorrelation-function-acf/) +- [편 자기 상관 함수(PACF) 해석](https://support.minitab.com/ko-kr/minitab/18/help-and-how-to/modeling-statistics/time-series/how-to/partial-autocorrelation/interpret-the-results/partial-autocorrelation-function-pacf/) + + + +#### Reference +[1] [시계열(Time series) > ACF, PACF](https://direction-f.tistory.com/65) +[2] [[R] 자기상관계수 (Autocorrelation Coefficients), 자기상관그림(Autocorrelation Plot)](https://rfriend.tistory.com/528) +[3] [자기 상관 그래프 (ACF Auto Correlation Function)](https://medium.com/@boramlee1/%EC%9E%90%EA%B8%B0-%EC%83%81%EA%B4%80-%EA%B7%B8%EB%9E%98%ED%94%84-acf-auto-correlation-function-41142935a87d) +[4] [TimeSeries with Python - 차분 & 차분을 이용한 예측값 구하기 +](https://kanggogo1234.tistory.com/48) diff --git a/_posts/cate_03_DL/NLP/2020-10-22-word2vec.md b/_posts/cate_03_DL/NLP/2020-10-22-word2vec.md new file mode 100644 index 00000000000..a904a0d6c42 --- /dev/null +++ b/_posts/cate_03_DL/NLP/2020-10-22-word2vec.md @@ -0,0 +1,160 @@ +--- +layout: post +title: Word2vec +date : 28 sep 2020 +category : DL +comments : true +--- +# Word2vec + + : 본 포스팅은, 쉽게 씌어진 word2vec 블로그를 공부하며 정리하기 위해 작성되었습니다. + +## 1. 단어 -> 숫자 +#### 1) one hot encoding + : 각 단어를 하나의 Feature로 활용해, 해당 단어가 속하는 Feature에만 1을 매기며, 나머지는 0으로 채우는 방법 + - 장점 : 표현이 쉬움. + - 단점 : 단어와 단어간 관계가 전혀 드러나지 않음 + - e.g. '강아지' & '멍멍이' 두 단어는 사실상 유사한 단어이나, 서로 다른 독립적인 feature로 인식됨 + +
+ +
+ + => 단어와 단어간 관계를 벡터 공간상 위치로 표현하기 위한 시도 등장 => *'word embedding model + + +#### 2) Embedding test + [한국어 Word2Vec](https://word2vec.kr/search/?query=%ED%95%9C%EA%B5%AD-%EC%84%9C%EC%9A%B8%2B%ED%8C%8C%EB%A6%AC) + +단어를 벡터간 위치값으로 변환시, 덧셈 & 뺄셈이 가능해짐. 위 사이트에서 단어와 단어를 빼거나 더했을 때 벡터간 위치의 변화로 인해 어떻게 의미가 변화하는지 경험해 볼 수 있음(e.g. “한국 - 서울 + 도쿄 = 일본") + + +## 2. Sparse vs Dense Representatios + * feature representation : 대상을 표현 하는 방식으로, 자연어 처리의 경우 특정 '텍스트'를 판단하기 위해 해당 단어와 함께 등장하는 단어, 단어의 길이, 단어의 위치, 함께 쓰인 품사 등이 특정 '텍스트'를 표현하고 있는 언어적 정보가 될 수 있다. 이같은 속성에는 크게 Sparse representation과 dense representation으로 존재. + +#### 1) Sparse representation + : one hot encoding or dummy variable, + - 단어의 표현 : 표현해야 하는 단어의 수 N개일 때 -> N차원의 벡터 생성 후 해당 단어에만 1표시 + - 품사의 표현 : 모든 품사의 개수 만큼의 차원 생성 -> '명사'에 해당하는 벡터의 요소값만 1표시 + + + + +#### 2) Dense representation : Embedding + : 설정한 차원의 개수로 특정 단어를 대응시켜 표현. 이때 각 단어를 주어진 차원에 어떻게 표현할 것인지를 학습. 이렇게 임베딩된 단어는 설정된 각 차원에 값을 갖고 있기에 더이상 sparse하지 않고 모든 열에 값이 채워지며 아래 방식으로 불림. + - 값이 채워져 있음: “Dense” + - 각 차원에 단어의 의미가 분산 됨 : “Distributed” + + + +## 3. Dense Representation의 장점 +#### (1) 차원이 저주 방지 + - 적은 차원으로 대상 표현 가능하며, 0으로만 채워져 있지도 않음. +#### (2) 일반화 능력 (Generalization power) + ex) ‘강아지’ 자주 등장 / ‘멍멍이’ 적게 등장 시 + - [Sparse] ‘강아지’와 ‘멍멍이’간의 관계에 대해서 전혀 표현되지 않기에 ‘강아지’는 학습이 되어도, ‘멍멍이’는 학습되지 않음 + - [Dense] ‘강아지’와 ‘멍멍이’ 유사한 맥락하에 등장하기에, 입력값이 유사하고, ‘강아지’로 학습된 모델에 ‘멍멍이’가 입력될 시 서로 동일한 아웃풋을 갖을 수 있음. + +## 4. word2vec 핵심 아이디어@ +: “단어의 주변을 보면 그 단어를 안다.” + +위 문장에서 food와 어울리는 단어는 빈칸에 들어가도 되지만, chair & parking등은 어색함. +-> 비슷한 맥락을 갖는 단어는 비슷한 벡터를 부여 + + + - word2vec -> predictive method 방식 + : 맥락으로 단어를 예측 / 단어로 맥락을 예측 + - Unsupuervised learning + : 어떤 단어와 어떤 단어가 비슷한지 주어진 문장을 토대로 스스스로 학습 + +## 5. Algorithm of word2Vec + 1) CBOW(Continuous Bag of Words): 맥락으로 단어 예측 + 2) Skip-gram(Continuous Bag of Words): 단어로 맥락을 예측 + +#### (1) CBOW + : 주변 단어로 타겟 단어를 예측하는 방법으로, 주변 단어를 인풋(X)으로 넣어가며, 파라미터를 학습해 타겟 단어를 벡터방식으로 표현 +##### (a) 구성 + - Window : 주변 단어, 맥락(Context) + - Window Size : 앞 & 뒤 몇개의 단어를 살펴볼 것인가 + - Target word : 타겟 단어 + + +##### (b) 학습 방식 +- **Sliding Window** + : window를 옆으로 밀면서, target 단어를 하나씩 바꿔가는 방식으로, 모든 단어에 대해서 학습해 나감 + + - **backpropagation & gradient descent** + : 딥러닝 방식과 동일하게, 랜덤하게 초기화(random initialization)된 파라미터로 시작하여, 이 파라미터로 예측한 값이 틀릴 경우, 오차를 수정하는 과정을 반복(backpropagation & gradient descent) + + + + +##### (c) 의의 + : 주변 단어가 입력값이 될때, 타겟 단어가 서로 다르더라도 주변 단어의 입력값이 서로 유사하다면, + 해당 타겟 단어들은 서로 유사한 벡터값을 지정받게 될 것이며, 이는 벡터간 거리가 짧다는 의미가 된다. + + + +## 6. Mathmatical meaning of word2Vec + - 문맥(input)을 바로 앞 단어 하나라고 가정(window size = 1) + + + + - V : 사전의 크기(vocabulary size) => 단어의 개수 + - N : 히든 레이어 크기(hiddn layer size) => 몇차원으로 임베딩할 지의 크기(embedding size) + +##### Step 1 : Input layer `x = [1xV]` + : OneHotEncoding된 벡터로, 타겟 단어의 앞 단어는 v개의 요소 중 단 하나의 요소만 1, 나머지는 모두 0인 1xV차원의 벡터입니다. + +##### Step 2 : $W$ (Weight between input & hidden layer) `W = [VxN]` + : 위에서 받은 OHE형태의 Input 행렬은 설정된 임의의 크기(N)의 hidden layer로 투영(projection)되기 위해 W행렬($W_{V*N}$)과 곱해집니다. + + +##### Step 3 : Hidden layer `h = [1xN]` + : Input 행렬에 $W_{V*N}$ 곱해져 1xN 차원의 embedding된 행렬입니다. +
+ + $x\times W = W^T_{(i,)} = h$ +이때, input행렬은 i번째 값을 제외하고 모두 0인 `[1xV]`행렬이기에, +$[x\times W]$는 $W$행렬의 i번째 행과 동일합니다.(학습대상1) + + +(window size가 2개 이상이면, + 각 h행렬값의 평균 벡터가 h가 됩니다) +$h$ = $(h_1 + h_2) \over 2 \times n(window size)$ +
+ +##### Step 4 : $W'$(Weight between hidden & output layer) `W' = [NxV]` + : 임베딩된 행렬을 토대로, 최종 Output값이 무엇인지 출력하기 위한 가중치행렬입니다.(학습대상2) + + +
+ +$W'_{M\times V} \times h = z $ +$softmax(z) = \hat{y},$ + +
+ +##### Step 5 : Output layer `y = 1XV` +: 출력은 타겟 단어로, 타겟 단어 바로 앞의 단어가 등장했을 때, 다음으로 등장할 수 있는 모든 단어 v개의 점수이며, 여기에 soft-max를 취해 확률값으로 변환됩니다. + +
+ +$softmax(z) = \hat{y},$ +이렇게 구해진 $\hat{y}$벡터를 스코어 벡터라고 부릅니다. + +
+ +
+ + + +그리고, 계산된 스코어 벡터를 실제 타겟 단어값을 기준으로 OHE된 행렬과 비교하여, 그 차이를 줄이는 방식으로 가중치 행렬($W, W'$)을 학습합니다. + + +
+ +#### Reference +[ [1] 쉽게 씌어진 word2vec](https://dreamgonfly.github.io/blog/word2vec-explained/#%EB%8B%A8%EC%96%B4-%EC%9E%84%EB%B2%A0%EB%94%A9word-embedding-%EB%A7%9B%EB%B3%B4%EA%B8%B0) +[ [2] 위키독스 : 워드투벡터(Word2Vec)](https://wikidocs.net/22660) +[ [3] 한국어 Word2Vec](https://word2vec.kr/search/?query=%ED%95%9C%EA%B5%AD-%EC%84%9C%EC%9A%B8%2B%ED%8C%8C%EB%A6%AC) diff --git a/_posts/cate_04_Preprocess/2020-08-03-Prep-Preprocess-CSR_Sparse_Matrix.md b/_posts/cate_04_Preprocess/2020-08-03-Prep-Preprocess-CSR_Sparse_Matrix.md new file mode 100644 index 00000000000..4f9be6b690d --- /dev/null +++ b/_posts/cate_04_Preprocess/2020-08-03-Prep-Preprocess-CSR_Sparse_Matrix.md @@ -0,0 +1,169 @@ +--- +layout: post +title: (Prep) CSR_Sparse_Matrix +date : 08 Aug 2020 +category : Preprocess +comments : true +--- + +: 추천 시스템, 자연어처리등을 하다보면 모든 아이템 또는 각 워드를 컬럼으로 사용해야하는 One-Hot-Encoding을 종종하게 됩니다. 그러나 이때 너무 많은 아이템 또는 단어가 컬럼 변환되며 이과정에서 대부분의 value는 0으로 이루어져 메모리만 크게 차지하는 희소 행렬을 자주 마주하게 됩니다. 이를 해결하기 위해 Sparse matrix의 종류중 하나인 CSR Matrix를 사용할 수 있으나, 문제는 인덱스만으로 이루어져있는 Sparse Matrix 특성상 종종 기존의 matrix에 적용하던 함수를 그대로 사용하면 에러가 발생하는 문제가 있어 이를 다시 어떻게 풀어가며 활용할지 CSR Matrix의 원리와 사용법을 살펴보고자 합니다. + +## 1. CSR Matrix(Compressed Sparse Row) Concept + : CSR Matrix는 단어 그대로, row별로 데이터를 압축하여 값이 존재하는 row별 column값을 출력합니다. + +id|A|B|C|D| +---|---|---|---|---| +정형돈|1|3|0|0| +유재석|0|5|0|2| +노홍철|0|0|2|0| + +위와 같은 행렬이 존재한다고 할때, sparse matrix의 결과는 아래와 같습니다. +```python +print(csr) +(0, 0) 1 +(0, 1) 3 +(1, 1) 5 +(1, 4) 2 +(2, 2) 2 +``` +이때 4번째 줄을 해석하는 방법은 1번째 row의 4번째 컬럼에 2이라는 값이 있다고 해석하면 됩니다. + + +### 1) CSR Matrix 생성하기-1 + : 우선 이미 sparse한 형태의 matrix를 갖고 있다면, 이를 CSR Matrix로 변환하는 것은 `csr_matrix()`함수를 사용해 쉽게 csr_matrix를 생성할 수 있습니다. +```python +import numpy as np +from scipy.sparse import csr_matrix + +x = [[1, 0, 0, 3, 0, 0], + [0, 0, 2, 0, 5, 0], + [0, 0, 0, 0, 1, 2], + [2, 3, 0, 0, 0, 4]] +x = np.asarray(x) +csr = csr_matrix(x) +``` +```python +csr +# <4x6 sparse matrix of type '' +# with 9 stored elements in Compressed Sparse Row format> + +print(csr) +# (0, 0) 1 +# (0, 3) 3 +# (1, 2) 2 +# (1, 4) 5 +# (2, 4) 1 +# (2, 5) 2 +# (3, 0) 2 +# (3, 1) 3 +# (3, 5) 4 +``` + +### 2) CSR Matrix 생성하기-2 + : 그러나 이미 희소행렬 자체가 너무 크다면, 이를 array 형태로 생성하는 것 조차 불가능한 경우가 있습니다. 즉 One-Hot-Encoding 자체가 메모리 이슈로 인해 진행되지 않는 상황입니다. + 이 경우, OHE과정에서 `sparse_output = ture`옵션을 활용해 OHE output matrix를 csr sprase matrix로 생성할 수 있습니다. + (특정 row가 2개 이상의 value를 갖고 있는 multi label의 상황을 가정하여 진행하였습니다.) + + ```python + import pandas as pd +df = pd.DataFrame({'id' : [1,2,3,4,5], + 'value' : [['a','b'], + ['b','f'], + ['c'], + ['a', 'c', 'e'], + ['e','f']]}) + ``` + +
+

+ +
+ + ```python + from scipy import sparse + from sklearn.preprocessing import OneHotEncoder, MultiLabelBinarizer + + ## 1) INSTANTIATE + enc = MultiLabelBinarizer(sparse_output=True) + + ## 2) FIT & Transform + df_mat = enc.fit_transform(df.value) # label이 들어가는 value를 input으로 fit_transform 시켜줄 것 + +print(df_mat) + # (0, 0) 1 + # (0, 1) 1 + # (1, 1) 1 + # (1, 4) 1 + # (2, 2) 1 + # (3, 0) 1 + # (3, 2) 1 + # (3, 3) 1 + # (4, 4) 1 + # (4, 3) 1 + ``` + + + +## 2. CSR Matrix indexing + +csr_matrix는 data, indices, indptr 세가지 구성요소를 갖고있습니다. + - `data` : matrix내에 있는 모든 0이 아닌 value값 + - `indices` : value가 위치한 columnd의 index + - `indptr` : indptr은 위 indices를 기준으로, 각 row내 value의 indices 시작점과 끝점을 알려준다. +
+ + + + +```python +# 1) data +df_mat.data +# array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + +# 2) indices +df_mat.indices +# array([0, 1, 1, 4, 2, 0, 2, 3, 4, 3], dtype=int32) + +# 3) indptr +df_mat.indptr +# array([ 0, 2, 4, 5, 8, 10], dtype=int32) +``` +
+ +
+ +위와 같이 생성한 행렬의 indices값을 토대로 0~2번째까지 값은 첫번째 row, 5~8번째 값은 row는 4번째 row에 속하는 값임을 알 수 있습니다. +
+ +- `nonzero()` +당장 위의 3가지 인덱싱을 이해하더라도 csr_matrix가 잘 이해되지 않는다면 `.nonzero()`를 사용해 값이 위치한 행과 열의 인덱스를 직관적으로 확인해 볼 수 있습니다. + +- `todense()` +끝으로, `todense()` 압축한 csr_matrix를 다시 익숙한 dense matrix로 변환해줍니다. + + + +```python +df_mat.nonzero() +# (array([0, 0, 1, 1, 2, 3, 3, 3, 4, 4], dtype=int32), +# array([0, 1, 1, 4, 2, 0, 2, 3, 4, 3], dtype=int32)) + +df_mat.todense() +# matrix([[1, 1, 0, 0, 0], +# [0, 1, 0, 0, 1], +# [0, 0, 1, 0, 0], +# [1, 0, 1, 1, 0], +# [0, 0, 0, 1, 1]]) +``` + + +여기까지 csr_matrix의 기본활용방법을 살펴봤습니다. csr_matrix는 큰 데이터를 다뤄야하는 추천 모델, 딥러닝 등 다양한 분야에서 자주 사용됩니다. 때문에 잘 만들어진 패키지 내부를 보면 csr_matrix의 인덱스를 활용해 큰 matrix도 상대적으로 가볍게 변환하여 연산을 진행하는 모습을 종종 볼 수 있었습니다. 다음엔, index를 활용해 만들어진 함수를 살펴보며 활용법을 배워보면 좋을 것 같습니다. + + + + + + +#### Reference +[1] https://lovit.github.io/nlp/machine%20learning/2018/04/09/sparse_mtarix_handling/ +[2] https://bkshin.tistory.com/entry/NLP-7-%ED%9D%AC%EC%86%8C-%ED%96%89%EB%A0%AC-Sparse-Matrix-COO-%ED%98%95%EC%8B%9D-CSR-%ED%98%95%EC%8B%9D diff --git a/_posts/cate_04_Preprocess/2020-09-19-Utils-dateTime.md b/_posts/cate_04_Preprocess/2020-09-19-Utils-dateTime.md new file mode 100644 index 00000000000..dce36563ea8 --- /dev/null +++ b/_posts/cate_04_Preprocess/2020-09-19-Utils-dateTime.md @@ -0,0 +1,127 @@ +--- +layout: post +title: (Utils) DateTime +date : 08 Sep 2020 +category : Preprocess +comments : true +--- + + : 로그 데이터를 다루다보면, 사용자가 언제 접속하는지, 얼마나 또는 얼마만에 접속하는지 등 시간에 관한 변수를 생성해야 하는 경우가 많다. 그러나 앱/사이트 별로 수집되는 time 변수의 format이 매번 다른 경우가 많기에 이를 핸들링해야하는 상황이 자주 생기게 되기에, time변수를 핸들링하는 방법들에게 대해서 정리해보고자 한다. + +## 1. Change format : [String/int] to DateTime + : datetime 또는 strptime 함수를 사용하여, 인자로 해당 String의 format을 넣어주면 datetime으로 바꿀 수 있다. +```python +from datetime import * + +# 1) datetime +date_time_str = "20120213" +date_time_obj = datetime(year=int(date_time_str[0:4]), + month=int(date_time_str[4:6]), + day=int(date_time_str[6:8])) +print(type(date_time_obj)) # + + +# 2) strptime function +## yyyymmdd -> datetime +date_time_str = "20120213" +date_time_obj = datetime.strptime(date_time_str, '%Y%m%d') + +## yy/mm/dd -> datetime +date_time_str = '18/09/24' +date_time_obj = datetime.strptime(date_time_str, '%y/%m/%d') +print(type(date_time_obj)) # + +## yy.mm.dd -> datetime +date_time_str = '18.09.24' +date_time_obj = datetime.strptime(date_time_str, '%y.%m.%d') +print(type(date_time_obj)) # + +## yyyy.mm.dd str -> datetime +## : 4글자 형태의 연도는 %Y 대문자로 format 지정 +date_time_str = '2018.09.24' +date_time_obj = datetime.strptime(date_time_str, '%Y.%m.%d') +print(date_time_obj) # 2018-09-24 00:00:00 +``` + + + +## 2. Calculate dateTime +:datetime type은 timedelta 함수를 활용해 날짜를 변경할 수 있다. +```python +date_time_obj = datetime.strptime('18.09.24', '%y.%m.%d') +date_time_obj = date_time_obj - timedelta(days=10) +print(date_time_obj) +date_time_obj = date_time_obj + timedelta(minutes=80) +print(date_time_obj) + +# 2018-09-14 00:00:00 +# 2018-09-14 01:20:00 +``` + + + +## 3. Get Y/M/D H/M/S Weekday + :datetime type에서 원하는 날짜 정보만을 출력하는 방법 +```python +# datetime +date_time_str = "20120213 180930" +date_time_obj = datetime.strptime(date_time_str, '%Y%m%d %H%M%S') + +# Date : Y/M/D +print('Date : {}'.format(date_time_obj.date())) +print('Year : {}'.format(date_time_obj.year)) +print('Month : {}'.format(date_time_obj.month)) +print('Day : {}'.format(date_time_obj.day)) +# Date : 2012-02-13 +# Year : 2012 +# Month : 2 +# Day : 13 + +# Time : H/M/S +print('Time : {}'.format(date_time_obj.time())) +print('Hour : {}'.format(date_time_obj.hour)) +print('Minute : {}'.format(date_time_obj.minute)) +print('Second : {}'.format(date_time_obj.second)) +# Time : 18:09:30 +# Hour : 18 +# Minute : 9 +# Second : 30 + +# weekday +print('Weekday : {}'.format(date_time_obj.weekday())) +print('Weekday by string: {}'.format(date_time_obj.strftime('%A'))) +# Weekday : 0 +# Weekday by string: Monday +``` + + +## 4. ISO format + : date 객체의 정보를 'YYYY-MM-DD' 형태의 문자열로 반환하며, + 월을 12개월의 월이 아닌, 누적 주의 수로 표현 가능하다. + +```python +date_time_now = datetime.now() +print('ISO format : {}'.format(date_time_now.isoformat())) # iso format을 사용하면, 월요일을 1부터 시작한 값으로 반환해준다 +print('ISO Weekday : {}'.format(date_time_now.isoweekday())) # +print('ISO calender : {}'.format(date_time_now.isocalendar())) # (YYYY, num_week, weekday) + +# ISO format : 2020-09-20T19:02:11.213896 +# ISO Weekday : 7 +# ISO calender : (2020, 38, 7) +``` + +## 5. Apply dateTime type to Columns + : 컬럼에 dateTime type을 적용하는 방법을 살펴보자 +```python +# 1) column type to 'datetime65[ns]' (시,분,초) +## "20120213" -> 2012-02-13 00-00-00 +df['date'] = pd.to_datetime(df['date'], format='%Y%m%d') + +# 2) column type to 'date'(날짜) +## "20120213" -> 2012-02-13 +df['date'] = pd.to_datetime(df['date'], format='%Y%m%d').dt.date +``` + +#### Reference +[1]https://www.programiz.com/python-programming/datetime/strftime +[2] https://devanix.tistory.com/306 diff --git a/_posts/cate_04_Preprocess/2020-10-20-Prep-np_where.md b/_posts/cate_04_Preprocess/2020-10-20-Prep-np_where.md new file mode 100644 index 00000000000..8164e68d139 --- /dev/null +++ b/_posts/cate_04_Preprocess/2020-10-20-Prep-np_where.md @@ -0,0 +1,76 @@ +--- +layout: post +title: (Prep) np.where()&np.Select() +date : 20 Oct 2020 +category : Preprocess +comments : true +--- + +## 1. np.where() + : 특정 조건에 따라 행별로 연산을 다르게 하고 싶을 때, 특정 컬럼의 값을 조건으로하여 연산하기. + + +```python +# np.where(조건문, True일 때 값, False일 때 값 ) +np.where(condition, + value if condition is true, + value if condition is false) +``` + +### simple test code + + + +```python +import pandas as pd +import numpy as np + +""" +col_1 == 1일때, col_3 = col_1 * col_2 +col_1 == 0일때, col_3 = col_2 +""" + +df_tmp = pd.DataFrame({'col_1' : [0,1,1,0], + 'col_2' : [2,4,3,2], + 'col_3' : [1,2,4,2]}) + +# using np.where +df_tmp['col_3'] = np.where(df_tmp['col_1'] == 1, + (df_tmp['col_1'] * df_tmp['col_2']) , + (df_tmp['col_1'])) +df_tmp +``` + +## 2. np.select() +: 복잡한 또는 다수의 조건을 활용해, 판다스 컬럼 생성하기 (More Complicated Conditions using np.select()) + +```python +import numpy as np +import random + + +# make sample data +df = pd.DataFrame({'col_1' : [random.randrange(1, 11) for i in range(10)], + 'col_2' : [random.randrange(1, 11) for i in range(10)], + 'col_3' : [random.randrange(1, 11) for i in range(10)]}) + +# create a list of our conditions +conditions = [ + (df['col_1'] <= 3), + (df['col_1'] > 3) & (df['col_1'] <= 7), + (df['col_1'] > 7) + ] + +# create a list of the values we want to assign for each condition +values = [(df['col_1'] * df['col_2']), + (df['col_1'] / df['col_2']), + df['col_3']] + +# create a new column and use np.select to assign values to it using our lists as arguments +df['col_4'] = np.select(conditions, values) +df.head() +``` + + +#### Reference +[1] [Adding a Pandas Column with a True/False Condition Using np.where()](https://www.dataquest.io/blog/tutorial-add-column-pandas-dataframe-based-on-if-else-condition) diff --git a/_posts/cate_04_Preprocess/2020-10-30-Utils-AddingValue_in_two_list.md b/_posts/cate_04_Preprocess/2020-10-30-Utils-AddingValue_in_two_list.md new file mode 100644 index 00000000000..98674f74f65 --- /dev/null +++ b/_posts/cate_04_Preprocess/2020-10-30-Utils-AddingValue_in_two_list.md @@ -0,0 +1,69 @@ +--- +layout: post +title: (Utils) Adding values ​​in two lists +date : 30 Oct 2020 +category : Preprocess +comments : true +--- + +## Q Adding values in two lists + : 두개의 리스트 내부에 있는 값들을 더하는 너무 간단한 문제이다. + 그러나 생각보다 코드가 길어져서 골머리를 앓다가, `zip`을 사용하니 허무하게도 쉽게 문제가 해결되었다. + +## zip + : `zip`은 동일한 개수로 이루어진 자료형을 묶어 주는 역할을 한다. + +```Python +list_A = [1,2,3,4] +list_B = ['a', 'b', 'c', 'd'] + +list(zip(Number,name)) +# [(1,'a'),(2,'b'),(3,'c'),(4,'d')] + +# make dict using zip +dic +for key, value in zip(list_A, list_B) : + dic[key] = value +print(dic) +# {1:'a', 2:'b', 3:'c', 4:'d'} + +``` +이렇게, 2개의 객체에서 순서대로 값을 하나씩 빼서 묶어주므로, +zip을 사용하면, 2개의 리스트의 각 원소별로 더할 수 있다! + + +## Adding values in two lists using 'zip' +zip을 사용한 리스트내 원소간 합 코드는 아래와 같다. +```Python +list_1 = [1,3,5,7] +list_2 = [10,20,30,40] + +[x + y for x, y in zip(list_1, list_2)] + +# [11, 23, 35, 47] +``` + +# ETC +## dict.items() : Get keys & Values from dictionary + : 키(Key) & 값(Value) 쌍을 리턴 +```python +dict_tmp = {"철수": 90, "민수": 85, "영희": 80} +# dict_items([('민수', 85), ('영희', 80), ('철수', 90)]) +``` + +## enumerate(list) : Get Index & Value from list +: 리스트내 인덱스(Index) & 값(Value) 쌍을 리턴. +```python +lst_tmp = ['a', 'b', 'c'] +for idx, value in enumerate(lst_tmp) + print(idx, value) +# 0,'a' +# 1,'b' +# 2,'c' +``` + + + +#### Reference +[1] [Python zip 내장함수](https://medium.com/@hckcksrl/python-zip-%EB%82%B4%EC%9E%A5%ED%95%A8%EC%88%98-95ad2997990) +[2] [Add SUM of values of two LISTS into new LIST](https://stackoverflow.com/questions/14050824/add-sum-of-values-of-two-lists-into-new-list) diff --git a/_posts/cate_04_Preprocess/2020-11-30-Prep-Standardize_Normalize_Regularization.md b/_posts/cate_04_Preprocess/2020-11-30-Prep-Standardize_Normalize_Regularization.md new file mode 100644 index 00000000000..4e386cdf316 --- /dev/null +++ b/_posts/cate_04_Preprocess/2020-11-30-Prep-Standardize_Normalize_Regularization.md @@ -0,0 +1,158 @@ +--- +layout: post +title: (Prep) Standardize vs Normalize vs Regularize +date : 30 Nov 2020 +category : Preprocess +comments : true +--- + : 데이터 전처리 단계에서 변수별 스케일이 서로 다르기에 이를 조정하기 위한 sclaling과정을 자주 거치게 된다. 위 3가지 방법은 데이터를 학습이 용이한 형태로 변형한다는 유사점을 갖고 있지만, 각 방법마다 상황에 맞게 사용하기 위해서 차이점을 구분해보자. + +# 1. Rescale +## 1) Normalization +#### (1) min-max Normalization[0~1] +**- 목표** : 데이터의 상대적 크기에 대한 영향력을 줄이기 +: Normalization은 변수의 스케일(scaling)을 [0,1]로 재조정한다. +- 특히 변수 1개 보다, 여러개의 변수가 서로 비교되어야 할 때, 특정 변수의 단위가 너무 커 상대적 영향력이 과대 평가되는 것을 방지하기 위해 사용됨. +- 단, 각 변수내에 이상치가 없다는 가정하에 사용하는 것이 적절하다. + +
+ + $x' = \dfrac{x - min(x)}{max(x) - min(x)}$ + +
+ +```python +from sklearn.preprocessing import MinMaxScaler +scaler = MInMaxScaler() +df[:] = scaler.fit_transform(df[:]) +df[:] = scaler.fit_transform(df['col_1']) # 하나의 열에 한하여 Normalization을 진행하고 싶은 경우, +``` + +#### (2) Mean Normalization[-1~1] +**- 목표** : 데이터가 평균보다 큰지 작은지 표현(이상치에 영향을 받을 가능성 존재) +: 영화 선호 평가(rating)처럼 데이터의 값이 {1,2,3,4,5}와 같은 경우, 평균값을 기점으로 평균이하에는 음의 수치를, 이상에는 양의 수치를 주고 적용하고 싶은 경우 Mean Normalization이 더 적절하다. +
+ + $x' = \dfrac{x - mean(x)}{max(x) - min(x)}$ + +
+ +
+ +## 2) Standardization(표준화) +**- 목표** : 데이터가 평균으로부터 떨어진 정도를 표현 +: Standardization(표준화)는 '전처리' 단계에서 변수의 평균을 0으로 조정하고 개별 단위 분산으로 값을 재조정(scaling)하기 위해 자주 사용된다. +표준화를 거쳐 +/-1.96(또는2)를 넘는 데이터 제거할 수 있음. + +
+ +$x' = \dfrac{x - \mu}{\sigma}$ + +
+```python +from scipy import stats +df['col_std'] = stats.zscore(df['col_raw']) +df = df[df['col_std'].between(-2,2)] # outlier detection +``` + +
+ +###### \+ 위 방법들은 독립적이지 않고, 아래와 같이 두 방법을 모두 거쳐 사용하기도 한다. + + - (1) Standardization(표준화)으로 outlier 제거하기 + - (2) Normalization(정규화)으로 scale의 상대적 크기 영향력을 줄여 분석에 투입 + +--- + +# 2. Regularization +: 위에서 언급한 Normalization & Standardization은 스케일링의 개념만을 갖고 있다면, + Regularization은 'Overfitting'의 문제를 해결하기 위해 등장한다. 모델에 추가적인 loss Function(손실 함수)을 추가함으로써, 모델의 파라미터가 더 작은 값으로 수렴하게 되어(중요하지 않은 변수의 영향력 축소) 과적합을 현저하게 낮추는 효과를 갖는다. + + ```python + import numpy as np + from sklearn import preprocessing + X = np.asarray([ + [-1,0,1], + [0,1,2]], + dtype=np.float) # Float is needed. + + # Before-normalization. + print(X) + # Output, + # [[-1. 0. 1.] + # [ 0. 1. 2.]] + ``` + +### 1) L1-Norm : Lasso +**- 목표** : 절대값 함수는 0에서 미분이 불가하기에, Sparse한 모델을 트레이닝할때, 불필요한 변수의 파라미터를 완전히 0으로 만들 수 있어 차원을 줄이는데 유용합니다. + +
+ +${\lVert x \rVert}_p = \sqrt[p]{\sum_{i = 1}^{n} {\lvert x_i \rvert}^p}$ +
+ + ```python + X_normalized_l1 = preprocessing.normalize(X, norm='l1') + print(X_normalized_l1) + # [[-0.5 0. 0.5] + # [ 0. 0.3 0.67]] + + # Absolute value of all elements/features. + X_abs = np.abs(X_normalized_l1) + print(X_abs) + # [[0.5 0. 0.5] + # [0 0.3 0.67]] + + # Sum over the rows. + X_sum_abs = np.sum(X_abs, axis=1) + print(X_sum_abs) + # Output, + # [ 1. 1.] + + # Yay! Each row sums to 1 after being normalized. + ``` + +**- 목표** : 반면 L2는 변수의 파라미터를 완전히 0으로 만들지 않기에, +주어진 조건이 명확하지 않거나 부족한 *ill-posed problem*에서 더 자주 선호됩니다. +
+ + : $F(x) = f(x) + \lambda {\lVert x \rVert}_2^2$ +
+ + +```python +# l2-normalize the samples (rows). +X_normalized = preprocessing.normalize(X, norm='l2') + +# After normalization. +print(X_normalized) +# Output, +# [[-0.70710678 0. 0.70710678] +# [ 0. 0.4472136 0.89442719]] + +# Square all the elements/features. +X_squared = X_normalized ** 2 +print(X_squared) +# Output, +# [[ 0.5 0. 0.5] +# [ 0. 0.2 0.8]] + +# Sum over the rows. +X_sum_squared = np.sum(X_squared, axis=1) +print(X_sum_squared) +# Output, +# [ 1. 1.] + +# Yay! Each row sums to 1 after being normalized. +``` + +
+-comparison between L1 and L2 regularizations- + + + +
+ +#### Reference +[1] [Differences between Normalization, Standardization and Regularization](https://maristie.com/2018/02/Normalization-Standardization-and-Regularization) +[2] [데이터 표준화(Standardization), 정규화(Normalization) 차이점](https://soo-jjeong.tistory.com/123) diff --git a/_posts/cate_04_Preprocess/2021-01-19-Vars-dynamically_create_variable.md b/_posts/cate_04_Preprocess/2021-01-19-Vars-dynamically_create_variable.md new file mode 100644 index 00000000000..ed475e2c7f7 --- /dev/null +++ b/_posts/cate_04_Preprocess/2021-01-19-Vars-dynamically_create_variable.md @@ -0,0 +1,44 @@ +--- +layout: post +title: (Vars) Dynamically_create_variable +date : 19 Jan 2021 +category : Preprocess +comments : true +--- + : 여러개의 변수를 loop문을 활용하여 자동으로 생성하는 방법. + +# 1. Dynamically create variable + +## 1) globals() 함수 +: `globals()`함수를 사용하여, 동적으로 변수를 생성 할 수 있다. + +```python +nm_list = ['cat', 'dog', 'rat'] +i = 0 +for nm in nm_list : + globals()[nm] = [x for x in range(i)] + +# cat = [0] +# dog = [0,1] +# rat = [0,1,2] +``` + +## 2) format() 활용하기 + : 할당 과정에서 format() 함수를 사용해, 규칙성을 있는 변수 목록 생성하기 +```python +nm_list = ['cat', 'dog', 'rat'] + +i = 0 +for nm in nm_list : + i += 1 + globals()['animal_{}'.format(nm)] = [x for x in range(i)] + +# animal_cat = [0] +# animal_dog = [0,1] +# animal_rat = [0,1,2] +``` + + + +#### Reference +[1] [변수 이름을 loop 돌려서 할당하기](http://blog.naver.com/PostView.nhn?blogId=nomadgee&logNo=220857820094&parentCategoryNo=&categoryNo=57&viewDate=&isShowPopularPosts=false&from=postView) diff --git a/_posts/cate_04_Preprocess/2021-03-18-Vars-Nan_vs_None.md b/_posts/cate_04_Preprocess/2021-03-18-Vars-Nan_vs_None.md new file mode 100644 index 00000000000..aee6de8f044 --- /dev/null +++ b/_posts/cate_04_Preprocess/2021-03-18-Vars-Nan_vs_None.md @@ -0,0 +1,41 @@ +--- +layout: post +title: (Vars) Nan vs None +date : 18 Mar 2021 +category : Preprocess +comments : true +--- +: 무심코 Nan과 None을 동일한 존재로 생각하고 있었다. +그러다, 분명 모든 결측치를 제거하였는데, 아래와 같은 에러가 뜨는 것을 확인하였다. +``` +Value too large for dtype('float64') sklearn.preprocessing .StandardScaler() +``` +문제의 원인은 무한대 값이 포함되어 있는 것이었으나, 이 과정에서 무한대가 Nan으로도 표현될 수 있다는 글을 보고 두 표기의 차이점을 확인해보고자 한다. + +## 1. None +##### `None` = `NULL` +: 타 프로그램의 Null값으로, 즉 아무것도 없는 데이터를 의미한다. +```python +# None 확인 방법 +a = None + +import pandas as pd +pd.isnull(a) +``` + + +## 2. NaN +##### `NaN` = `Not A Number` +: 반면 `NaN`은 표현되지 않은 부동소수점 값으로, Python에서는 `float`타입이 됨. +```python +# nan 확인 방법 +b = float('Nan') + +import math +math.isnan(b) +``` + + +#### Reference +[1] [(python)None, NaN에 대해서](https://purplechip.tistory.com/5) +[2] [Value too large for dtype('float64') sklearn.preprocessing .StandardScaler()](https://stackoverflow.com/questions/45886312/value-too-large-for-dtypefloat64-sklearn-preprocessing-standardscaler) diff --git a/_posts/cate_04_Preprocess/2021-05-10-Utils-generator_yield.md b/_posts/cate_04_Preprocess/2021-05-10-Utils-generator_yield.md new file mode 100644 index 00000000000..75eb22bc1bb --- /dev/null +++ b/_posts/cate_04_Preprocess/2021-05-10-Utils-generator_yield.md @@ -0,0 +1,171 @@ +--- +layout: post +title: (Utils) generator & yield +date : 10 May 2021 +category : Preprocess +comments : true +--- +# 1. why use generator? +### (1) Memory issue +: for-loop는 , 돌아야하는 list전체를 메모리에 올려놓은 상태로 작업을 시작하게된다. 때문에 list의 크기가 큰 경우, 차지하는 메모리가 커진다. + 반면, generator는 값을 한꺼번에 메모리에 적재 하지 않고, next() 메소드를 통해 차례로 값에 접근할 때마다 메모리에 적재한다. + +```python +import sys +sys.getsizeof( [i for i in xrange(100) if i % 2] ) # list +# 536 +sys.getsizeof( [i for i in xrange(1000) if i % 2] ) +# 4280 + +sys.getsizeof( (i for i in xrange(100) if i % 2) ) # generator +# 80 +sys.getsizeof( (i for i in xrange(1000) if i % 2) ) +# 80 +``` + +### (2) Lazy evaluation : 계산 결과 값이 필요할 때까지 계산을 늦추는 효과 +: 아래 예제를 보면, 일반 list는 list 내부 함수를 먼저 실행하여 값들을 모두 대기시켜놓은 후 for문을 통해 하나씩 추출한다. 때문에 리스트 내부의 함수 연산이 오래걸린다면, for문 자체의 실행이 늦춰진다. +```python +# list 생성 +list = [sleep_func(x) for x in xrange(3)] +for i in list: + print i + +# <결과> +# sleep... # (1) list : 내부 [sleep_func(x) for x in xrange(5)] 함수 먼저 실행 +# sleep... +# sleep... +# 0 # (2) list : 이후 for loop 실행 +# 1 +# 2 +``` +반면, generator는 for문이 수행 될 때마다 추출해야하는 값의 연산을 그때 그때 진행하기에 수행 시간이 긴 연산을 필요한 시점까지 늦출 수 있다는 특징이 있다. +```python +# generator 생성 + +gen = (sleep_func(x) for x in xrange(3)) +for i in gen: + print i + +# <결과> +# sleep... # (1-1) generator 추출할 첫번째 값의 함수 실행 +# 0 # (1-2) 이후 for loop 진행 +# sleep... # (2-1) generator 추출할 두번째 값의 함수 실행 +# 1 # (2-2) 이후 for loop 진행 +# sleep... +# 2 +``` +
+따라서, 크기가 크거나 for문에 들어갈 list의 연산이 복잡할 경우에 generor를 사용하면, 메모리 및 속도 측면에서 효율적으로 활용할 수 있다.
+ + +# 2. How to use generator? +### (1) 함수로 생성 +: generator를 생성하는 방법은 2가지가 있다. +첫번째는 for loop를 통해 값을 하나씩 반환하는 일반 함수를 생성하되, 반횐하는 함수를 `return` 대신 `yield` 를 사용하는 방법이다. +```python +# data +df = pd.DataFrame( + key_id : ['a','b','c'], + value : [1,2,3] + ) + +# make generator +def gen(df_tmp) : + for idx in df_tmp['key_id'] : + yield idx +idx_gen = gen(df_tmp) + +# use generator by 'next' +while True : + try : + next(idx_gen) + except StopIteration : + break +``` + + +### (2) Generator expression +두번째는 generator expression를 사용하는 방법이다. +```Python +# make generator by generator expression +idx_gen = ( i for i in df_tmp.index ) + +# use generator by 'next' +next(idx_gen) +``` + + +# 3. What is generator? +시간이 좀 있다면, generator가 어떻게 작동하는지도 자세히 살펴보자. +generator는 iterator 를 생성해 주는 function으로 `next()` 메소드를 사용해, 데이터에 순차적으로 접근가능한 'object'다. generator자체를 만드는데 있어서는 return 대신 yield라는 구문을 사용한다는 점을 제외하면 일반 함수와 큰 차이점이 없다. + +그렇다면, `yield`와 일반 함수의 `return`의 차이점을 살펴보자 + - `return` : 함수 사용이 종료되면, 결과값을 호출하여 반환(return)후 함수 자체를 종료한다.(즉, 함수가 완전히 모두 실행 후 종료) + - `yield` : + (1) 특정함수(주로 generator함수)가 `yield`를 만나게 되면, + (2) 그 기점에서 함수를 잠시 정지 후 반환값을 `next()`를 호출한 쪽으로 전달한다. + (3) 이후 함수는 종료되지 않고, 유지된 상태로 남아있게 된다. + +아래 예시를 살펴보자. +```python +def generator(n) : + i = 0 + while i < n : + yield i + i += 1 + +for x in generator(5) : + print(x) + +# <결과> +# 0 +# 1 +# 2 +# 3 +# 4 + +# (1) for 문이 실행되며, 먼저 generator 함수가 호출된다. +# (2) generator 함수는 일반 함수와 동일한 절차로 실행된다. +# (3) 실행 중 while문 안에서 yield 를 만나게 된다. 그러면 return 과 비슷하게 함수를 호출했던 구문으로 반환하게 된다. 여기서는 첫번재 i 값인 0 을 반환하게 된다. 하지만 반환 하였다고 generator 함수가 종료되는 것이 아니라 그대로 유지한 상태이다. +# (4) x 값에는 yield 에서 전달 된 0 값이 저장된 후 print 된다. 그 후 for 문에 의해 다시 generator 함수가 호출된다. +# (5) 이때는 generator 함수가 처음부터 시작되는게 아니라 yield 이후 구문부터 시작되게 된다. 따라서 i += 1 구문이 실행되고 i 값은 1로 증가한다. +# (6) 아직 while 문 내부이기 때문에 yield 구문을 만나 i 값인 1이 전달 된다. +# (7) x 값은 1을 전달 받고 print 된다. (이후 반복) +``` + +# 4. Usage +## 1) list_sum +: generator와 dictionary 자료구조를 사용해 시간을 단축한 예제다. +무수히 많은 리스트가 존재하고, 해당 원소들의 개수를 모두 더해서 카운트해야하는 문제에서 많은 리스트를 제너레이트로 변환하고, +원소들을 dictionary형태의 key값으로 지정하여 개수를 카운트하였다. +```python +def generate_list_sum(target_idx) : + """ + : [a,b,c] + [a,b,f] = {a : 2, b = 2, c = 1, f = 1} + """ + gen_list = (i for i in target_idx) + dict_counter = {} + while True : + try : + l = next(gen_list) + for k in l : + try : + dict_counter[k] += 1 + except : + dict_counter[k] = 0 + except StopIteration : + break + return dict_counter +``` + + + + + + + + + +#### Reference +[1] [python generator(제너레이터) 란 무엇인가](https://bluese05.tistory.com/56) diff --git a/_posts/cate_04_Preprocess/2021-06-20-Multiprocess-multiprocess_pool_n_process.md b/_posts/cate_04_Preprocess/2021-06-20-Multiprocess-multiprocess_pool_n_process.md new file mode 100644 index 00000000000..e6631bcd37d --- /dev/null +++ b/_posts/cate_04_Preprocess/2021-06-20-Multiprocess-multiprocess_pool_n_process.md @@ -0,0 +1,178 @@ +--- +layout: post +title: (Multiprocess) Pool vs Process +date : 30 Jun 2021 +category : Preprocess +comments : true +--- + : 일부 반복적인 작업 과정에서 1개의 Process만을 사용함에 따라, 작업시간이 오래걸리는 문제를 해결하기 위해 MultiProcessing에 대해서 공부해보고자한다. + +# 1. Multi-Processing vs Multi-Thread + +### (1) Thread?? Processing?? +: MultiProcessing에 앞서서, 우선 Thread와 Processor에 대한 정의와 차이부터 살펴보자. 컴공 지식에 대해서는 잘 모르기에, 내가 알 수 있는 깊이에서 둘 간의 차이점을 살펴보자. + +| | Thread | Processe | +|---|---|---| +|정의| 프로세스내에서 실제로 작업을 수행하는 주체 | 실행 중인 프로그램 | +| | 모든 프로세스에는 한개 이상의 스레드(thread)가 존재하여 작업을 진행함. | 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것. | +| | 하나의 프로세스에 2개 이상의 스레드(thread)를 갖는 것을 multi-Thread process라고함. | 프로세스는 프로그램에 사용되는 '데이터', '메모리 등의 자원', '스레드'로 구성됨.| +|메모리 공유| 메모리를 공유하여, 각 cpu가 서로의 상태를 공유할 수 있음. | 메모리를 공유하지 않음 | +|Interrupt &kill| Interrupt & kill 불가능 | 메모리를 공유하여, 각 cpu가 서로의 상태를 공유할 수 있음. | +|Thread의 장점| 1) 프로세스보다 생성 및 종료시간, 쓰레드간 전환시간이 짧다. | | +| | 2) 프로세스의 메모리, 자원등을 공유하기에, 커널의 도움 없이 상호통신이 가능하다. | | + +여기까지 살펴보았을 때, 우리의 목표는 하나의 파이썬이라는 프로세스(프로그램)에서 여러개의 쓰레드를 띄워 필요한 작업을 병렬로 처리하면 될 것으로 보인다. + +### (2) GIL(Global Interpreter Lock) + : 그러나 슬프게도(?) 파이썬에서는 여러개의 쓰레드를 사용하는 Multi-Thread를 지원하지 않는다. + 파이썬은 global변수로 하나의 인터프리터가 실행된다. 만약 쓰레드가 동시에 작동한다면, global변수를 함께 공유하게 될 것이고, 특정 스레드가 global변수를 변경할시, 동일한 변수에 접근해있던 다른 쓰레드는 엉망이 되어버릴 것이기에 *한번에 하나의 Thread만이 인터프리너 내부의 global변수에 접근할 수 있도록 해놓았다.(GIL)*(하나의 thread만이 접근가능한 일부 틀릴 수 있음.) + + 따라서 파이썬에서는 Multi Thread를 사용하더라도, Lock으로 인하여 한번에 하나의 Thread만 실행되기에, 되려 Multi core CPU라고 하더라도 실행시간이 효과가 없거나 되려 늘어나버릴 수 있다. + + 그렇다고 Multi-Thread를 사용할 수 없는 것은 아니다. GIL이 적용도니느 것은 CPU동작에 한해서이며, 쓰레드가 CPU동작을 마치고 I/O작업을 실행하는 동안에는 다른 쓰레드가 CP동작을 동시에 실행 할 수 있다. 따라서 CPU동작이 많지 않고 I/O동작이 더 많은 프로그램에서는 Multi-Thread를 사용하여 큰 효과를 볼 수 있다. (다만 나는 어떤 작업이 CPU가 적고 I/O가 많은지 구별하지 못한다...) + + +# 2. Multi-Processing + : 앞선 이유로 Multi-Thread 사용은 제한되지만, `multiprocessing`패키지를 사용하면, 프로세스 자체를 복수로 생성하여 보유하고 있는 CPU를 병렬로 사용할 수 있다. `multiprocessing`는 아래 두가지 방식으로 사용 가능하며, 각 수행해야 하는 테스크에 따라 적합한 방식이 달라진다. + - multiprocessing : Pool + - multiprocessing : Process + +## 1) Pool + : Pool은 FIFO(first in, first out) 방식으로 업무를 사용가능한 Processor에게 분배한다. map-reduce방식과 유사하게 작업을 각기 다른 프로세서에게 맵(map)하고, 각 결과를 다시 수집한후(reduce) 결과를 list or array형태로 출력한다. pool은 각 프로세스가 맡은 모든 작업이 끝날 때까지 기다린후 결과를 수집하여 반환하며, 메모리 측면에서 pool은 프로세스에 할당된 작업은 메모리에 올라가지만 실행되지 않은 작업은 메모리에 올라가지 않는다. + - 작동 방식 : 각 프로세스가 맡은 모든 작업이 끝날 때까지 기다린후 결과를 수집하여 반환 + - output type : list or array + - memory :프로세스에 할당된 작업만 메모리에 올라가며(stored in), 그외의 작업은 메모리에서 제외됨(stored out) + +## 2) Process + : 반면 프로세스에 모든 프로세스를 메모리를 올려두고, 작업들을 FIFO 방식으로 스케쥴링한다. + - output type : list or array + - memory :모든 프로세스가 메모리에 올라감 + + +# 3. [Pool vs Process] 무엇을 써야할까? +- `multiprocessing.pool` : 병렬로 작업해야하는 작업량이 *많으*나 'I/O operation'이 작을 때 +- `multiprocessing.process`: 병렬로 진행해야 하는 작업량이 *적고*, 각 작업이 한번만 진행되면 되는 상황 + +## 1) Task Number + : pool은 실행중인 작업만을 memory에 올려 두기에 task가 많아도 메모리를 모두 차지하지 않는다. 반면 Process는 실행해야하는 모든 작업을 한번에 memory에 올려두기에 작업량이 많으면 메모리 문제를 발생시킬 수 있다. + +## 2) I/O operation + : pool은 각 process들을 FIFO 방식으로 CPU core에 할당하고, 할당된 process는 순자적으로 실행된다. 따라서 이때 시간이 길게 소요되는 I/O Operation이 있다면, Pool은 I/O operation이 끝날 때 까지 기다리며 process들의 스케쥴을 잡지 않게된다. 이는 결국 큰 시간 소요로 이어지게 된다. 반면 process class는 I/O operation 실행을 잠시 중지하며, 다른 process의 스케쥴을 잡기에 I/O 작업이 길어도 비효율적으로 시간을 소모하지 않는다. + +# 4. Multi-Processing Code +```python +import numpy as np +import multiprocessing +import time + +# 전체 작업량 +task = list(range(100000000)) +``` + +## 0) single core +```python +start_time = time.time() +output = 0 +gen = (i for i in task) +for i in gen : + output += i +print("---%s second ---"% (time.time() - start_time)) +# ---9.102992296218872 second --- +``` + +## 1) multiprocess.pool +```python +# 1. 작업 분할 및 process 개수 지정 +## 1) 코어 개수 생성 +n_process = 4 #calc_n_procs_core(task) + +## 2) 작업분항(job_list) 생성 +job_list = np.array_split(task, n_process) + +# 2. multiprocess +## 1) 실행할 작업 함수 +def list_sum(target_lst) : + output = 0 + gen = (i for i in target_lst) + for i in gen : + output += i + return output + +## 2) multiprocess.pool 객체 생성 +start_time = time.time() + +if __name__ == '__main__' : + lst_tmp = [] + # multiprocess + + pool = multiprocessing.Pool(processes = n_process) + lst_pool = pool.map(list_sum, job_list) + pool.close() + pool.join() +print(sum(lst_pool)) +print("---%s second ---"% (time.time() - start_time + +# 4999999950000000 +# ---7.931491851806641 second --- +``` + +## 2) multiprocess.Prcoess +```python +# 1. 작업 분할 및 process 개수 지정 +## 1) 코어 개수 생성 +# n_process = 4 #calc_n_procs_core(task) + +## 2) 작업분항(job_list) 생성 +job_list = np.array_split(task, n_process) + +# 2. multiprocess +## 1) 각 프로세스에서 반환한 Output을 list형태로 묶어주기 위해서 manager 메서드 사용 +manager = multiprocessing.Manager() +fin_list = manager.list() + +## 2) 실행할 작업 함수 +def list_sum(target_lst) : + output = 0 + gen = (i for i in target_lst) + for i in gen : + output += i + fin_list.append(output) + return output + +## 3) multiprocess.process 객체 생성 +def multiProcess_main() : + procs = [] + for _job in job_list : + lst_tmp = [] + # multiprocess + proc = multiprocessing.Process(target = list_sum, args = (_job,)) + procs.append(proc) + proc.start() # 프로세스 시작 + + for proc in procs : + proc.join() # 프로세스 종료 + +start_time = time.time() +if __name__ == '__main__' : + multiProcess_main() + +print(sum(list(fin_list))) +print("---%s second ---"% (time.time() - start_time)) +#4999999950000000 +#---6.672454118728638 second --- +``` + + + + + +#### Reference +##### 1. Multi-Processing vs Multi-Thread +[1] [Thread란?](http://tcpschool.com/java/java_thread_concept) +[2] [Thread와 MultiProcessing 차이점](https://www.ellicium.com/python-multiprocessing-pool-process) +##### 2 & 3 . Multi-Processing +[1] [Python Multiprocessing: Pool vs Process – Comparative Analysis](https://www.ellicium.com/python-multiprocessing-pool-process) + +##### 4. Multi-Processing Code +[1] [[Python] 병렬처리(Multiprocessing)를 통한 연산속도 개선](https://yganalyst.github.io/data_handling/memo_17_parallel/) diff --git a/_posts/cate_04_Preprocess/2022-10-30-Prep-transpose_dataframe_shape.md b/_posts/cate_04_Preprocess/2022-10-30-Prep-transpose_dataframe_shape.md new file mode 100644 index 00000000000..7765d887e7a --- /dev/null +++ b/_posts/cate_04_Preprocess/2022-10-30-Prep-transpose_dataframe_shape.md @@ -0,0 +1,126 @@ +--- +layout: post +title: (Prep) Transpose DataFrame Shape (wide <-> long) +date : 30 Oct 2022 +category : Preprocess +comments : true +--- + : 일상적인 데이터는 주로 각 피쳐를 column으로 가져가지만, 시각화를 필요로하는 경우엔 각 피쳐값을 하나에 컬럼에 모아, 다시 새로운 변수로 할당해주는 형태인 long-form 형태의 데이터 변환이 필요하다. 이때 주로 사용하는 함수들이 상황에 따라 매번 햇갈려 정리가 필요했다. 해당 자료는 "rfriend" 내용을 정리하였다. + + +## 1. Long to Wide (pivoting) +### (1) pivot + : `pd.pivot`함수도 있으나, 기능이 유사하고 더 범용적인 `pivot_table`함수만 정리 +
+ +
+ +```Python +pd.pivot_table(df, index=, columns=, values=) +``` + - index + : wide 형태 데이터에서, 인덱스 역할을 할 컬럼 + - columns + : N개의 Column을 생성하기 위한, 정보를 가져올 Column + (2개 이상의 Column을 지정할 경우, 멀티 컬럼 형태의 WideFormData생성) + - values + : Column에서 지정한 필드에 상응하는 값이 존재하는 Column + - margins + : True로 설정시, 행과 열을 기준으로 합계(All, row sum, column sum)를 같이 제시 + + + +## 2. Wide to Long (melt) + : 주어진 WideFormData를 아래로 길게 녹여내듯 LongForm으로 변환 + +
+ +
+ + ```Python + pd.melt(data, id_vars=['id1', 'id2', ...]) + ``` + - id_vars + : longform 데이터의 인덱스 개념이 될 컬럼(column 레벨이며, index레벨이 아님.) + - var_name + : (default : None) Category or Group과 같이 값의 구분자가 될 필드명 + - value_name + : (default : value) value값 column명 + + + +## 3. Stack <-> Unstack + : 앞서 pivot과 melt함수는, transpose를 위해 기준이 되는 column들을 인자로 지정해주었던 반면, Stack & Unstack 함수는 어떤 데이터를 주어주던 필요한 형태로 변환하는 목적에 충실한 느낌이다. + + - Stack : wide to "long" + - Unstack : long to "wide" + +
+ +
+ +#### (1) Stack +```Python + pd.DataFrame.stack(level=-1, dropna=True) +``` +```Python +data_wide +# [output] +# cust_id prod_cd grade pch_amt +# 0 c1 p1 A 30 +# 1 c1 p2 A 10 +# 2 c1 p3 A 0 +# 3 c2 p1 A 40 +# 4 c2 p2 A 15 + +data_wide.set_index(['cust_id', 'prod_cd']).\ + stack(level = -1).to_frame().head(10) +# [output] +# 0 +# cust_id prod_cd +# c1 p1 grade A +# pch_amt 30 +# p2 grade A +# pch_amt 10 +# p3 grade A +# pch_amt 0 +# c2 p1 grade A +# pch_amt 40 +# p2 grade A +# pch_amt 15 +``` + +#### (2) UnStack +```Python + pd.DataFrame.stack(level=-1, dropna=True) +``` +```Python +data_long +# [output] +# 0 +# 0 grade A +# pch_amt 30 +# 1 grade A +# pch_amt 10 +# 2 grade A +# pch_amt 0 +# 3 grade A +# pch_amt 40 +# 4 grade A +# pch_amt 15 + + +data_long.unstack() +# grade pch_amt +# 0 A 30 +# 1 A 10 +# 2 A 0 +# 3 A 40 +# 4 A 15 + +``` + +#### Reference +[1] [데이터 재구조화_1 : pivot & pivot_table](https://rfriend.tistory.com/275) +[2] [데이터 재구조화_2 : melt](https://rfriend.tistory.com/278?category=675917) +[2] [데이터 재구조화_3 : stack & unstack](https://rfriend.tistory.com/276) diff --git a/_posts/cate_04_Preprocess/2023-02-24-Vars-local_global_var.md b/_posts/cate_04_Preprocess/2023-02-24-Vars-local_global_var.md new file mode 100644 index 00000000000..f56b87e8e9d --- /dev/null +++ b/_posts/cate_04_Preprocess/2023-02-24-Vars-local_global_var.md @@ -0,0 +1,58 @@ +--- +layout: post +title: (Error) Global variable 호출시, referenced before assignment에러 발생 +date : 24 Feb 2023 +category : Preprocess +comments : true +--- + +## 1. 문제 상황 +: 외부 함수에서 선언한 변수를, 다른 함수 내부에서 불러오기 위해 global로 해당 변수를 선언을 해주었다. +이후 다른 함수에서는 해당 변수가 문제없이 잘 불러와졌으나, 특정 함수에서만 global로 선언한 변수가 존재하지 않는 상태로 호출되었다는 "referenced before assignment" 에러가 발생하였다. + +```python +def global_func() : + global a + a = 10 +global_func() +``` + +```python +def local_func_1() : + print(a) +local_func_1() +# 10 # 정상 + +def local_func_2() : + a += 10 + print(a) +local_func_2() +# local variable 'a' referenced before assignment # Error 발생 +``` + + + +## 2. 문제 원인 +: 실제 `a`변수는 네임스페이스에 global로 존재하지만, `local_func_2` 함수의 `a += 10` 코드에서, Python은 새로운 지역변수를 할당하는 코드라고 인식하게 되면서, `a`라는 지역변수가 먼저 참조 되지 않았다고 에러를 발생시키는 것이다. +```python +def local_func_2() : + a += 10 # Python은 새로운 지역변수를 a를 할당하는 코드라고 인식하기에 이 함수 내에서 지역변수로 선언된 a 변수를 탐색함. + print(a) +local_func_2() +``` + + + +## 3. 문제 해결 +: 따라서 해당 변수를 사용하고자 한다면, 해당 함수 내부에서 해당 변수를 'global'로 선언해주어야 한다. +```python +def local_func_2() : + global a + a += 10 # Python은 새로운 지역변수를 a를 할당하는 코드라고 인식하기에 이 함수 내에서 지역변수로 선언된 a 변수를 탐색함. + print(a) +local_func_2() +# 20 +``` + +#### Reference +[1] [파이썬 referenced before assignment에러 이유와 해결 - 홍식의 개발 HDD님의 블로그](https://velog.io/@hongsikcho/%ED%8C%8C%EC%9D%B4%EC%8D%AC-referenced-before-assignment%EC%97%90%EB%9F%AC-%EC%9D%B4%EC%9C%A0%EC%99%80-%ED%95%B4%EA%B2%B0) diff --git a/_posts/cate_04_Preprocess/2023-02-27-Class-_instance_method_error.md b/_posts/cate_04_Preprocess/2023-02-27-Class-_instance_method_error.md new file mode 100644 index 00000000000..96d04818b2b --- /dev/null +++ b/_posts/cate_04_Preprocess/2023-02-27-Class-_instance_method_error.md @@ -0,0 +1,75 @@ +--- +layout: post +title: (Class) class내 instance method 중복 호출시 에러 +date : 27 Feb 2023 +category : Preprocess +comments : true +--- + +## 1. 문제 상황 +### 1) 문제 코드 +: 하나의 클래스에서 여러개의 instance method를 생성하고, 그 중 마지막 main에 해당하는 method가 상위 method를 내부에서 다시 호출하는 구조로 클래스를 만들어, 하나의 클래스의 main만 메소드만 실행하여 전체 메서드를 실행하고자 함. + +```python +class Parent : + def __init__(self) : + self.budget = 100 + + def child_1(self) : + self.budget -= 10 + + def child_2(self) : + self.budget -= 5 + + # 문제가 된 method + # instance method를 내부에 갖고 있는 instnce method + def family_main(self) : + Parent.child_1() + Parent.child_2() + print(self.budget) + + +parnet_inst = Parent() # instnace 생성 +parnet_inst.family_main()# main function 실행 +> TypeError: child_1() missing 1 required positional argument: 'self' +``` + +### 2) 발생 에러 +위와 같이 `parnet_inst.family_main` 메서드를 실행하자, `missing 1 required positional argument: 'self'` 해당 메서드가 self 인자를 필요로하는데 받지 못했다는 에러가 발생. + + +--- +## 2. 문제 원인 +: `family_main`안에 존재하는 `Parent.child_1`는 `Parent` 클래스의 '인스턴스 메서드'이다. +따라서 코드를 잘 살펴보면, + - Parent() 클래스를 `parent_inst`에 할당 + - 그러나 `family_main`내부의 메서드를 호출할 땐, 할당한 인스턴스의 이름인 `parent_inst`가 아닌 클래스명이 `Parent`로 호출하고 있음. + + +--- +## 3. 문제 해결 + : 동일한 클래스의 인스턴스 메서드끼리 호출할 때는, 클래스명을 다시 호출하는 것이 아니라, 'self'를 클래스명으로 호출하면 가능하다. +```python +class Parent : + def __init__(self) : + self.budget = 100 + + def child_1(self) : + self.budget -= 10 + + def child_2(self) : + self.budget -= 5 + + def family_main(self) : + self.child_1() + self.child_2() + print(self.budget) + +Parent().family_main() +> 85 +``` + +#### Reference +[1] [TypeError: Missing 1 required positional argument: 'self' - stackfoverflow](https://stackoverflow.com/questions/17534345/typeerror-missing-1-required-positional-argument-self) +[2] [[Python] 메서드(method)와 스태틱/클래스 메서드(static/class method)](https://heytech.tistory.com/107) +[3] [35.3 클래스 메서드 사용하기 - 코딩 도장](https://dojang.io/mod/page/view.php?id=2380) diff --git a/_posts/cate_04_Preprocess/2023-04-07-Utils-lambda_map_filter_reduce.md b/_posts/cate_04_Preprocess/2023-04-07-Utils-lambda_map_filter_reduce.md new file mode 100644 index 00000000000..c949e2dd366 --- /dev/null +++ b/_posts/cate_04_Preprocess/2023-04-07-Utils-lambda_map_filter_reduce.md @@ -0,0 +1,135 @@ +--- +layout: post +title: (python-utils) lambda / map / filter / reduce +date : 07 Mar 2023 +category : Preprocess +comments : true +--- + +## 1. lambda + - 익명 함수 : 객체를 만들지 않기에, 메모리를 할당하지 않고 다음줄로 넘어가면 힙(heap)메모리 영역에서 증발 + - 일반 함수 : 함수는 객체를 만들고, 재사용을 위해 함수 이름(메모리)를 할당 + + > **[Formula]** + > `lambda x, y, ... : [인수를 활용한 표현식]]` + +**** +```python +## Ex_1) +lambda_sum = lambda a, b : a+b +lambda_sum(10,20) +# > 30 +``` + +## 2. map + - 게으른 연산을 진행하는 map iterator 객체로 리턴. + - generate와 유사하게 값을 next로 다음 iterator를 실행히며, generate는 list의 다음 값만 추출해준다면, map은 다음 값을 활용한 연산을 진행 + + > **[Formula]** + > `map(function, iterable)` + > - function : Return 값이 `True` or `Flase` 둘중 하나인 함수 + > - iterable : iterable 객체 + +```python +# input +lst = [1,2,3] +## Ex_1) map with labmda +list(map(lambda x+1 : lst)) +# > [2,3,4] + +## Ex_2) map with function +def func(x) : + return x + 10 +list(map(func(x), lst)) +# > [11, 12, 13] + +## Ex_2) 3항 연산자 (if else, else, else, ...) +li = [-3, -2, 0, 6, 8] +list(map(lambda x : 'positive' if x > 0 else ('negative' if x < 0 else 0) , li)) +# > ['음수', '음수', 0, '양수', '양수'] +``` + +**※ [게으른 연산]**
+ : 속도 자체는 더 느리지만, 한번에 list를 모두 메모리에 올리지 않고 실행에 필요한 다음 값만 메모리에 올리기에, 연산량이 많을 때 메모리 부하를 줄일 수 있음. + - next() 메소드로 데이터를 순차적으로 호출 가능한 object + - 마지막 데이터까지 불러오면, StopIteration exception 발생 + - 일반 `iterable`한 객체(ex. 리스트)를 `iterator`로 변환하려면, `iter()` 함수 사용 + + ```python + x = [1,2,3] + print(type(x)) # list ('iterable') + y = iter(x) + print(type(y)) # list ('iterator') + next(y) # 1 + next(y) # 2 + next(y) # 3 + next(y) # Error : StopIteration + ``` + + + +## 3. filter + - iterable 객체에서, **함수의 리턴값이 참**인 값만 반환 + - 따라서 함수의 return값은 + + > **[Formula]** + > `filter(function, iterable)` + > - function : Return 값이 `True` or `Flase` 둘중 하나인 함수 + > - iterable : iterable 객체 + +```python +# input +li = [-2, -3, 5, 6] + +## Ex_1) filter with labmda +list(filter(lambda x: x > 0, li)) +# > [5, 6] + +## Ex_2) filter with function +def func(x) : + return x > 0 +list(filter(func, li)) +# > [5, 6] +``` + + +## 4. reduce + - 여러 개의 데이터를 주로, **누적**집계 하기위해 사용 + > **[Formula]** + > `reduce(function, iterable)` + > - function : 누적자 + > - iterable : 루프를 돌면서 하나씩 가져오는 값(첫번째값이 초기값) + > - initializer(=None) : 초기값, (if initializer ==None, iterable contains only one item, the first item is returned. + +```python +from functools import reduce +# input +users = [ + {'mail': 'gregorythomas@gmail.com', 'sex': 'M', 'age': 73}, + {'mail': 'hintoncynthia@hotmail.com', 'sex': 'F', 'age': 29}, + {'mail': 'wwagner@gmail.com', 'sex': 'M', 'age': 51}, + {'mail': 'daniel79@gmail.com', 'sex': 'F', 'age': 32}, + {'mail': 'ujackson@gmail.com', 'sex': 'F', 'age': 42} + ] + +## Ex_1_1) No initialize +reduce(lambda x, y : x + y['age'], users) +# {'mail': 'gregorythomas@gmail.com', 'sex': 'M', 'age': 73} + 73 # Error +# -> 리스트의 첫번째 값을 초기값으로 사용했기에 `dict` + `int`가 되면셔 Error 발생 +## Ex_1_2) With initialize +reduce(lambda x, y : x + y['age'], users, 0) +# 0 + 73 +# 73 + 29 +# 73 + 29 + 51 + +## Ex_2) +reduce(lambda x, y : x + [y['mail']], users, []) +# [] + ['gregorythomas@gmail.com'] +# ['gregorythomas@gmail.com'] + ['hintoncynthia@hotmail.com'] +# ['gregorythomas@gmail.com', 'hintoncynthia@hotmail.com'] + ['wwagner@gmail.com'] + +``` + +#### Reference +[1] [T강의노트 03. 파이썬 lambda, map, filter, reduce, dic - 초보몽키의 개발공부로그](https://wayhome25.github.io/cs/2017/04/03/cs-03/) +[2] [파이썬 reduce 함수 사용법 - daleseo님](https://www.daleseo.com/python-functools-reduce/) diff --git a/_posts/cate_04_Preprocess/test.ipynb b/_posts/cate_04_Preprocess/test.ipynb new file mode 100644 index 00000000000..543a8887378 --- /dev/null +++ b/_posts/cate_04_Preprocess/test.ipynb @@ -0,0 +1,228 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "def func(x) :\n", + " return x + 10" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "li = [1,2,3] * 10000000" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.03553 sec\n" + ] + } + ], + "source": [ + "start = time.time()\n", + "\n", + "a = list(map(func , li))\n", + "\n", + "end = time.time()\n", + "print(f\"{end - start:.5f} sec\")" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 6]" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "li = [-2, -3, 5, 6]\n", + "## 1) filter with labmda \n", + "list(filter(lambda x: x > 0, li))\n", + "# > [5, 6]\n", + "\n", + "# ## 2) filter with function \n", + "# def func(x) :\n", + "# return x > 0\n", + "# list(filter(func, li))" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n" + ] + }, + { + "ename": "StopIteration", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m: " + ] + } + ], + "source": [ + "x = [1,2,3] \n", + "print(type(x)) # list ('iterable')\n", + "y = iter(x)\n", + "print(type(y)) # list ('iterator')\n", + "next(y) # 1\n", + "next(y) # 2\n", + "next(y) # 3\n", + "next(y) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['gregorythomas@gmail.com',\n", + " 'hintoncynthia@hotmail.com',\n", + " 'wwagner@gmail.com',\n", + " 'daniel79@gmail.com',\n", + " 'ujackson@gmail.com']" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from functools import reduce\n", + "users = [\n", + " {'mail': 'gregorythomas@gmail.com', 'sex': 'M', 'age': 73},\n", + " {'mail': 'hintoncynthia@hotmail.com', 'sex': 'F', 'age': 29},\n", + " {'mail': 'wwagner@gmail.com', 'sex': 'M', 'age': 51},\n", + " {'mail': 'daniel79@gmail.com', 'sex': 'F', 'age': 32},\n", + " {'mail': 'ujackson@gmail.com', 'sex': 'F', 'age': 42}\n", + " ]\n", + "\n", + "## ex_1_1) No initialize -> 리스트의 첫번째 값을 초기값으로 사용\n", + "reduce(lambda x, y : x + y['age'], users)\n", + "# {'mail': 'gregorythomas@gmail.com', 'sex': 'M', 'age': 73} + 73 # Error\n", + "## ex_1_2) With initialize\n", + "reduce(lambda x, y : x + y['age'], users, 0)\n", + "# 0 + 73\n", + "# 73 + 29\n", + "# 73 + 29 + 51\n", + "\n", + "## ex_2) \n", + "reduce(lambda x, y : x + [y['mail']], users, []) \n", + "# [] + ['gregorythomas@gmail.com']\n", + "# ['gregorythomas@gmail.com'] + ['hintoncynthia@hotmail.com']\n", + "# ['gregorythomas@gmail.com', 'hintoncynthia@hotmail.com'] + ['wwagner@gmail.com']" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from functools import reduce\n", + "# users = [\n", + "# [100,10],[2,3,], [4,5]\n", + "# ]\n", + "users = [\n", + " 1,2,3\n", + " ]\n", + "\n", + "reduce(lambda x, y : x + y, users)" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['negative', 'negative', 0, 'positive', 'positive']" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "\n", + "# list(lambda x : 'positive' if x > 0 else 'a' for x in li)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/_posts/cate_06_Evaluation/2020-08-26-Evaluation-RMSE_MAE.md b/_posts/cate_06_Evaluation/2020-08-26-Evaluation-RMSE_MAE.md new file mode 100644 index 00000000000..74548836d85 --- /dev/null +++ b/_posts/cate_06_Evaluation/2020-08-26-Evaluation-RMSE_MAE.md @@ -0,0 +1,31 @@ +--- +layout: post +title: RMSE & MAE +date : 28 Aug 2020 +category : Evaluation +comments : true +--- + +: 모델의 성능을 평가하다보면, 종종 RMSE와 MSE를 함께 사용하는 경우를 볼 수 있습니다. 둘다 오차의 크기를 재기위한 방법인데, 서로 어떤 차이가 있고 함께 사용했을 때 어떤 장점이 있는지 비교해보고자 합니다. + +## 1. RMSE(Root Mean Square Error) + : RMSE(평균 제곱근 오차)는 회귀 문제의 성능 지표로 주로 활용된다. + $RMSE = \sqrt{ \frac{1}{m} \sum_{i=1}^m(h(x^i) -y^i)^2}$ + + +## 2. MAE(Mean Absolute Error) + : 평균적인 오차의 크기를 나타내는 값으로, 이때 오차의 방향성은 고려하지 않는다. + $MAE = \frac{1}{m} \sum_{i=1}^m|h(x^i) -y^i|$ + +## 3. RMSE vs MAE + : 얼핏 보면 두 지표 모두, 예측값과 실제값 사이의 오차의 거리를 측정하기 위한 지표로 큰 차이가 보이지 않는다. 그렇다면 굳이 두 지표를 함께 쓴느 이유는 무엇일까. + RMSE는 평균값을 계산하기 앞서, 오차에 제곱항을 씌워주기에 상대적으로 오차가 큰 값들을 더욱 크게 만드는 효과가 있다. 이점 때문에 모델 성능 평가에 있어서 RMSE를 사용할 시 작은 오차는 작게, 큰 오차는 크게 여길 수 있다는 특징이 있다. + + 나아가 RMSE는 항상 MAE보다 크거나 같으며, RMSE가 MAE와 같다면 모든 예측값과 실제값사이의 오차의 크기가 동일하다는 이야기가 되며, + MAE 대비 RMSE가 상대적으로 큰 값을 갖는다면, 이는 상당히 큰 오차값들이 존재함을 의미한다. + + + +#### Reference +[1] [Mean Absolute Error (MAE) and Root Mean Squared Error (RMSE)](http://www.eumetrain.org/data/4/451/english/msg/ver_cont_var/uos3/uos3_ko1.htm) +[2] https://mjdeeplearning.tistory.com/30 diff --git a/_posts/cate_06_Evaluation/2021-02-08-AIC_BIC.md b/_posts/cate_06_Evaluation/2021-02-08-AIC_BIC.md new file mode 100644 index 00000000000..361f829285c --- /dev/null +++ b/_posts/cate_06_Evaluation/2021-02-08-AIC_BIC.md @@ -0,0 +1,31 @@ +--- +layout: post +title: AIC_BIC +date : 8 Feb 2021 +category : Evaluation +comments : true +--- +AIC & BIC는 CV(cross validation)처럼 모델의 적합도를 판단하여 파라미터에 따른 모델을 선택하기 위해서 사용되는 확률적 모델 선택 방법론('Probabilistic Model Selection' or 'information criteria')이다. +두 방법의 장점으로는 K-fold CV처럼, 샘플 데이터를 설정하는 hold-out test set이 필요 없다는 장점이 있으나, 불확실성을 충분히 고려하지 않아 모델 선택 과정이 단순화 될 수 있다는 한계점 또한 존재한다. + + +# 0. Probabilistic Model Selection +- Model Performance +: How well a candidate model has performed on the training dataset. +- Model Complexity + : How complicated the trained candidate model is after training. + +# 1. AIC +AIC = -2/N * LL + 2 * k/N + +# 2. BIC +BIC = -2 * LL + log(N) * k + + + + + +#### Reference +[1] [Probabilistic Model Selection with AIC, BIC, and MDL](https://machinelearningmastery.com/probabilistic-model-selection-measures/) + +[2] [AIC(Akaike information criterion)](https://m.blog.naver.com/PostView.nhn?blogId=euleekwon&logNo=221465294530&proxyReferer=https:%2F%2Fwww.google.com%2F) diff --git a/_posts/cate_08_DataAnalysis_Marketing/2022-02-03-data_analysis_process.md b/_posts/cate_08_DataAnalysis_Marketing/2022-02-03-data_analysis_process.md new file mode 100644 index 00000000000..b4307f18700 --- /dev/null +++ b/_posts/cate_08_DataAnalysis_Marketing/2022-02-03-data_analysis_process.md @@ -0,0 +1,214 @@ +--- +layout: post +title: 데이터 분석 리포트 작성 프레임워크(Data Analysis Reporting Framework) +date : 03 Feb 2022 +category : DataAnalysis_Marketing +comments : true +--- +: 데이터 분석을 하다보면, 연간/분기/특정기간내 서비스 전체 또는 주요 지표들에 대해서 리포팅을 해야하는 상황이 생겨난다. 이에 데이터 분석 리포팅 작성시, 절차 및 이슈들을 정리해보자. + 이때 각자의 문제 상황에 따라서 리포팅 작성 방식은 다를 수 밖에 없기에, 특정 문제를 해결하기 위한 FrameWork라고 보면 좋을 것 같다. 또한 본글은 개인적 경험과 일부 리서치에 기반하였기에, 지속적인 수정 & 보완이 필요하다. + + +> 아래 작성한 개인 경헙에 기반한 분석 방법론 외, 체계화 되어있는 방법론들은 아래 링크를 참고하자 + +
+ + + + [데이터_분석계획_빅데이터_분석기획 by noti-note님 블로그](https://noti-note.tistory.com/12) + +
+ + +
+# 1. 문제정의 $\star\star\star$ +## 1) Why : 리포팅을 왜 하는 것일까? $\star$ + : 리포트를 보는 대상에 따라서, 문제정의 작성 및 리포팅의 이유가 크게 달라진다. + 특정 문제에 국한된 리포트 또는 Daily리포트는 주로 실무자나 중간급에서 빠른 의사결정 및 진행상황을 체크하기 위함이기에 문제정의가 명확하다.
+ + 반면, 리포트 작성의 이유가, 전반적인 서비스 평가 및 서비스 지속 인사이트 추출이라는 모호한 경우가 있다. 주로 중장기간의 서비스 전체 또는 KPI 2,3개 이상의 리포트를 작성하여 상급자에게 리포트를 하는 경우이거나, 아직 데이터로 구체적인 KPI를 잡지 못하여 모니터링 조차 하지 못하는 팀에서 "전체적인 탐색적 분석을 하며 인사이트를 찾고 싶어요"라는 막연한 요청을 하는 경우가 주로 이러하다.
+ + 이런 막연함 속에도 "우리의 서비스가 얼마나 효율적으로 또는 어떤 방향으로 운영되고 있으며", "어떤 문제가 있는지", "분기별로 얼만큼의 성과를 이루었는지" 등의 목표가 존재한다. 추상적인 목표를 아래 분석 항목별로 나눠, 구체화 시키는 작업이 필요하다. + + +
+## 2) What : 무엇을 분석할 것인가? $\star$ + : 커머스 서비스 가정하에 탐색적 분석을 진행하기 위하여, 고객 여정별 분석 항목을 정리해보자. + +
+ +
+ + (1) 유입 (Acqusition) + - 앱설치자수 (total / daily) + + (2) 유입 채널 (Attribution) + - 채널별 앱설치자수(유입자수) (total / daily) + - 채널별 유입자 *KPI 전환율 (KPI : 회원가입 / 구매 / ETC) + - 채널별 Fraud / Bounce 유저수 (total / daily) + + (3) 활성화 (Activation) + - 회원가입자수 (total / monthly / weekly / daily) + - 회원가입 전환율 (total / monthly / weekly / daily) + + (4) 유지 (Retention) + - 접속 빈도 : DAU / WAU / MAU + - 접속 빈도 : 평균 접속주기 + - 사용 시간 : 세션당 평균 사용 시간 (집단별 / daily) + - 퍼널 분석 : 설치 > 가입 > 상품 조회 > 상품 구매 > 재구매 + (기간별 / 집단별 비교) + + (5) 참여 & 커머스 (Engagement & Commerce) + - 참여 : 특정 이벤트 유입자 및 회원가입 등 KPI 지표 + - 참여 : 공유 조회 활성 유저수 (total / monthly / weekly / daily) + - 커머스 : 상세페이지 조회 & 조회자수 + - 커머스 : 구매 & 구매자수 (total / monthly / weekly / daily) + - 커머스 : 재구매 & 재구매율 + - 커머스 : 조회 & 구매 상품 Top 10 + - 커머스 : 구매 전환율 (사용자 그룹별 / 기간별 / 상품별) + - 커머스 : 구매 금액 / 인당 평균 구매액 + - 커머스 : Pair 분석 + + (6) 이탈 (Churn) + - 최근 7/14/28일 이탈율 (동기간 대비 / 집단별 / 일별) + - Bounce / Farud 유저수 / 비율 + + (7) 도달 (Reachability) + - 메시지 퍼널 : 발송자 > 오픈자수 > 오픈자 중 구매자 + - 메시지 성과 분석 : 시간대별 접속자수 / 구매자수 추이 + 메시지 발송 시간 표기 + + + 인구통계 (Demographic) + - 전체 유저 : 성별 / 연령 분포 + - 사용자 그룹별(일반 / VIP 등등) : 성별 & 연령 분포 + - 사용자 속성 정보(등급 / 설문 결과 등등) + + + 위 목록에서 필요한 항목을 골라, 1차 문제 정의를 작성하고 탐색적 리포팅을 작성한다. 이 과정에서 시간과 여유가 있다면, 탐색적 분석 과정에서 도출한 인사이트를 토대로 원인을 파악하기 위한 2차 문제 정의를 작성 할 수 있을 것이다. + + +
+## 3) How : 어떻게 분석할 것인가? + : 위 에서 어떤 항목을 분석할지 선택하더라도, 단일 지표만을 가지고 해당 지표를 긍정적으로 해석해야할지 부정적으로 해석해야할지 판단하기 쉽지 않다. 때문에 타겟 지표를 비교 할 수 있는 비교 집단을 함께 설계하는 것이 중요하다. + + ex) 메시지 성과 분석 + - 분석 집단 : 메시지 발신 후 전환율 + - 비교 집단 : 메시지 발신 전 전환율 + +--- +
+# 2. 데이터 수집 + : 분석에 필요한 데이터를 수집하는 과정으로, 사전에 협의된 분석 기간의 데이터를 추출한다. 이 단계에서는 데이터의 수집 뿐아니라, 적합성, 커스텀 변수등을 확인한다. + + (1) 데이터 퀄리티 + - 데이터 누락 확인 + + (2) 데이터 기간 + - 분석 데이터 기간 확인 + + (3) 분석 기준 + - 사용자 기준 데이터 + - 기기 기준 데이터 + + (4) Key, Value, Param 정의 + - 매출, 카테고리 KPI 변수명 등을 사전에 정의 + +--- +
+# 3. 데이터 전처리 + : 수집된 데이터의 결측치, 중복값, 타입오류 등의 이슈를 사전에 체크해준다. 다만 로그데이터를 분석하는 경우, 이상치 제거는 평균의 왜곡 등을 방지하기 위해서 필요하지만, 경우에 따라서 DB값과 차이를 생성하므로, 제거 여부 논의 후 판단해야하는 상황이 생긴다. 주요 전처리 이슈들은 아래와 같다. + + (1) 데이터셋 확인 단일 + - 상품의 중복 카테고리 이슈 [ex. 상품 1개, 카테고리 2개] + - 데이터 타입 이슈 [ex. 금액 Value : str type으로 수집됨] + (2) 결측값 처리 + - 삭제 + - 대체 (평균, 최빈값, 중간값) + - 예측값 대체 (Regression, Logistic) + (3) 이상치 처리 + - 단순 삭제 + : 리포트 경우 삭제가 어렵기에, Scaling으로 편향된 이상치를 조정 + - 평균, 중위값 등으로 + (4) Feature Engineering + - Scaling + : 변수의 단위가 너무 크거나 편향 될 경우, 변수간 관계가 잘 드러나지 않기에, Log 또는 SqureRoot등을 취해 스케일 조정 + - Binning + : 연령, 금액 등 연속형 변수를 범주형 변수로 변경 + - Transfrom + : 자주 사용하는 예로, 단순 weekday를 주중과 주말로 변환하는 것 처럼, 분석 목표에 맞는 변수생성 + + * [데이터 전처리에 대한 모든 것 - DODOMIRA](http://www.dodomira.com/2016/10/20/how_to_eda/) + * [데이터 전처리 필요성 및 - 나는야 데이터사이언티스트](https://rk1993.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%84%EC%B2%98%EB%A6%AC) + + +--- +
+# 4. 데이터 분석 or 모델링 + : ML/DL 모델을 구축하는 과정은 이단계에서 정제된 데이터를 모델에 넣어 최적화 작업을 진행한다. + 반면 리포트를 위한 분석에서는 데이터를 토대로, 인사이틀 발굴하기 위한 차이점과 원인을 찾는 실험설계의 과정이 반복된다. + + 1. 가설 설정 + 2. 실험군 비교군 설정 + 3. 분석 지표 생성 + 4. 결과 해석 +리포트를 쓰다보면, 수많은 가설들을 세우고, 이에 따른 실험군과 비교군의 사용자집단들이 무수히 많아지기도 한다. 때문에 아래 2가지 모듈을 사전에 생성하고 작업한다면 비교적 정리된 상태로 분석을 진행할 수 있다. + + 1. Module_1 : 사용자 그룹 생성 + 2. Module_2 : 지표 분석 + + +--- +
+# 5. 데이터 분석 시각화 + : 시각화는 앞선 분석항목들을 최종적인 형태로 만들어 분석 결과를 해석하거나, 또는 리포트를 받는 사람입장에서 직관적으로 결과를 인지하기 위해 필요하다. + 때로는 너무 많은 변수들을 하나의 차트에 담으려고 하다보면, 시각화된 자료를 보고 해석하는데 많은 시간이 소요될 수 있으니, 시각화도 결국 어떤 분석 결과를 보여주기 위함인지 목적에 맞추어 필요한 정보만을 비교하는 것이 좋을 것 같다. + + - 적절한 시각화 방법 활용 + - 항목간 비교시 파이 그래프(비율)는 지양하고 막대(양) 그래프 위주 + - 시계열은 라인으로(실선) + - 분포는 히스토그램이나 박스플롯 + - 변수간 관계는 산점도 + + +--- +
+# 6. 리포팅 및 피드백 반영 +: 열심히 '기획 정의'를 작성하고 코드를 짜며 '분석'을 완료하고, '시각화'까지 마쳤다면, 이제 자료를 리포팅 형식으로 정리고 결과를 해석하기 위한 글을 작성하는 마지막 단계가 남아있다. 여기까지 오느라 이미 많이 지쳤겠지만, 이단계가 잘 이뤄지지 않으면 그동안의 노력이 물거품이 되어버릴 수 있을 만큼 중요한 단계이다. + +## 1) 리포팅 포맷 + : 최종 리포트 작성을 위해 먼저 고민하는 것은 리포트의 포맷이다. 가장 쉽게는 '엑셀' 또는 'PPT'가 있을 것이며, 'GA Data Studio', 'Tableau'와 같은 툴을 사용하고 있다면 해당 분석툴의 기능을 사용하는 것도 좋을 것 같다. + 'Excel'과 'PPT'도 물론 사용자의 능력에 따라 다르겠지만, 개인적인 경험에 따르면 아래와 같은 상황에서 각각의 툴을 선택하는 것이 좋은 것 같다. + + - Excel + : 탐색적 데이터 분석 과정에서 획득한 데이터들을 보며 실무진에게 리포팅하는 경우 + - PPT + : 탐색적 분석을 마치고, 인사이트를 정리하여, 최종 의사결정자에게 중요한 분석 결과만 전달하는 경우 + + +## 2) 리포팅 정리시 주안점 + +### (1) 독자 중심 정리 + - 상대가 이해할 수 있는 언어 사용 + - 목적을 수시로 상기하고 재확인 + - 분석 과정 보다는 '결과'중심 전달 + +### (2) 간결 & 명확 + - 짧은 문장 + - Bullet point 방식 + - 선 핵심내용, 후 근거 + +### (3) 피드백 & 수정 + - 피드백 후 수정 & 보완은 당연한 과정 + - 분석입장에서 공을 들인 결과물도, 고객사 입장에서 중요도가 낮을 수 있음을 명시. + +--- +여기까지 분석 리포트를 작성하기 위한 각 단계별 작업들을 정리해보았다. 개인적으로 리포트라는 업무가 주어지면, 가이드라인 없이 망망대해에서 작업하던 경험이 많았기에, 그동안 작업했던 경험과 자료들을 취합하여 내가 사용하기 위한 글을 정리해보았다. +더불어 개인적으로 향상된 리포트 작성을 위해선, 복잡하고 각기 다른 형태의 산출물 데이터를 시각화 시키는 능력이 더 필요할 것 같다. + + + + +#### Reference +[1] [데이터 분석 절차 - @osk3856](https://velog.io/@osk3856/data-analysis) +[2] [데이터 분석을 위한 5단계 절차 - 마경근](https://brunch.co.kr/@data/10) +[3] [분석 프로세스 - 위키독스](https://wikidocs.net/16561) +[4] [데이터 분석 계획](https://noti-note.tistory.com/12) diff --git a/_posts/cate_08_DataAnalysis_Marketing/2022-02-07-app_push_marketing.md b/_posts/cate_08_DataAnalysis_Marketing/2022-02-07-app_push_marketing.md new file mode 100644 index 00000000000..ff54f696174 --- /dev/null +++ b/_posts/cate_08_DataAnalysis_Marketing/2022-02-07-app_push_marketing.md @@ -0,0 +1,39 @@ +--- +layout: post +title: 푸시 마케팅의 기본 3요소 +date : 07 Feb 2022 +category : DataAnalysis_Marketing +comments : true +--- +: 시장에는 비슷한 기능과 서비스를 제공하는 다른 player들이 계속해서 생겨나고 있기에 그들과 계속해서 경쟁하고 차별점을 제공해야만 살아남을 수 있기에, 적극적인 푸시 마케팅이 필요함. 이때, 사용자가 원하는 정보를 적합한 타겟에게, 적시적기에, 명확한 메시지로 전달하는 것이, 사용자들의 신뢰도를 지켜가며 마케팅을 하기위한 중요한 요소이다. 이같은 고려없이 무분별하게 반복되는 푸시 마케팅은 사용자의 피로도만 증가시키고 결국, 푸시마케팅 이후 더 많은 사용자 이탈을 초래한다. + +# 푸시 마케팅을 위한 3요소 : 발송 대상, 타이밍, 분석 + +## 1. 발송 대상 + : 발송전 명확한 대상을 설정 필요성 + - 명확한 대상에 따라, 이후 컨텐츠 및 메시지 내용 기획 가능 + - 잘못 설정된 대상에겐, 스팸으로 느껴져 서비스 신뢰도 하락 +
+ +
+ +## 2. 발송 타이밍 + - 너무 반복적으로 남용된 푸시는 사용자의 피로감 상승하며, 이로인한 이탈률 증가 + - 주요 앱 사용시간에 재접속 유도 & 휴면 VIP 고객 재접속 유도 등 고객 행동에 따라 적합한 타이밍에 발송 + +
+ +
+ +## 3. 발송 결과 분석 +#### A|B TEST + : 두 가지 이상의 전략을 두고 타겟 유저들이 어떤 전략에 더 반응을 많이 하는지 확인하는 방식 + > - 버튼 / 아이콘 / 색상 / 이미지 / 텍스트 배치 + > - 푸시 발송 타이밍 + > - 랜딩 페이지 + > - 문구 + + + +#### Reference +[1] [푸시 마케팅의 기본 3 요소 - 유라클 전략기획팀](https://uracle.blog/2020/03/05/push-mkt/) diff --git a/_posts/cate_08_DataAnalysis_Marketing/2023-01-02-data_literacy copy.md b/_posts/cate_08_DataAnalysis_Marketing/2023-01-02-data_literacy copy.md new file mode 100644 index 00000000000..89349a20bd6 --- /dev/null +++ b/_posts/cate_08_DataAnalysis_Marketing/2023-01-02-data_literacy copy.md @@ -0,0 +1,161 @@ +--- +layout: post +title: Data Literacy를 올리는 방법(화해 블로그) +date : 02 Jan 2023 +category : DataAnalysis_Marketing +comments : true +--- +> 해당 내용은 화해의 기술블로그 중 오세창님(데이터팀 리드)의 글 '데이터 리터러시(Data Literacy)를 올리는 방법'을 정리한 내용입니다. + +--- +## 1. 데이터 리터러시(Data Literacy)란? + : "데이터를 활용해 문제를 해결할 수 있는 능력" + +데이터를 잘 활용한다는 것은, +데이터를 활용해 문제를 잘 정의하고 & 해결할 수 있다는 말이고, +데이터를 잘 활용하도록 만들려면, +데이터/실험 기반 사고방식이 자리잡혀야 하며, +분석 흐름대로 데이터를 탐색할 수 있는 환경이 필요 (supported by 데이터 분석가) + +#### * 기존 문제 + : 기존 요구하는 지표 전달를 빠르게 제공하는 것에만 초점을 맞추다보니 아래와 같은 문제 발생 + - 문제_1 : 해결하려는 문제와 전혀 상관없거나 효과가 매우 미미한 지표가 요청됨. + - 문제_2 : 특정 문제를 해결하기위해, 관련됐다고 생각된 모든 지표를 살펴보다보니, 되려 의사결정이 어려움. + +```markdown +---[before] 신규 기능 관련 이벤트 성과 측정을 위한 데이터 요청--- + - 전면팝업 데이터 + - 노출수, 클릭수, 노출(유니크), 클릭(유니크) + + - 이벤트 참여 데이터 + - 전체조회수, 유니크조회수 + - 전체참여수, 옵션별 선택 수 + - 일자별 이벤트 참여수 + - 신규유저/기존유저 각 참여자수 + - 이벤트 기간 내 신규 설치수 + - 이벤트 기간 내 신규 가입수 + + - 신규 기능 관련 데이터 + - 이벤트 진행 전/후 신규 기능 경험 수치 변화 + - 이벤트 진행 전 1달 + - 이벤트 진행 기간 + - 이벤트 뷰어 & 참여자의 신규 기능 경험 수치 +``` + +```markdown +
[after] 신규 기능 관련 이벤트 성과 측정을 위한 데이터 요청
+ - 해결하려는 문제 + - 신규 기능에 대한 인지가 부족한 문제 + + - 솔루션 + - 신규 기능에 대한 브랜딩 활동을 통해 신규 기능 인지 강화 + + - 측정 지표 + - 이벤트 조회자수 + - 이벤트 참여자수 + ** 단 건의 앱 내 이벤트를 통해서는 기능의 사용성을 단기간에 올리기 어려우므로, 장기적으로만 모니터링 +``` + +
+위처럼 데이터 요청의 목적과 배경을 인터뷰하여, 아래와 같이 크게 3가지로 정리할 수 있다. +
+ + > 1) 해결하려는 문제 (문제정의) + > 2) 솔루션 + > 3) 측정 지표 + + + +--- +## 2. 데이터/실험 기반 사고 방식 $\star$ + +#### * 실험 프로세스 / 실험보드 + +: 데이터/실험 기반 사고방식이 만들어 지려면, 모든 업무들이 데이터와 실험 기반으로 이뤄지는 환경 구축이 필요했음. 따라서 실제 진행중인 업무들부터, 데이터 기반 사고방식으로 실행되도록 유도함. 이런 방식이 자연스러워지도록,`데이터 기반 실험 프로세스 프레임`을 도입. 해당 프로세스의 목적은 `1) 실험 횟수를 높여 성과 증대`의 목표와 함께 `2) 데이터 중심 문제 해결능력 배양`. + + +
+ [실험 프로세스] +
+ + + - 1) 해결하려는 문제 ➡️ 문제정의 + - 2) 관련 OKR ➡️ 전사 목표와 align 되어있는지 + - 3) 측정 지표 ➡️ 문제와 지표가 align 되어있으며, 측정 가능한 것인지 + - 4) 검증 기준 ➡️ 성공 여부를 어떻게 판단할 것인지 + - 5) 검증 후 변화될 액션 ➡️ 의미없는 액션을 하는게 아닌지 + - 6) 결과 ➡️ 검증 기준으로 결과가 나왔는지 + - 7) 학습한 점 ➡️ 어떤 학습을 했고, 다음 실험에는 어떻게 반영될 것인지 + + +
+
+ +--- + + +## 3. 분석 흐름대로 데이터를 탐색할 수 있는 환경 $\star$ +#### 1) 데이터 맵 +##### (a) 데이터 맵 도입 배경 +: 그러나 문제를 잘 정의하려면 여전히 분석가와 함께 논의를 해야 하는 어려움이 남아있었음. 때문에 분석가 없이도 가장 중요한 지표에 집중할 수 있도록 전사에서 다루는 중요한 인풋 지표와 아웃풋 지표 간의 관계를 표현한 관계도를 제작·공유함. + +##### (b) 데이터 맵 원칙 +: 단순히 모든 지표를 도식화한다고 하면 너무 많은 지표들이 담길 수 있기 때문에 보다 중요한 지표에 집중하기 위해 인풋 지표 설정에 중요한 원칙 두 가지를 설정 + * 1) 측정 가능 + * 2) 직접적으로 control 가능 + * 3) 데이터 관계가 쉽게 이해될 수 있어야함. + +
+ +#### 2) 대시보드 +##### (a) 대시보드 도입 배경 +: 지표 관계를 잘 이해하게 되었다면, 다음은 그 흐름에 따라 지표의 현재 수준을 확인할 수 있는 환경이 필요하였으며, 분석 흐름을 따라가면서 지표들을 탐색할 수 있도록 대시보드 설계하였음. 대시보드를 활용해 분석가가 아닌 구성원들도 중요한 지표 변동과 원인을 파악하는 분석 정도는 스스로, 그리고 빠르게 할 수 있어야 함. + +##### (b) 대시보드 원칙 + - 분석 흐름을 따라가면서 지표들을 탐색. + - 최상위 문제를 발견하면, 각 지표와 관련된 하위 지표들이 구성된 분석 대시보드 내에서 원인을 짐작할 수 있어야함. + +
+ + +## 4. 이 과정을 도와주는 분석가 +#### 데이터 분석가(Data Scientist) +: 우리는 분석가의 역할이 단순히 데이터를 추출하고, 분석 내용을 리포팅하는 것에만 그쳐서는 안된다고 생각합니다. 1)문제를 정의하고 2)원인을 분석한 뒤에는 3)액션 아이템까지 도출해 리포트를 제공받은 4)협업팀이 실행에 옮기도록 만들어야 합니다. + +
<분석가의 역할을 명확히 할 수 있는 JD(Job Description)>
+ +``` + - 제품/비즈니스 성장을 위한 지표 설계 및 대시보드를 개발 + - 제품/비즈니스 문제 해결을 위한 실험을 설계 + - 핵심 지표 모니터링 및 지표 변동의 root cause를 분석 + - 데이터 분석 결과를 바탕으로 실질적인 액션 아이템을 제안 + - 데이터 기반 사고와 실험 활성화를 위한 전사적인 코칭 및 컨설팅 역할을 수행 +``` + +그리고 매 분기마다 우리가 기대하는 모습을 가장 중요한 OKR로 설정해 모든 분석가의 업무 방향성을 일치 시켰습니다. + +`KR : 분석가의 산출물로 협업팀/밴드 과제지표 및 전사지표의 성장 또는 중요 의사결정 견인(1인당 월 2회 달성)` + +#### 데이터 플랫폼 + : 분석가뿐만 아니라 많은 구성원들이 빠르게 분석할 수 있으려면 데이터를 빠르게 준비해 사용할 수 있는 구조가 필요합니다. + + - 데이터 레이크 : 모든 원천데이터가 적재 + - 구조화된 데이터 웨어하우스 : 신속하게 정확한 데이터를 추출 + - 데이터 카탈로그 : 레이크/웨어하우스 내에 어떤 데이터가 있는지 쉽게 확인 + + 데이터 웨어하우스와 카탈로그는 분석가들이 실질적인 분석 업무를 빠르게 수행할 수 있도록 도와줍니다. 분석가가 아니더라도 SQL을 알고있는 구성원이라면 본인이 필요한 데이터는 SELECT, FROM, WHERE, GROUP BY 정도만 작성하면 쉽게 얻을 수 있습니다. + + 데이터 웨어하우스를 통해 분석가의 업무 효율은 비약적으로 상승했고, 본질적인 분석 업무에 더 많은 시간을 할애할 수 있게 되었습니다. 분석파트에서 조직이 성장한 점을 리뷰할 때마다 데이터 웨어하우스 구축은 가장 손꼽히는 변화이자, 업무에 가장 큰 도움을 준 요소라고 말할 정도니까요. + +
+ src : [화해의 Data Warehouse를 소개합니다(화해 블로그) - by 최혜림](http://blog.hwahae.co.kr/all/tech/tech-tech/9409/) + + +## 5. 맺음말 +: 앞서 말씀드린 것처럼 저는 `데이터 리터러시`를 `데이터를 활용해 문제를 해결할 수 있는 능력`이라고 정의하고 있습니다. 하지만 단순히 구성원들에게 데이터를 보여주는 것만으로 문제 해결력이 좋아지지는 않았습니다. `구성원들이 데이터를 바라보는 올바른 관점을 만드는게 가장 중요했고, 이 관점을 유지·강화 시키기 위한 환경`이 필요했습니다. + +이때 경영진들의 강한 지지가 환경을 조성하는 데 중요한 역할을 했습니다. 그 뿐만 아니라 화해팀 모두의 노력과 적극적인 참여를 통해 화해팀은 데이터를 활용해 문제를 해결하는데 매우 익숙한 조직으로 변화해왔습니다. 조직 전체의 데이터 리터러시를 높이고 이를 통해 성과들이 만들어지도록, 저희 데이터팀은 더 좋은 환경과 구조들을 만들어나갈 예정입니다. + + +#### Reference +[1] [데이터 리터러시(Data Literacy)를 올리는 방법(화해 블로그) - by 오세창](http://blog.hwahae.co.kr/all/tech/tech-tech/9757/) diff --git a/_posts/cate_08_DataAnalysis_Marketing/2023-04-19-acquisition_source_mdedium_referr.md b/_posts/cate_08_DataAnalysis_Marketing/2023-04-19-acquisition_source_mdedium_referr.md new file mode 100644 index 00000000000..b18897453b1 --- /dev/null +++ b/_posts/cate_08_DataAnalysis_Marketing/2023-04-19-acquisition_source_mdedium_referr.md @@ -0,0 +1,79 @@ +--- +layout: post +title: 2023-04-19-acquisition_source_mdedium_referr +date : 11 May 2023 +category : DataAnalysis_Marketing +comments : true +--- +외부 채널 + +--- + +## 1.획득 (Acquisition)이란 + : GA에서 획득(Acquisition)이란, **사용자들이 어떤 경로(채널/캠페인)를 통해 우리 웹사이트를 방문**하였는지를 보여주는 개념. 이를 활용하여 마케팅 활동별 성과를 측정. + +--- +
+ +## 2. UTM (Urchin Tracking Module) +: 유입 구분값을 살펴보기 앞서, UTM은 어느 사이트로 부터 유입되었는지를 알려주는 꼬리표로, +타겟 사이트를 외부에 공유/홍보시 사용하는 url을 의미한다. 이 utm 값을 분석하여 유입 경로를 구분할 수 있다. + +
+ + +
<이미지 출처 : 그로스클, 김신입_마케팅용어집> + +
+ + - ex) https://taehwanyoun.git.io?utm_source=kakao&utm_medium=push&utm_campaign=fb_promotion&utm_term=promotionAE&utm_content=202305_contents + - utm_source=kakao : 소스(soruce) + - utm_medium=push : 매체(medium) + - utm_campaign=fb_promotion : 캠페인(campagin) + - utm_term=promotionAE : 유입 키워드 + - utm_content=202305_contents : 유입 컨텐츠 + + +--- +
+ +## 3. 주요 용어 구분 + +### 1) 채널 > 매체 > 소스 + +| **구분** | **용어** | **정의** | **예시** | +| **그룹** | **채널(channel)** | 각 매체에서 여러 소스를 포함하는 집합이나, 매체와 유사하게 구분됨 | | +|:-: |:-----: |:-----: |:----- | +| **범주** | **매체(medium)** | 소스의 상위 카테고리 or 사용자를 사이트로 보내는 시스템
(별도의 추가 설정이 없을 경우 기본값은 none, referral, organic 3가지뿐) | - none(없음)
: 직접(direct) url 입력을 통해 유입되거나, 소스 부재

- referral(추천)
: referral url을 클릭하여 유입

- organic(자연검색)
: 구글/네이버 등 무료 검색 결과 유입

- cpc(유료검색)
: 키워드 광고등 유료 검색을 통해 유입

- banner/display(디스플레이)
: 디스플레이/배너 광고 클릭

- social(소셜)
: Instagram, Facebook, Kakao 등
| +| **출처** | **소스(source)** | 트레픽이 유입된 위치(검색엔진, 도메인 등) | [google.com, naver.com, blog.naver.com] | + +※ 매체와 채널
+매체와 채널은 굉장히 유사한 개념으로 보임. 앞서 utm을 살펴보면, +매체(medium)값은 수집되는 값이지만, 채널(channel)값은 따로 utm url을 통해 수집되는 것이 아닌, GA 구분을 통해 생성되는 것 같다. (개인 추측) +아직은 두 개념이 명확히 구분되지 않아, 우선은 매체와 소스 위주로 더 정리해보려한다. + - 매체 : 소스를 마케팅 수단으로 그룹핑한 카테고리 + - 채널 : 수집된 소스/매체값을 그룹핑한 카테고리 + +## (2) 매체 구분 + - none(없음) : 직접(direct) url 입력을 통해 유입되거나, 소스 부재 + - referral(추천) : referral url을 클릭하여 유입 + - organic(자연검색) : 구글/네이버 등 무료 검색 결과 유입 + - cpc(유료검색) : 키워드 광고등 유료 검색을 통해 유입 + - banner/display(디스플레이) : 디스플레이/배너 광고 클릭 + - social(소셜) : Instagram, Facebook, Kakao 등 + +
+ + +
<이미지 출처 : 파인데이터랩 > + +
+ + + + + +#### Reference +[1] [[GA기본] 5-2. 구글애널리틱스 표준 보고서 (Standard reports) - 분석마케팅](https://analyticsmarketing.co.kr/digital-analytics/google-analytics-basics/2318/) +[2] [2022_디지털마케팅(30) 구글 애널리틱스(38) - 채널 분석](https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=hsjeong106&logNo=221690237016) +[3] [구글애널리틱스(GA) 사용법 : 획득보고서](https://finedata.tistory.com/39) \ No newline at end of file diff --git a/_posts/cate_09_Crawler/2020-10-22-crawler_naver_actor_filmo.md b/_posts/cate_09_Crawler/2020-10-22-crawler_naver_actor_filmo.md new file mode 100644 index 00000000000..156b76844db --- /dev/null +++ b/_posts/cate_09_Crawler/2020-10-22-crawler_naver_actor_filmo.md @@ -0,0 +1,165 @@ +--- +layout: post +title: NaverNews_Crawler_tab 화면 전환 +date : 22 Oct 2020 +category : Crawler +comments : true +--- + +# naver & wikipedia crawler + +## switch window ...@ㅁ@ +: 네이버 뉴스 및 위키피디아를 사용해, 특정 배우의 filmo graphy와, 학력, 나이 등의 기본 정보를 스크랩핑해야 하는 상황이 생겼다. + +프로세스는 해당 배우의 이름(query)을 검색한 후, **'더보기'** 버튼을 클릭해서, 세부 내용을 가져오는 어렵지 않은 과정이었다. + +문제는 셀레니움 패키지를 사용해 **'더보기'** 버튼을 클릭할 시, 새로운 창이 뜨게 되는데, 새롭게 생겨난 창을 Driver가 잡지 못하면서 해당 페이지의 정보를 가져오지 못하게 된다. + +이렇게 새로운 탭이 생성되는 경우, `driver.switch_to.window(driver.window_handles[0])` 코드를 사용해, 탭의 위치를 지정해주어야 한다. + +```python +# sample code +naver_url = str(basic_url + '&query=' + actor) +driver = webdriver.Chrome('./chromedriver') + +driver.get(naver_url) +more_btn = driver.find_element_by_xpath('//*[@id="people_info_z"]/div[3]/a') +more_btn.click() + +driver.switch_to.window(driver.window_handles[0]) +``` + + +```python +# full code +from bs4 import BeautifulSoup +from selenium import webdriver +from datetime import datetime, timedelta, date +import requests +import pandas as pd +import re +from math import * +import time +import wikipediaapi + +actor_list = ['이민정','배수지', '박은빈', '공유'] + +listForDF = [] +for actor in actor_list : + # final filmo dict + filmo_dict = {} + + # 1) get basic info from 'wikipedia' + page_py = wiki.page(actor) + if page_py.exists() == True : + # (1) age + try : + actor_summary = page_py.summary + regex = re.compile(r'\d+년\b') + birth = regex.search(actor_summary)[0] + age = int(now.year - int(re.findall(r'\d+', birth)[0]) + 1) + except : + age = None + + # education + try : + education = page_py.section_by_title('학력') + education = education.text.split('\n')[-1] + except : + education = None + + else : + print("Page - Exists: %s" % page_py.exists(), "Pass education & age") + education = None + age = None + pass + + # 2) get filmo info from naver ------------------ + # url setting & Chrome driver + naver_url = str(basic_url + '&query=' + actor) + driver = webdriver.Chrome('./chromedriver') + driver.get(naver_url) + try : + more_btn = driver.find_element_by_xpath('//*[@id="people_info_z"]/div[3]/a') + except : + # person with the same name + driver.close() + naver_url = str(basic_url + '&query=' + actor + ' 탤런트') + driver = webdriver.Chrome('./chromedriver') + driver.get(naver_url) + more_btn = driver.find_element_by_xpath('//*[@id="people_info_z"]/div[3]/a') + + + + ## * get age & education from naver(if necessary) + if age == None : + try : + age_element = driver.find_element_by_css_selector('#people_info_z > div.cont_noline > div > dl > dd:nth-child(3) > span') + if bool(re.match("\d+년 \d+월 \d+일", age_element.text)) : + birth = age_element.text + age = int(now.year - int(re.findall(r'\d+', birth)[0]) + 1) + print('{}\'s age from naver :'.format(actor) , age_element.text) + except : + age = None + + if education == None : + try : + education_element = driver.find_element_by_css_selector('#people_info_z > div.cont_noline > div > dl > dd:nth-child(9) > a') + if '학교' in education_element.text : + education = education_element.text + print('{}\'s education from naver : '.format(actor), education_element.text) + except : + education = None + + filmo_dict['actor'] = actor + filmo_dict['age'] = age + filmo_dict['education'] = education + + # 3) click more information for 'filmo' + more_btn.click() + + # 4) switch window...! (important!) + driver.switch_to.window(driver.window_handles[-1]) + + # 5-2) get filmo info + ## (2) genre setting + for genre in ['drama', 'movie'] : + if genre == 'drama' : + UI_code = str(76) # drama code : 76 + else : + UI_code = str(78) # movie code : 78 + locate = '#listUI_'+ UI_code +' > li > span > a' # '#listUI_78 > li > span > a' #영화 + + ## (5-2) get info + filmo_list = [] + elements = driver.find_elements_by_css_selector(locate) + for element in elements : + filmo_list.append(element.text) + + ## (5-3) click next page & get info + page = True + while page == True : + try : + # next page click + driver.find_element_by_xpath('//*[@id="pagination_'+UI_code+'"]/span[4]/a').click() + time.sleep(1) + + # get title + elements = driver.find_elements_by_css_selector(locate) + for element in elements : + filmo_list.append(element.text) + except : + page = False +# print('no more page') + + # make dict + filmo_dict[genre] = filmo_list + + # make list for DataFrame + listForDF.append(filmo_dict) + driver.close() # tab_2 + driver.switch_to.window(driver.window_handles[0]) + driver.close() # tab_1 +df_fin = pd.DataFrame(listForDF) + +``` diff --git a/_posts/cate_09_Crawler/2020-10-22-crawler_naver_query_time.md b/_posts/cate_09_Crawler/2020-10-22-crawler_naver_query_time.md new file mode 100644 index 00000000000..4a7b839543a --- /dev/null +++ b/_posts/cate_09_Crawler/2020-10-22-crawler_naver_query_time.md @@ -0,0 +1,98 @@ +--- +layout: post +title: NaverNews_Crawler +date : 16 Oct 2020 +category : Crawler +comments : true +--- +# Naver News Cralwer + + +```python +from bs4 import BeautifulSoup +from datetime import datetime, timedelta, date +import requests +import pandas as pd +import re +import os +from math import * + +def crawler(query,sort,s_date,e_date): + query = query.replace(' ', '+') + s_from = s_date.replace(".","") + e_to = e_date.replace(".","") + + # find max page number + # 1. url setting + basic_url = "https://search.naver.com/search.naver?where=news" + url = str(basic_url + '&query=' + query + "&sm=tab_opt&sort="+ str(sort)+ + "&nso=so%3Ar%2Cp%3Afrom" + s_from + "to" + e_to) + + # 2. get url + response = requests.get(url) + html = response.text + soup = BeautifulSoup(html, 'html.parser') + + total_count = soup.find_all(attrs={'class':'title_desc all_my'})[0].get_text() + total_count = total_count.split('/')[1].replace(',','') + total_count = int(re.findall('\d+', total_count)[0]) + +# maxpage = ceil(total_count/10) +# maxpage_t =(int(maxpage)-1)*10+1 # 11= 2페이지 21=3페이지 31=4페이지 ...81=9페이지 , 91=10페이지, 101=11페이지 +# print('maxPage number : {}'.format(maxpage)) + +# page = 1 +# while page <= maxpage_t: +# # 1. url setting +# basic_url = "https://search.naver.com/search.naver?where=news" +# url = str(basic_url + '&query=' + query + "&sm=tab_opt&sort="+ str(sort)+ +# "&nso=so%3Ar%2Cp%3Afrom" + s_from + "to" + e_to + +# "%2Ca%3A&start=" + str(page)) + +# # 2. get url +# response = requests.get(url) +# html = response.text + +# #뷰티풀소프의 인자값 지정 +# soup = BeautifulSoup(html, 'html.parser') + +# #태그에서 제목과 링크주소 추출 +# atags = soup.select('._sp_each_title') +# for atag in atags: +# title_text.append(atag.text) #제목 +# link_text.append(atag['href']) #링크주소 + +# #신문사 추출 +# source_lists = soup.select('._sp_each_source') +# for source_list in source_lists: +# source_text.append(source_list.text) #신문사 + +# #날짜 추출 +# date_lists = soup.select('.txt_inline') +# for date_list in date_lists: +# test=date_list.text +# date_cleansing(test) #날짜 정제 함수사용 + +# #본문요약본 +# contents_lists = soup.select('ul.type01 dl') +# for contents_list in contents_lists: +# #print('==='*40) +# #print(contents_list) +# contents_cleansing(contents_list) #본문요약 정제화 + + +# #모든 리스트 딕셔너리형태로 저장 +# result= {"date" : date_text , +# "title":title_text , +# "source" : source_text , +# "contents": contents_text , +# "link":link_text, +# "query" : query} +# # print(page) + +# df = pd.DataFrame(result) #df로 변환 +# page += 10 + + return total_count#, df + +``` diff --git a/_posts/cate_10_Git/2021-08-22-git_from_hell_start.md b/_posts/cate_10_Git/2021-08-22-git_from_hell_start.md new file mode 100644 index 00000000000..fcdcdf8d0ea --- /dev/null +++ b/_posts/cate_10_Git/2021-08-22-git_from_hell_start.md @@ -0,0 +1,97 @@ +--- +layout: post +title: Git 버전관리의 본질 +date : 22 Aug 2021 +category : Git +comments : true +--- +`#git, #생활코딩, #본질 +` + +## 1. git 설치 + [git 설치사이트 : www.git-scm.com](www.git-scm.com) + + +## 2. git 저장소 관리 +```sh +# 1) 프로젝트 파일 생성 및 폴더로 진입 +mkdir git_prj +cd git_prj + +# 2) 현재 디렉토리를 git의 버전 저장소로 만 +## 해당 폴더 내에 `.git` 이라는 디렉토리가 함께 생성되며, 해당 폴더 내에 git 관리 정보가 들어있음. +git init +``` + + +## 3. 관리할 파일 생성 +```sh +# 1) 파일 생성 및 수정 +vim f1.txt + +# 2) git에게 위 파일을 관리하라고 명령 (최초 생성 & 추후 수정할 때 마다) +git add f1.txt + +# 3) git이 관리하는 파일 확인하기 +git status +``` + + +## 4. GIT 버전관리 +```sh +# 1) Git에 내 정보 등록하기(최초 1회) +git config --global user.name [git에 가입한 아이디] +git config --global user.email [git에 가입한 이메일] + +# 2) 버전 저장 하기 : "Commit" +git commit -m '버전 내용 작성' + +# 3) 버전 기록 확인하기 +git log +``` + + +## 5. GIT Stage Area +### 1) 왜 commit 전에 add를 해야 하는가 +- 파일의 버전관리에 있어서 '선택적 파일 관리'를 가능하게 해줌 +- 협업 과정에서 여러파일을 관리하다 보면, 버전관리에 포함되어야 할 파일과 그렇지 않은 파일이 나뉠 수 있음. (stage에 올릴 파일들을 선택할 수 있음.) + +
+ +< local(개인PC) --> `git add` --> Stage(=commit 대기 상태) -> git_repository > + +
+ + +## 6. GIT 변경사항 확인하기(log / diff) +```sh +# 1) 로그에서 출력되는 버전간의 차이점 확인하기 +git log -p + +# 2) 특정 버전간의 차이점을 비교할 때 +## (1) commit 아이디 확인하기 +## : git log시 commit : 'commit id' 값 확인 +## (2) 버전간 차이점 확인하기 +git diff 'commit_id_1' 'commit_id_2' + +# 3) git add하기 전과 git add 후의 파일 내용 비교 +git diff +``` + +## 7. Reset : 과거로 돌아가기 +- 1) reset : 이전 버전 id로 돌아가기 +- 2) revert : 버전 id의 커밋을 취소한 내용을 새로운 버전으로 만들기..? + +```sh +# 1) reset +## : 최신 commit 대신, 과거 시점의 특정 커밋을 가장 최신 상태로 되돌리기 +## reset은 git_repository에 공유하기 전단계의 파일들일 것!! +git reset --hard 'commit_id_1' # commit_id_2 --> commit_id_1 + +# 2) revert +git revert 'commit_id_1' +``` + + +#### Reference +[1] [[생활코딩 : 지옥에서 온 git] 버전관리의 본질](https://opentutorials.org/course/2708/15242) diff --git a/_posts/cate_10_Git/2021-09-02-git_prj_start.md b/_posts/cate_10_Git/2021-09-02-git_prj_start.md new file mode 100644 index 00000000000..7e8431dba0c --- /dev/null +++ b/_posts/cate_10_Git/2021-09-02-git_prj_start.md @@ -0,0 +1,133 @@ +--- +layout: post +title: git 프로젝트 시작하기 +date : 02 Sep 2021 +category : Git +comments : true +--- + +`#git, #gitlab, #github, #branch +` + +github(or gitlab)을 사용하여, 프로젝트를 시작할때 절차별 사항들을 정리해보자. + +## 1. git 서버에 프로젝트 생성하기 +: git 프로젝트 생성방법은 아래 링크에 소개되어있는 절차대로 진행하면 쉽게 생성할 수 있다.(간단하기에 링크없이도 진행할 수 있다)
+ - [git lab 프로젝트 생성하기](https://goldsony.tistory.com/138) +
+ +## 2. git config +git에 생성한 repository를 다운받기 전, +실행하고자 하는 local pc에 내가 어떤 git 계정인지 세팅해주어야 한다. +(git 계정이 private인 경우, 서버에도 해당 계정을 초대/등록해주어야 함.) + +```sh +# 1) git global config 정보 확인 +git config --list + +# 2) git global user.name & email 세팅 +git config --global user.name "git 회원가입 시 입력한 이름" +git config --global user.email "git 회원가입 이메일 주소" +``` +
+ + + +## 3. 로컬 pc에 git서버 clone +내가 누구인지 설정해주었다면, remote서버내 저장되어 있는 repository를 복사해오자. +```sh +$ git clone "git 주소" # 이때 git 주소는 repository에서 copy. +``` +
+ + +## 4. 프로젝트 관리하기(매번 할 작업) +```sh +## 0) pull : remote 서버내 변경 사항 불러오기 +$ git pull + +## 1) add : 변경 내역 알리기 +$ git add test.py # 특정 파일만 알림 +$ git add . # 모든 변경 내역 알림 + +## 2) commit : 로컬 저장소에 변경 내역을 저장 +$ git commit -m "이 버전의 변경 내역에 대한 설명" +$ git commit -am "이 버전의 변경 내역에 대한 설명" # add + commit + +## 3) push : remote 서버에 변경 내역 올리기 +$ git push -u origin master +$ git push # -u 옵션을 이용하면 다음 push때 이전 히스토리를 기억하고 반영 +``` +
+ + +## 5. Branch 전략 + Refernce : [git branch & commend](https://www.holaxprogramming.com/2018/11/01/git-commands/) + +Git 작업시 주요 브랜치는 master(main)와 develop 이며, 이외에도 기능별 브랜치가 존재하지만 지금 나는 이 두개도 벅차다..ㅎ +
+ +
+ +작업 순서는 아래와 같이 생각하면 된다. +
+@ [작업 시작] +1. `git checkout dev` : git master branch --> dev branch 변경 + (HEAD가 dev 브랜치를 바라보며 변경사항을 저장) +2. [branch : dev] 파일 생성 및 분석 작업 진행 +3. [branch : dev] `add, commit, push` + +@ [dev에서 작업이 끝나고 "배포할" 코드를 master로 merge할 경우] +1. `git checkout master` git dev branch --> master branch 변경 + (HEAD가 master 브랜치를 바라보며 변경사항을 저장) +2. [branch : master] `git merge "dev"` : dev branch를 merge +3. [branch : master] `gut push` : 최종 배포할(merge된) 코드를 git에 업로드 + + + +
+--- +## + branch 주요 commend + +```sh +## 1) branch 생성 : master branch에서 develop 이라는 새로운 branch를 만들고 갈아탄다. +$ git checkout -b dev + +## 2) branch 확인 및 변경 (서버에서 만든 branch가 보이지 않을 땐, pull로 업데이트) +$ git branch # local +$ git branch -r # remote 저장소의 branch 확인 +$ git branch -a # local & remote branch 모두 확인 +$ git checkout "dev" # master branch로 이동 + +## 3) 특정 branch(dev)에 push +$ git push # 이미 dev branch에 있다면, 그냥 Push 해도됨. +$ git push -u origin dev # main에 있다면, push할 branch를 명시해줌. + +## 4) master branch에 merge +$ git checkout master # master branch로 이동 +$ git merge "dev" # merge 하고자 하는 branch명을 써주면 master로 merge 끝! +``` + + +
+--- +## Git Branch 이름 변경하기 +```sh +## 1) [local] branch 이름 변경 +$ git branch -m old_branch_name new_branch_name + +## 2) [remote] branch 이름 변경 +git push origin :old_branch_name + +## 3) 변경한 새로운 브런치를 업로드 +git push --set-upstream origin new_branch +``` + + + + +#### Reference +[1] [git lab 프로젝트 생성하기](https://goldsony.tistory.com/138) +[2] [git branch & commend](https://www.holaxprogramming.com/2018/11/01/git-commands/) +[3] [branch Merge하기](https://backlog.com/git-tutorial/kr/stepup/stepup2_4.html) +[4] [Git Branch 이름 변경하기](https://thdev.tech/git/2016/12/19/Git-Branch-Name-Change/) diff --git a/_posts/cate_10_Git/2021-10-07-git_collaboration_strategy.md b/_posts/cate_10_Git/2021-10-07-git_collaboration_strategy.md new file mode 100644 index 00000000000..a453e27c67b --- /dev/null +++ b/_posts/cate_10_Git/2021-10-07-git_collaboration_strategy.md @@ -0,0 +1,40 @@ +--- +layout: post +title: Git 협업 전략 +date : 07 Oct 2021 +category : Git +comments : true +--- + +`#git, #gitlab, #github, #branch, #collaboration +` + +이전 문서에서, Git을 활용한 프로젝트 관리의 시작 단계를 살펴보았다. +그러나 실제 팀원과 동일한 코드 내에서 작업을 해야하는 환경에서는 Git을 활용하더라도 코드가 충돌하여 에러가 뜨는 경우가 자주 발생하였다. +이에, Git을 이용한 협업 전략을 살펴보자. + +#### 현재 브랜치 상태 + - 최종 코드 : Master branch + - 개발 코드 : dev branch + +## Step 1. 격리된 개별 브랜치 생성하기 + : main - dev 뼈대를 두고, 각자의 브랜치 생성하하고 각자의 브랜치에서 작업을 수행 + * 이때 브랜치이름을 'feature/main', 'feature/run' 이렇게 네이밍을 항 +
+ +
+ +```sh +git branch [branch_nm] # 브랜치 생성 +git checkout [branch_nm]# 생성한 독립된 브랜치로 이동 +``` + + +## 2. 개별 브랜치에서 dev브랜치에 합치기 전에 검토 요청하기 (pull request) + : 개별 브랜치에서 만든 내용을 다시 dev에 합치려고 합니다. 이때 바로 합치기 보다, dev 브랜치에 내 코드를 합칠테니 검토를 부탁한다는 요청을 보냅니다. + + + + +#### Reference +[1] [초심자를 위한 Github 협업](https://milooy.wordpress.com/2017/06/21/working-together-with-github-tutorial/) diff --git a/_posts/cate_10_Git/2023-02-14-git_push_localRepo_to_remote.md b/_posts/cate_10_Git/2023-02-14-git_push_localRepo_to_remote.md new file mode 100644 index 00000000000..5dff62d02af --- /dev/null +++ b/_posts/cate_10_Git/2023-02-14-git_push_localRepo_to_remote.md @@ -0,0 +1,82 @@ +--- +layout: post +title: local repository를 remote repository로 push하기 +date : 14 Feb 2023 +category : Git +comments : true +--- + +`#git, #github, #branch , #push +` + +local 디렉토리를 git remote repository로 push하기. + + +## 1. (remote) git 서버에 repository 생성하기 + : 일반적인 repository를 생성하되, 'README.md' 파일을 성성하지 말 것. +- 생성시, 자동으로 'main' 브랜치가 생성되며, 이후 local에서 업로드한 dev 브랜치와 remote main 브랜치간 연결이 되어있지 않아 pull request가 생성되지 않는 아래와 같은 상황이 발생. + +
+There isn't anything to compare +main and mybranch are entirely different commit histories +
+ + +--- + +## 2. local main -> remote main repository git 연동(push) + : +```sh +## 1) local repository git 추적 시작 +git init +## 2) git add & commit +git add README.md +git commit -m "first commit" +## 3) local branch의 이름을 main으로 변경 (중요!!!) +git branch -M main +## 4) 원격 저장소 연결 +git remote add origin {remote} +## 5) local 저장소를 원격 origin/main 브랜치로 업로드 +git push -u origin main +``` + +## 3. dev branch 생성 하기 + +```sh +## 1) (local) branch 생성 : master branch에서 develop 이라는 새로운 branch를 만들고 갈아탄다. +$ git checkout -b dev + +## 2) branch 확인 및 변경 (서버에서 만든 branch가 보이지 않을 땐, pull로 업데이트) +$ git branch # local +$ git branch -r # remote 저장소의 branch 확인 +$ git branch -a # local & remote branch 모두 확인 + +## 3) (원격) dev branch 생성(push) +$ git push -u origin dev # push할 원격 dev branch를 명시. +``` + +## 4. dev -> main 으로 pull request 보내기 +```sh +## 1) dev branch 이동 +$ git checkout dev + +## 2) 코드 작업 +$ vi README.md # 'text 추가' + +## 3) git add & commit +git add README.md +git commit -m "first commit" + +## 4) (원격) dev branch 생성(push) +$ git push -u origin dev # push할 원격 dev branch를 명시. +``` + +위 작업 이후, git 사이트로 이동해보면, 정상적으로 pull reqeust가 가능 + + + +#### Reference + +[1] [connect_local_folder_to_git_repository](https://stackoverflow.com/questions/36132956/how-to-connect-local-folder-to-git-repository-and-start-making-changes-on-branch) +[2] [pull_request 안될때, A_brnach and B_brnach are entirely different commit histories](https://gobae.tistory.com/137) +[3] [기본 local 폴더 git 업로드 방법](https://huzz.tistory.com/34) \ No newline at end of file diff --git a/_posts/cate_11_Linux_Env/2021-08-03-linux-file_permission.md b/_posts/cate_11_Linux_Env/2021-08-03-linux-file_permission.md new file mode 100644 index 00000000000..78960390a9c --- /dev/null +++ b/_posts/cate_11_Linux_Env/2021-08-03-linux-file_permission.md @@ -0,0 +1,102 @@ +--- +layout: post +title: linux file permission (chmod & chown) +date : 03 Aug 2021 +category : Linux_Env +comments : true +--- + +`#linux, #file, #permission, #chmod, #chown +` + +## 1. 문제 상황 +

: linux에서 사용자 계정과 root 계정을 혼용해서 사용하다보면, 'permission error가 뜨는 경우가 종종 있다. 이때는 타 계정도 해당 폴더 및 파일에 접근하여 필요한 작업을 진행할 수 있도록 파일 권한을 변경해주어야 한다. +.

+ +## 2. linux 파일 권한 읽기 + : 우선 파일 및 폴더의 권한을 읽는 방법 부터 샅펴보자. `ls -all`명령어를 사용하면 아래와 같이 파일들의 권한과 정보를 확인 할 수 있다. +
+ +
+ +
+ +"drwxr-xr-x 13 root tand 4096 4 3 0066" 이 정보를 하나씩 확인하면, 아래와 같다. + + +
+ +#### * file type + - `d`' : dir + - `-` : 일반파일 + +#### * permission 종류 + - `r`(읽기): 파일의 읽기 권한 (4) + - `w`(쓰기): 파일의 쓰기 권한 (2) + - `x`(실행): 파일의 실행 권한 (1) + +## 3. chmod : linux 파일 권한 변경하기 + +``chmod (옵션) [변경할 권한 값] [변경할 파일]`` + + +: 파일 소유자는 `chmod` 명령어를 사용해, 그룹 또는 사용자 전체에게 해당 파일의 권한을 변경해 줄 수 있다. +권한값을 지정할 때, 권한을 계산하는 방식은 각 권한에 따른 수치를 더하는 방식이다. +이때 파일이 디렉토리인 경우, -R (대문자) 옵션을 사용해 하위 폴더까지 권한을 변경하면 된다. + +#### * 수행할 연산 + - `+` : 권한 추가 + - `-` : 권한 제거 + - `=` : 권한 부여(지정) -> 기존의 권한 속성이 사라짐 + +#### * 사용자 + - `u` : user, 소유자 + - `g` : group, 그룹 + - `o` : other, 일반 사용자 + - `a` : all, 모든 사용자 + +### (1) 권한값을 이용해, 모든 사용자의 권한을 각각 지정하는 경우 +```sh +# ex) 소유자 : rwx, 그룹 : r-x, 전체사용자 : r-- +chmod 751 test.txt +# ex) 소유자 : rwx, 그룹 : r-x, 전체사용자 : r--, 하위 디렉터리 폴더 모두 변경시 +chmod -R 751 file_nm +``` + +### (2) 권한을 변경할 사용자를 지정하여 권한을 각각 지정하는 경우 +```sh +# ex) 그룹에게 쓰기 기능을 추가 +chmod -R g+w directory_nm +# ex) 모든 사용자에게 읽기,쓰기 권한을 부여 +chmod -R a=rw directory_nm +``` + + +## 4. chown : linux 파일 소유권을 변경 + +``chown (옵션) [변경할 유저명 또는 그룹명] [변경할 파일]`` + + + : `chmod`는 권한을 변경했다면, `chown`은 파일 및 디렉토리의 소유권을 바꾸는 명령어다. + + +```sh +# ex_1) test.txt 파일에 대해 소유자를 user1로 바꾼다. +chown user_1 test.txt + +# ex_2) test.txt 파일에 대해 그룹명을 members1로 바꾼다. +chown :members1 test.txt + +# test.txt 파일에 대해 소유자 및 그룹명을 root로 바꾼다. +chown root test.txt + +# test.txt 파일에 대해 소유자는 user1, 그룹명은 user2로 바꾼다. +chown user1:user2 test.txt +``` + + + +#### Reference +[1] [리눅스 권한(permisson) 설정(chmod,chown)(1)](https://velog.io/@wmc1415/%EB%A6%AC%EB%88%85%EC%8A%A4-%EA%B6%8C%ED%95%9Cpermisson-%EC%84%A4%EC%A0%95chmodchown1) + +[2] [linux 파일, 폴더 권한 변경](https://itworld.gmax8.com/25) diff --git a/_posts/cate_11_Linux_Env/2021-12-15-linux-crontab_error_1.md b/_posts/cate_11_Linux_Env/2021-12-15-linux-crontab_error_1.md new file mode 100644 index 00000000000..30c2e31667f --- /dev/null +++ b/_posts/cate_11_Linux_Env/2021-12-15-linux-crontab_error_1.md @@ -0,0 +1,63 @@ +--- +layout: post +title: linux crontab bash setting error +date : 15 Dec 2021 +category : Linux_Env +comments : true +--- + +`#linux, #crontab, #bash, #shell +` + +## 1. 문제 상황 +: crontab을 사용하여 자동 예약을 걸어놓았는데, 위와 같은 에러가 발생함. + `/bin/sh: 1: [[: not found` + + +## 2. 문제 원인 + - 조건문 `[[]]` 는 bash 에서 사용하는 문법이나, 내가 crontab을 설정한 shell은 bash가 아닌, sh이었음. + - error 발생시 날아온 메일을 확인해보면 `SHELL=/bin/sh` SHELL이 sh로 설정되어있음을 알 수 있음. (메일 위치 : /var/mail) + +``` +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +Message-Id: <20211215033701.8B348A60019@localhost> +Date: Wed, 15 Dec 2021 12:37:01 +0900 (KST) + +/bin/sh: 1: [[: not found +``` + + +## 3. 해결 + - 스택 오버플로우에서 제시한 방법(Add #!/bin/bash at the top of file)이 작동하지 않았음. + - 스크립트 상단에 SHELL 옵션을 ```/bin/bash```로 설정함. + (서버개발자분께 문의드림..) + +``` +SHELL=/bin/bash +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +``` + + - 고의로 에러를 발생시킨 다음 crontab에서 날아온 메일에 SHELL 옵션이 bin/bash로 바뀌어있는 것을 확인 할 수 있음. + +``` +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +``` + + + + + +#### Reference +[1] [에러 문제 확인한 스택오버플로우](https://stackoverflow.com/questions/12230690/string-comparison-in-bash-not-found/17753098) diff --git a/_posts/cate_11_Linux_Env/2023-01-10-docker-cheat_sheet.md b/_posts/cate_11_Linux_Env/2023-01-10-docker-cheat_sheet.md new file mode 100644 index 00000000000..059f8b8a235 --- /dev/null +++ b/_posts/cate_11_Linux_Env/2023-01-10-docker-cheat_sheet.md @@ -0,0 +1,35 @@ +--- +layout: post +title: (Docker) cheat_sheet +date : 10 Jan 2023 +category : Linux_Env +comments : true +--- + +`#python, #docker, virtual_envrioment +` +--- +### 1. 도커 컨테이너 접속 & 종료 & 삭제 +```sh +# 1) 컨테이너 리스트 출력 +docker ps -a #모든 컨테이너 출력(정지 컨테이너 포함) +docker ps #실행 중인 컨테이너만 출력 + +# 2) 컨테이너 시작 +docker start hello #hello 이름의 컨테이너 시작 +docker restart hello #hello 이름의 컨테이너 재시작(재부팅) + +# 3) 컨테이너 접속 +docker attach hello #컨테이너에 접속(bash 쉘 접속) + +# 4) 컨테이너 종료 +docker stop hello #hello 이름의 컨테이너 종료 + +# 5) 컨테이너 삭제 +docker rm hello #hello 이름의 컨테이너 삭제 +docker rm -f hello #hello 이름의 컨테이너 강제삭제 +``` + +#### Reference +[1] [도커-명령어-모음](https://yeosong1.github.io/%EB%8F%84%EC%BB%A4-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%A8%EC%9D%8C) +[2] [Docker : 이미지와 레이어(layer) 구조](https://hyeo-noo.tistory.com/340) diff --git a/_posts/cate_11_Linux_Env/2023-01-16-docker-01_setup.md b/_posts/cate_11_Linux_Env/2023-01-16-docker-01_setup.md new file mode 100644 index 00000000000..f409832352a --- /dev/null +++ b/_posts/cate_11_Linux_Env/2023-01-16-docker-01_setup.md @@ -0,0 +1,143 @@ +--- +layout: post +title: (Docker) 01_Setup +date : 16 Jan 2023 +category : Linux_Env +comments : true +--- +`#python, #docker, virtual_envrioment +` +``` +이 글은 zini님의 GitBlog "Docker(도커) 시작하기, 설치부터 배포까지" 컨텐츠를 정리한 글입니다. +``` + +--- +### 배경 상황 +: 통상 사용하려는 패키지의 버전이 서로 다를 경우, 각 분석 환경을 독립적인 가상 환경으로 구축하여 사용한다.
+ +그런데 이때 패키지의 버전이 아닌, 파이썬 자체의 버전이 낮아 패키지 사용이 불가능한 케이스가 발생했다. 서버에 설치된 파이썬을 업데이트하려했으나, 기존의 파이썬 버전도 유지해야하는 이슈가 존재했다.
+ +이에 서버내에 복수의 파이썬을 설치하여, 버전별로 바라보는 경로를 다르게 잡는 방법도 존재하나, 독립적인 경로 설정의 어려움 및 서로 다른 파이썬 버젼에 따른 패키지간 충돌이 우려되었다. 때문에 이보다는 docker를 사용하여 독립적인 컨텐이너를 구축하여, 별도의 환경을 만들어 분석을 진행하고자 하였다. + + +# Docker Intro + + +## 1) Docker : Image & Container +: 도커에서 가장 중요한 개념은 `컨테이너`와 `이미지` !! +- **이미지** : 도커 컨테이너를 구성하는 파일 시스템과 실행할 어플리케이션 설정을 하나로 합친 것으로, 컨테이너를 생성하는 템플릿 역할을 하며, 불변함. +- **컨테이너** : 도커 이미지를 기반으로 생성되며, 파일 시스템과 어플리케이션이 구체화되어 실행되는 상태. + +따라서, 동일한 이미지로 다수의 컨테이너를 생성할 수 있고 컨테이너에 변화가 생겨도 이미지에는 영향을 주지 않는다.
+ +
+ + + +
+ + +## 2) Docker : Layer +: 도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 갖고 있기에 용량이 수백 MB이다. 처음 컨테이너를 만들기 위해서 이미지를 다운로드하는 건 필요하지만, 이미지의 불변성 때문에 현재 이미지에 작은 수정사항이 생길 시 새롭게 이미지를 다운로드 받기위해 수백MB를 다시 다운로드 받는 다면 매우 비효율적일 것이다.
+도커는 이 문제를 해결하기 위해, 레이어(Layer)라는 개념을 사용하여, 여러개의 레이어를 하나의 파일 시스템으로 사용할 수 있게 해준다.
+ + +
+ +Docker : 이미지와 레이어(layer) 구조 + + +도커의 이미지는 압축파일과 유사한 구조를 갖지만,
레이어를 공유한다는 점에서는 차이점을 지닌다. + +
+ + + +
+ +--- +# 2. Docker Setup +도커 설치는 자동 설치 스크립트를 사용하는 방법과 패키지를 직접 설치하는 방식 2가지로 나뉜다. +## 1) Docker 설치 +### (1) 자동 설치 스크립트 +```sh +sudo wget -qO- https://get.docker.com/ | sh +## hello-world 이미지도 같이 설치되는데, 사용하지 않을시 삭제 +sudo docker rm 'sudo docker ps -aq' +sudo docker rmi hello-world +``` + +### (2) 패키지 직접 설치 +- Ubuntu + ```sh + sudo apt-get update + sudo apt-get nistall docker.io + sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker + ``` +- CentOS7 + ```sh + sudo yum install docker + sudo service docker start #Docker 서비스 실행 + sudo chkconfig docker on #부팅시 자동 실행 + ``` +_Mac, Windows의 경우는 도커 공식홈에서 받고 설치하면 되므로 다른 글을 참조하자._ + +```sh +# 도커 설치 완료 확인 +sudo docker version +``` + +### (3) +Tip. 패키지 직접 설치 + : docker는 명령을 root 권한으로 실행해야 하기 때문에 + 명령어를 쓰기 위해서는 항상 sudo를 붙여줘야 한다. +이때, 일반적으로 root로 작업하는 경우는 많지 않기에, **일반 계정을 docker group에 추가**하여 sudo를 입력하지 않고 사용 할 수 있다. + +```sh +sudo usermod -aG docker ${USER} +sudo service docker restart +``` + +
+--- +## 2) 도커 이미지 다운로드 & 실행 +### (1) 도커 이미지 다운로드 +: 도커 이미지는 1) docker_hub 공식 이미지 다운 , 2) 직접 생성, 3) 다른 사용자가 만들어둔 이미지 다운 받는 방법이 있다. +- Docker Hub에서 이미지 받기 : `docker pull <이미지 이름>:<태그>` +- 사용자 이미지 받기 : `docker pull :` + +```sh +docker pull ubuntu:latest # 우분투 최신 버젼 다운로드 +docker pull ubuntu:18.04 # 우분투 특정 버젼(18.04) 다운로드 +docker pull python # python +``` + +### (2) 도커 이미지 실행 (= 컨테이너 생성) + : `docker run <옵션> <이미지 이름> <실행할 파일>` +```sh +# 1) 다운로드한 이미지 목록 확인 +docker image +# 2) ubuntu 이미지를 컨테이너로 생성 후 이미지 안의 /bin/bash를 실행 +docker run -it --name hello ubuntu /bin/bash +# docker run [-it] [--name 별명] /bin/bash +### -it 옵션을 사용하면 실행된 Bash 쉘에 입출력을 가능하게 해줌. +### --name 옵션을 사용하면 컨테이너 이름을 지정 (미지정시 자동으로 이름 부여) +# +``` +### (3) 도커 컨테이너에서 나오기 + : 위 명령어에서는 bash(terminal)을 실행하는 명령어까지 입력했기에, exit으로 빠져나오면, 컨테이너가 정지 상태로 변경된다. +```sh +exit +``` + + +
+ +--- +# 3. 나만의 이미지 생성하기(ft. Dockerfile) + + + + +#### Reference +[1] [Docker(도커) 시작하기, 설치부터 배포까지 - zini님의 git blog](https://zinirun.github.io/2020/08/15/how-to-use-docker/#1-%EB%8F%84%EC%BB%A4%EB%A5%BC-%EC%99%9C-%EC%93%B8%EA%B9%8C-%EB%AD%90%EA%B8%B8%EB%9E%98) +[2] [Docker : 이미지와 레이어(layer) 구조](https://hyeo-noo.tistory.com/340) diff --git a/_posts/cate_11_Linux_Env/2023-04-99-docker-02_image_generate.md b/_posts/cate_11_Linux_Env/2023-04-99-docker-02_image_generate.md new file mode 100644 index 00000000000..4036dc186fb --- /dev/null +++ b/_posts/cate_11_Linux_Env/2023-04-99-docker-02_image_generate.md @@ -0,0 +1,143 @@ +--- +layout: post +title: (Docker) 02_Image Generate +date : 16 Jan 2023 +category : Linux_Env +comments : true +--- +`#python, #docker, virtual_envrioment +` +``` +이 글은 zini님의 GitBlog "Docker(도커) 시작하기, 설치부터 배포까지" 컨텐츠를 정리한 글입니다. +``` + +--- +### 배경 상황 +: 통상 사용하려는 패키지의 버전이 서로 다를 경우, 각 분석 환경을 독립적인 가상 환경으로 구축하여 사용한다.
+ +그런데 이때 패키지의 버전이 아닌, 파이썬 자체의 버전이 낮아 패키지 사용이 불가능한 케이스가 발생했다. 서버에 설치된 파이썬을 업데이트하려했으나, 기존의 파이썬 버전도 유지해야하는 이슈가 존재했다.
+ +이에 서버내에 복수의 파이썬을 설치하여, 버전별로 바라보는 경로를 다르게 잡는 방법도 존재하나, 독립적인 경로 설정의 어려움 및 서로 다른 파이썬 버젼에 따른 패키지간 충돌이 우려되었다. 때문에 이보다는 docker를 사용하여 독립적인 컨텐이너를 구축하여, 별도의 환경을 만들어 분석을 진행하고자 하였다. + + +# Docker Intro + + +## 1) Docker : Image & Container +: 도커에서 가장 중요한 개념은 `컨테이너`와 `이미지` !! +- **이미지** : 도커 컨테이너를 구성하는 파일 시스템과 실행할 어플리케이션 설정을 하나로 합친 것으로, 컨테이너를 생성하는 템플릿 역할을 하며, 불변함. +- **컨테이너** : 도커 이미지를 기반으로 생성되며, 파일 시스템과 어플리케이션이 구체화되어 실행되는 상태. + +따라서, 동일한 이미지로 다수의 컨테이너를 생성할 수 있고 컨테이너에 변화가 생겨도 이미지에는 영향을 주지 않는다.
+ +
+ + + +
+ + +## 2) Docker : Layer +: 도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 갖고 있기에 용량이 수백 MB이다. 처음 컨테이너를 만들기 위해서 이미지를 다운로드하는 건 필요하지만, 이미지의 불변성 때문에 현재 이미지에 작은 수정사항이 생길 시 새롭게 이미지를 다운로드 받기위해 수백MB를 다시 다운로드 받는 다면 매우 비효율적일 것이다.
+도커는 이 문제를 해결하기 위해, 레이어(Layer)라는 개념을 사용하여, 여러개의 레이어를 하나의 파일 시스템으로 사용할 수 있게 해준다.
+ + +
+ +Docker : 이미지와 레이어(layer) 구조 + + +도커의 이미지는 압축파일과 유사한 구조를 갖지만,
레이어를 공유한다는 점에서는 차이점을 지닌다. + +
+ + + +
+ +--- +# 2. Docker Setup +도커 설치는 자동 설치 스크립트를 사용하는 방법과 패키지를 직접 설치하는 방식 2가지로 나뉜다. +## 1) Docker 설치 +### (1) 자동 설치 스크립트 +```sh +sudo wget -qO- https://get.docker.com/ | sh +## hello-world 이미지도 같이 설치되는데, 사용하지 않을시 삭제 +sudo docker rm 'sudo docker ps -aq' +sudo docker rmi hello-world +``` + +### (2) 패키지 직접 설치 +- Ubuntu + ```sh + sudo apt-get update + sudo apt-get nistall docker.io + sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker + ``` +- CentOS7 + ```sh + sudo yum install docker + sudo service docker start #Docker 서비스 실행 + sudo chkconfig docker on #부팅시 자동 실행 + ``` +_Mac, Windows의 경우는 도커 공식홈에서 받고 설치하면 되므로 다른 글을 참조하자._ + +```sh +# 도커 설치 완료 확인 +sudo docker version +``` + +### (3) +Tip. 패키지 직접 설치 + : docker는 명령을 root 권한으로 실행해야 하기 때문에 + 명령어를 쓰기 위해서는 항상 sudo를 붙여줘야 한다. +이때, 일반적으로 root로 작업하는 경우는 많지 않기에, **일반 계정을 docker group에 추가**하여 sudo를 입력하지 않고 사용 할 수 있다. + +```sh +sudo usermod -aG docker ${USER} +sudo service docker restart +``` + +
+--- +## 2) 도커 이미지 다운로드 & 실행 +### (1) 도커 이미지 다운로드 +: 도커 이미지는 1) docker_hub 공식 이미지 다운 , 2) 직접 생성, 3) 다른 사용자가 만들어둔 이미지 다운 받는 방법이 있다. +- Docker Hub에서 이미지 받기 : `docker pull <이미지 이름>:<태그>` +- 사용자 이미지 받기 : `docker pull :` + +```sh +docker pull ubuntu:latest # 우분투 최신 버젼 다운로드 +docker pull ubuntu:18.04 # 우분투 특정 버젼(18.04) 다운로드 +docker pull python # python +``` + +### (2) 도커 이미지 실행 (= 컨테이너 생성) + : `docker run <옵션> <이미지 이름> <실행할 파일>` +```sh +# 1) 다운로드한 이미지 목록 확인 +docker image +# 2) ubuntu 이미지를 컨테이너로 생성 후 이미지 안의 /bin/bash를 실행 +docker run -it --name hello ubuntu /bin/bash +# docker run [-it] [--name 별명] /bin/bash +### -it 옵션을 사용하면 실행된 Bash 쉘에 입출력을 가능하게 해줌. +### --name 옵션을 사용하면 컨테이너 이름을 지정 (미지정시 자동으로 이름 부여) +# +``` +### (3) 도커 컨테이너에서 나오기 + : 위 명령어에서는 bash(terminal)을 실행하는 명령어까지 입력했기에, exit으로 빠져나오면, 컨테이너가 정지 상태로 변경된다. +```sh +exit +``` + + +
+ +--- +# 3. 나만의 이미지 생성하기(ft. Dockerfile) + + + + +#### Reference +[1] [Docker(도커) 시작하기, 설치부터 배포까지 - zini님의 git blog](https://zinirun.github.io/2020/08/15/how-to-use-docker/#1-%EB%8F%84%EC%BB%A4%EB%A5%BC-%EC%99%9C-%EC%93%B8%EA%B9%8C-%EB%AD%90%EA%B8%B8%EB%9E%98) +[2] [Docker : 이미지와 레이어(layer) 구조](https://hyeo-noo.tistory.com/340) diff --git a/_posts/cate_11_Linux_Env/2023-04-99-pyenv_start_1.md b/_posts/cate_11_Linux_Env/2023-04-99-pyenv_start_1.md new file mode 100644 index 00000000000..cb4c0184e85 --- /dev/null +++ b/_posts/cate_11_Linux_Env/2023-04-99-pyenv_start_1.md @@ -0,0 +1,79 @@ +--- +layout: post +title: (venv) pyenv를 활용한 다양한 버전의 python +date : 10 April 2023 +category : Linux_Env +comments : true +--- +### 배경 상황 +`pyenv`는 프로젝트별로, 서로 다른 Python 버전을 필요로하는 경우, 디렉토리별로 서로 다른 가상환경을 구축하여 각기다른 python 버전을 지정하여 사용할 수 있게 만들어준다. + + +## 1. pyenv 설치하기 (ubuntu) +#### 1) 종속성 설치 + - pyenv를 설치하기전 OS에 맞는 종속성이 필요함. +```sh +sudo apt-get install -y make build-essential libssl-dev zlib1g-dev +# > libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev +# >libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl +``` + +#### 2) pyenv-installer 설치 +```sh +curl https://pyenv.run | bash +``` + : 정상 설치가 완료되면, `~/.pyenv` 폴더가 생성된다. + +#### 3) shell 실행시 pyenv 실행을 위한 설정 추가 + : 설치가 완료되면, `pyenv`가 shell 실행되기 위해서, `~/.bashrc` or `~/.bash_profile` 파일의 가장 하단에 아래 문구를 추가한다. + +```sh +export PATH="${HOME}/.pyenv/bin:$PATH" +eval "$(pyenv init -)" +eval "$(pyenv virtualenv-init -)" +``` + +#### 4) 쉘 재실행 + : 변경된 설정을 저장해주기 위한, 쉘 재실행 +```sh +exec "$SHELL" +``` + +## 2. pyenv를 활용한 파이썬 버전별로 설치하기 +#### 1) 설치 가능한 파이썬 버전 확인 +```sh +pyenv install --list | grep " 3\.[678]" # 3.6 ~3.7 사이의 버전만 살펴보기 +pyenv install --list # 모든 phthon 버전 확인하기 +``` +#### 2) pyenv를 활용한 파이썬 설치 & 삭제 +```sh +## 1) python 설치 +pyenv install 3.6.9 + +## 2) python 설치 여부 확인 +ls ~/.pyenv/versions/ + +## 3) python 설치 여부 확인 (2가지 방법중 1가지 선택) +rm -rf ~/.pyenv/versions/3.6.9 +pyenv uninstall 3.6.9 +``` + +## 3. pyenv로 사용한 파이썬 지정하기 (⭐️⭐️⭐️) +#### 1) 설치 가능한 파이썬 버전 확인 +```sh +pyenv versions # +# system +# 2.7.9 +# 3.6.9 +# * 3.6.9 +``` + + + + + + +#### Reference +[1] [01) pyenv와 가상환경](https://wikidocs.net/10936) +[2] [pyenv란? pyenv 사용하기](https://scshim.tistory.com/602) +[3] [[python] pyenv? virtualenv?](https://velog.io/@ryu_log/pyenv-virtualenv) \ No newline at end of file diff --git a/_posts/cate_12_GA_GTM/2021-03-07-GA_1.md b/_posts/cate_12_GA_GTM/2021-03-07-GA_1.md new file mode 100644 index 00000000000..557fa3bcc3b --- /dev/null +++ b/_posts/cate_12_GA_GTM/2021-03-07-GA_1.md @@ -0,0 +1,29 @@ +--- +layout: post +title: GA 클래스 정리 +date : 7 Mar 2021 +category : GA_GTM +comments : true +--- + + +# 1. Misunderstanding +## 1) GA는 분석 도구가 아닌, 측정 도구다. +- 측정 : 웹사이트의 다양한 구성요와 활동을 측정 +- 분석 : 반면, 분석은 측정된 결과를 이용하여, 다양한 웹사이트의 결과원인을 분석 + +
+단순 몇가지 양적인 지표(이탈율, 체류시간 등등)만으로 현황을 평가하는 건 위험 할 수 있다.
+GA가 보여주는 고객의 행동 데이터(양적 데이터)와 고객의 질적 데이터를 결합하여 분석해야 한다. +
+ +## 2) 데이터만 보면서 인사이트를 발굴한다는 착각 +: 문제의식 및 문제정의를 명확히 하고, 데이터로 확인하는 과정을 거쳐야지, 데이터만 무작정 처다보며 결과를 도출하려는 사고방식에서 벗어나자. + - 마케팅 목표를 달성 하기 위해, 아이디어를 도출하는 것 + - 가설을 수립하기 위해, 분석을 하는 것 이고 + - 분석을 하기 위해 데이터를 확인하는 것이고, + - 데이터를 확인하기 위해, 측정을 하는 것 + + +#### Reference +[1] [ㅍㅍㅅㅅ-디지털 데이터 분석툴 구글 애널리틱스 클래스](https://edu.ppss.kr/category/DATA/course/ga-class) diff --git a/_posts/cate_12_GA_GTM/2021-10-31-GTM_1_BASIC_INSTALL.md b/_posts/cate_12_GA_GTM/2021-10-31-GTM_1_BASIC_INSTALL.md new file mode 100644 index 00000000000..95b33e9933a --- /dev/null +++ b/_posts/cate_12_GA_GTM/2021-10-31-GTM_1_BASIC_INSTALL.md @@ -0,0 +1,75 @@ +--- +layout: post +title: GTM 개념 및 설치 +date : 31 Oct 2021 +category : GA_GTM +comments : true +--- + +`#googleTagManager +` +※ GTM 스터디를 위한 마케톨로지 가이드 요약 문서입니다. + +## 1. 구글 태그 관리자(GTM)란? + : 구글 + 태그 + 관리자 '구글에서 만든 태그를 (효율적으로) 관리해 주는 툴' + +#### 1) 태그(Tag) + - 태그 : 광고나 로그분석 프로그램을 실행시키는 짧은 자바스크립트 코드(= 스니펫)로 html 문서ㅔ 추가되어 코드내에 지정된 작업이 실행됨. + +
+ + +"GTM을 사용해 위 코드 대신, GTM의 코드가 설치되고, + 기능과 설정을 GTM에서 쉽게 관리가능" +
+ +## 2.태그 관리자 장점 +#### 1) html문서 편집 필요 X + : 대시보드에 값을 입력하는 방식으로 작성하기에, html 문서를 편집할 위험성이 낮음. + +#### 2) 태그 관리자 코드가 여러 코드를 대신함 + : GA, 카카오광고, 페이스북 등 여러 서비스의 추적 기능을 활성화 할 수 있음. +
+ +
+ +#### 3) 트리거를 이용해 복잡한 기능 구현 가능 + : 이벤트가 전달 복잡한 조건문을 마케터가 설정가능 +
+ +
+ + +## 2. GTM 설치 방법 +#### 1) GTM 컨테이너 스니펫(태그) +: GTM의 추적을 가능하게 해주는, 웹페이지상의 짧은 스크립트 코드 +
+ +
+ +#### 2) [컨테이너 스니펫] 스크립트 발급받기 + - step_1 : 구글 계정 준비 + - GA or Google Ads 에 사용한 메일 주소 추천) + - step_2 : 컨테이너 생성 + - 계정을 회사 / 컨테이너를 웹(앱) 단위로 관리 추천 +
+ +
+ + - step_3 : 컨테이너 클릭시 스니펫(태그 : 추적 코드) 출력! +
+ +
+ + - step_4 : 설치가이드에 따라 코드를 복사 & 웹페이지 상의 html 상단에 추가
+ - 대부분의 웹사이트 및 쇼핑몰 솔류션에서 웹페이지 상단 부분을 별도의 헤더 파일로 관리함.
+ - 워드프레서, 카페24, 고도몰 등 헤더 파일이 따로 있고, 그안에 태그가 있는 경우, 해당 파일에만 코드 추가시 모든 페이지에 적용됨. +
+ +
+ + +#### Reference +[1] [GTM관리자란 무엇이고 왜 사용하는가 - 마케톨로지](https://marketology.co.kr/all-category/tag-manager/%ea%b5%ac%ea%b8%80-%ed%83%9c%ea%b7%b8-%ea%b4%80%eb%a6%ac%ec%9e%90%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b4%ea%b3%a0-%ec%99%9c-%ec%82%ac%ec%9a%a9%ed%95%98%eb%8a%94%ea%b0%80/) + +[2] [구글 태그 관리자 설치 및 사용법 - 마케톨로지](https://marketology.co.kr/all-category/tag-manager/%EA%B5%AC%EA%B8%80-%ED%83%9C%EA%B7%B8-%EA%B4%80%EB%A6%AC%EC%9E%90-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95/) diff --git a/_posts/cate_12_GA_GTM/2021-10-31-GTM_2_USAGE.md b/_posts/cate_12_GA_GTM/2021-10-31-GTM_2_USAGE.md new file mode 100644 index 00000000000..2a1f652d430 --- /dev/null +++ b/_posts/cate_12_GA_GTM/2021-10-31-GTM_2_USAGE.md @@ -0,0 +1,78 @@ +--- +layout: post +title: GTM 사용방법 +date : 31 Oct 2021 +category : GA_GTM +comments : true +--- + +`#googleTagManager +`
+※ GTM 스터디를 위한 요약 문서입니다. + +## GTM 사용 방법 + : 기본 GTM 스니펫을 설치했다면, 이제 사이트의 정보를 분석툴(ex. GA, Sphere 등등)로 전달하기 위한 절차를 살펴 보자. + +## 1. GTM 주요 3요소 + : 우선 GTM의 태그를 설정하기 위해선 아래 3가지 요소를 잘 이해해야 한다. + + - 태그(how) : 변수와 트리거가 실행될 때 명령 + - Ex) "{회원가입}버튼 클릭시 {GA(or Sphere)}로 보내라" + - 트리거(when) : 행동 조건 및 발송 시점(특정 행동이 발생할 "때") + - Ex) '회원가입'버튼 클릭"시" + - 변수(what)): 트리거를 동작하는 변할 수 있는 값으로 이벤트에 담길 데이터 자체 + - Ex) 클릭하는 버튼명 + +
+ ---------------[작업 순서]--------------- +
+ + 1) 변수 생성 (기본 제공 & 사용자 정의 변수)
+ 2) 트리거 생성
+ 3) 태그 생성
+ 4) 제출 & 게시
+ 5) 작동 확인
+ 1) 미리보기(디버거)로 확인
+ 2) 애널리틱스 실시간 보고서 확인(스피어)
+ 3) 태그 어시스턴트로 확인 + +
+ + + + +## 2. 변수 생성 + - 상황에 따라 다른값을 가질 수 있음 + - 트리거의 실행조건을 정의하거나 태그의 동적인 정보를 전달 + +###### (1) GTM에 양식이 지정되어 있는 변수 + +
+트리거의 실행 조건이 아래와 같을
+ + +
+ + + + + + + + + + + + + + + + + + +#### Reference +[1] [구글 태그 관리자 설치 및 사용법](https://marketology.co.kr/all-category/tag-manager/%EA%B5%AC%EA%B8%80-%ED%83%9C%EA%B7%B8-%EA%B4%80%EB%A6%AC%EC%9E%90-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95/) + +[2] [GTM사용하기](https://medium.com/@cute3681/3-ga-tag-manager-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-2cb6b27e4e61) + +[3] [지원되는 태그](https://support.google.com/tagmanager/answer/6106924?hl=ko&ref_topic=3002579) diff --git a/_posts/cate_12_GA_GTM/2021-11-08-GTM_4_DataLayer.md b/_posts/cate_12_GA_GTM/2021-11-08-GTM_4_DataLayer.md new file mode 100644 index 00000000000..31f9508bd2e --- /dev/null +++ b/_posts/cate_12_GA_GTM/2021-11-08-GTM_4_DataLayer.md @@ -0,0 +1,72 @@ +--- +layout: post +title: GTM 사용방법 +date : 08 Nov 2021 +category : GA_GTM +comments : true +--- + +`#googleTagManager, #DataLayer +`
+ +※ GTM 스터디를 위한 요약 문서입니다. + +## 1. DataLayer + : GA "페이지뷰 추적"을 목표로 GTM을 활용하는 예시 + +#### 1) GTM 주요 3요소 + - 태그 : 변수와 트리거가 실행될 때 명령 + - Ex) '회원가입'버튼 클릭시 GA로 보내라 + - 트리거 : 행동 + - Ex) '회원가입'버튼 클릭 + - 변수 : 트리거를 동작하는 변할 수 있는 값(조건) + - Ex) 클릭하는 버튼명 + +
+ ------------[작업 순서]------------ +
+ + 1) 변수 생성 (기본 제공 & 사용자 정의 변수)
+ 2) 트리거 생성
+ 3) 태그 생성
+ 4) 제출 & 게시
+ 5) 작동 확인
+ 1) 미리보기(디버거)로 확인
+ 2) 애널리틱스 실시간 보고서 확인(스피어)
+ 3) 태그 어시스턴트로 확인 + + +#### 1) 변수 생성 + - 상황에 따라 다른값을 가질 수 있음 + - 트리거의 실행조건을 정의하거나 태그의 동적인 정보를 전달 + + +
+트리거의 실행 조건이 아래와 같을
+ + +
+ + + + + + + + + + + + + + + + + + +#### Reference +[1] [구글 태그 관리자 설치 및 사용법](https://marketology.co.kr/all-category/tag-manager/%EA%B5%AC%EA%B8%80-%ED%83%9C%EA%B7%B8-%EA%B4%80%EB%A6%AC%EC%9E%90-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95/) + +[2] [GTM사용하기](https://medium.com/@cute3681/3-ga-tag-manager-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-2cb6b27e4e61) + +[3] [지원되는 태그](https://support.google.com/tagmanager/answer/6106924?hl=ko&ref_topic=3002579) diff --git a/_posts/cate_12_GA_GTM/2022-07-28-GA_GA4_study_session.md b/_posts/cate_12_GA_GTM/2022-07-28-GA_GA4_study_session.md new file mode 100644 index 00000000000..7deae852da0 --- /dev/null +++ b/_posts/cate_12_GA_GTM/2022-07-28-GA_GA4_study_session.md @@ -0,0 +1,56 @@ +--- +layout: post +title: GA4 +date : 28 July 2022 +category : GA_GTM +comments : true +--- + +`#GA4` + +※ 김선영 대표, 스피어가 GA4와 공존할 수 있는 방안 모색 + +## 1. GA4 특징 +#### 1) 사용자 식별성 강화 + - 플랫폼을 소유하기에, 쿠키 의존도를 낮추고 코호트 방식으로 사용자 식별성을 높임. + - 구글 / 아마존 / 네이버등 플랫폼을 소유한 업체만이 갖는 장점. + +#### 2) 사이트별 크로스 교차 분석 + +#### 3) 이벤트 기반의 데이터 모델 + - PV -> Event 기반의 행동분석 + +#### 4) 향상된 수집기능 + - 스크롤, 체류시간, 마우스 클릭 등 다양한 행동까지 수집. + > 구글이 자동 테깅한 데이터를, 우리도 기본으로 받아서 사용하는 방식 + +#### 5) 새로운 측정 항목 + - 단순 설치가 아닌, 참여 세션수(Engaged session) 활용 + - Engaged Session : 10초 이상 지속, 전환 이벤트 1회 이상 발생, 페이지 조회 2회 이상 발생 + +#### 6) 기본 채널 그룹 + - attribution 채널을 유료와 오거닉으로 구분 --> 어려운 영문을 국문으로? + +#### 7) 목표 vs 전환 + - 주요 산업별 전환 KPI는 뻔하기에, 주요 KPI들을 미리 리스트업해놓고 비즈니스 하기. + +#### 8) 예측 잠재고객 + - 7일 이내, 잠재 고객 생성 해서 광고 효율성 올리는게 중점 + - 세팅 이후, 컨설팅 니즈가 존재하며, 툴을 사용해서 잠재고객을 뽑고 싶어함. + - 쉽게 컨설팅 없이도 툴을 사용해서 잠재고객을 뽑을 수 있으면 좋겠음. + +#### 9) Raw Data : Big Query 연동 + - GA4의 big query와, 내부 데이터를 연동하여 CRM을 제공 + +#### +) debug 기능 + - 데이터 정합성 향상 기능 +#### +) dynamic link + +## 2. +#### 1) +- bigquery 추천 교육 : query ga4 data by simo ahava + + + + +#### Reference diff --git a/_posts/cate_13_Tableau/2021-12-06-Tableau_Study_1.md b/_posts/cate_13_Tableau/2021-12-06-Tableau_Study_1.md new file mode 100644 index 00000000000..9d5486295c6 --- /dev/null +++ b/_posts/cate_13_Tableau/2021-12-06-Tableau_Study_1.md @@ -0,0 +1,54 @@ +--- +layout: post +title: Tableau_Study_1 +date : 06 Dec 2021 +category : Tableau +comments : true +--- + +# Tableau +## 주요 전처리 기능 정리 + + +#### 1) 데이터 전처리 +##### (1) 피벗 (long-form) + : wide-form -> long-form데이터 형태여야 시각화 가능 +``` +Step_1) 전환해야하는 축 범위 선택 +Step_2) 전환해야하는 축 마지막 컬럼에서 화살표 클릭 +Step_3) 피벗 클릭 +``` + + +##### (2) 데이터 원본 필터링 +``` +Step_1) 데이터 원본 시트 우측 상단 '필터' '추가' 클릭 +Step_2) 기준이 될 필드 선택 +Step_3) 필터 기준 선택 +``` +
+ + + + + +
+ + +##### (3) 새로운 필드 생성하기 (계산된 필드 생성하기) +``` +Step_1) 계산 대상 필드 마우스 우측 클릭 +Step_2) 계산된 필드 생성 +Step_3) 계산식 입력 +``` +
+ +
+ + +##### (+) 사용자그룹별 분석시 데이터의 형태 + : 다수 사용자그룹을 생성하여, 특정항목에 대한 분석을 진행해야 하는 경우, 아래 두가지 테이블을 생성한 후 분석하는 방향으로 진행. + 이후 두 테이블을 서로 merge할시, Tabeau에서 쉽게 filter를 줄 수 있음. + - 분석 테이블 + - 유저별 사용자 그룹 테이블 +||| <---- 예시 테이블 만들 차례! diff --git a/_posts/cate_13_Tableau/2021-12-12-Tableau_Study_Training_1.md b/_posts/cate_13_Tableau/2021-12-12-Tableau_Study_Training_1.md new file mode 100644 index 00000000000..0ea3f9672ad --- /dev/null +++ b/_posts/cate_13_Tableau/2021-12-12-Tableau_Study_Training_1.md @@ -0,0 +1,49 @@ +--- +layout: post +title: Tableau_Study_1 +date : 12 Dec 2021 +category : Tableau +comments : true +--- + +# Tableau +`#막대차트, #간트차트, #이중축` + +## 목표 +: 개별 bar plot에 레이블을 다는 것은 어렵지 않으나, 아래와 같이 개별 컬럼에 2가지 형태의 서로 다른 레이블을 다는 경우, `간트차트`와 `이중축`을 사용해볼 수 있다. + +
+ +
+ +## 단계별 과정 +##### Step_1 + : 2개 이상의 필드 추가(시즌별 & 리그별) +
+ +
+ +##### Step_2 : 개별 그래프 & 통합 그래프 만들기 + : 열 선반에 있는 카운트를 하나 더 추가 후, 해당 그래프에서 색상에 들어있는 필터를 삭제하고 간트 차트로 변경 +
+ +
+ +##### Step_3 : 2개 그래프 합치기 + : 우측 그래프기준 '이중 축'선택, 이때 기존 그래프까지 간트차트로 바뀌기에 기존 차트는 다시 Bar그래프로 변경 +
+ + + +
+ +##### Step_4 : 축 동기화 + : 하단 -> 마우스 오른쪽 -> "축 동기화" 클릭 +
+ + + +
+ +#### Reference +[1] [테블루 손흥민 시즌별 대회별 득점수 시각화 #막대차트 #간트차트 #이중축](https://www.youtube.com/watch?v=kn4e5e8XICA) diff --git a/_posts/cate_14_SQL/2021-07-28-sql_1.md b/_posts/cate_14_SQL/2021-07-28-sql_1.md new file mode 100644 index 00000000000..e46d97500c8 --- /dev/null +++ b/_posts/cate_14_SQL/2021-07-28-sql_1.md @@ -0,0 +1,99 @@ +--- +layout: post +title: SQL for starter +date : 28 July 2021 +category : SQL +comments : true +--- +## 1. SQL이란? (Structured Query Language) +

: 관계형 데이터베이스 관리 시스템(RDBMS)의 데이터를 관리하기 위해 특수 설계된 특수 목적 프로그래밍 언어.

+(SQL종류 : MySQL, PostgreSQL, MariaDB, Oracle) + + + +### (1) 데이터베이스 관리 시스템(DBMS)의 특징 + +- 실시간 접근 +- 계속적인 변화 +- 동시 공용 +- 내용에 의한 참조 + +
"데이터 저장소에서 데이터를 추출하기 위한 도구"
+ +### 1) SQL 분류 +#### (1) DML(Data Manipulation Language) + - 데이터 조작 목적의 언어 + - DML을 사용하기 위해서는 타겟이 되는 '테이블'이 반드시 정의되야함. + - SELECT(선택) + - INSERT(삽입) + - UPDATE(수정) + - DELETE(삭제) + + +#### (2) DDL(Data Definition Language) + - 데이터 정의 언어 + - 데이터 베이스, 테이블, 뷰, 인덱스 등의 데이터 베이스 개체를 생성/삭제/변경 역할 + - 실행 즉시 MySQL에 적용되며, ROLLBACK 및 COMMIT 불가 + - CREATE + - DROP + - ALTER + + +#### (3) DCL(Data Control Language) + - 데이터 제어 언어 + - 사용자에게 특정 권한을 부여/제거시 사용 + - GRANT + - REVOKE + - DENY 등 + + +## 2. 실습 환경 및 연습 TABLE +[sqlfiddle.com](http://sqlfiddle.com/) 이 사이트에, 아래 CREATE 코드 입력 및 Build schema 버튼 실행 +```sql +CREATE TABLE IF NOT EXISTS `user_log` ( + `index` INTEGER NOT NULL AUTO_INCREMENT, + `user_id` VARCHAR(6) NOT NULL, + `event` VARCHAR(200) NOT NULL, + `event_date` date NOT NULL, + PRIMARY KEY (`index`, `user_id`) +) DEFAULT CHARSET=utf8; +INSERT INTO `user_log` (`user_id`, `event`,`event_date`) VALUES + ('1', 'login_facebook', '2018-03-12'), + ('1', 'write_posting', '2018-03-12'), + ('1', 'write_comment', '2018-03-12'), + ('1', 'view_posting', '2018-03-12'), + ('1', 'view_posting', '2018-03-12'), + ('2', 'login_facebook', '2018-03-12'), + ('2', 'view_posting', '2018-03-12'), + ('2', 'view_posting', '2018-03-12'), + ('2', 'write_comment', '2018-03-12'), + ('2', 'logout', '2018-03-12'), + ('2', 'login_facebook', '2018-03-13'), + ('3', 'login_google', '2018-03-13'), + ('3', 'write_posting', '2018-03-13'), + ('3', 'view_posting', '2018-03-13'), + ('3', 'view_posting', '2018-03-13'), + ('3', 'purchase_item', '2018-03-15'), + ('3', 'write_comment', '2018-03-14'), + ('1', 'view_posting', '2018-03-14'), + ('4', 'view_posting', '2018-03-14'), + ('5', 'purchase_item', '2018-03-13'); +``` + +* local 학습용 계정 : th_sql_study + +## 3. SQL공부하기 + - [데이터 분석, 먹고 들어가기 위한 SQL 공부법(1편)](https://www.minwookim.kr/how-to-learn-sql-1/) + - [데이터 분석, 먹고 들어가기 위한 SQL 공부법(2편)](https://www.minwookim.kr/how-to-learn-sql-2/) + +### 1) 기본 문법 학습하기 +#### (1) 책 +- [데이터 분석을 위한 SQL 참고도서 추천](https://brunch.co.kr/@datarian/4) +- 칼퇴족 김대리는 알고 나만 모르는 SQL + + + + +#### Reference +[1] [비전공자를 위한 SQL](https://zzsza.github.io/development/2018/03/18/sql-for-everyone/) +[2] [MySQL 데이터베이스 한번에 끝내기 SQL Full Tutorial Course using MySQL Database](https://www.youtube.com/watch?v=vgIc4ctNFbc) diff --git a/_posts/cate_14_SQL/2022-07-05-sql_2.md b/_posts/cate_14_SQL/2022-07-05-sql_2.md new file mode 100644 index 00000000000..061859ff630 --- /dev/null +++ b/_posts/cate_14_SQL/2022-07-05-sql_2.md @@ -0,0 +1,92 @@ +--- +layout: post +title: SQL for starter - 기초 +date : 05 July 2022 +category : SQL +comments : true +--- + + +## SQL 사용을 위한 데이터 베이스 용어 + - 데이터 베이스 : 여러 사람에게 공유되어, 사용될 목적으로 관리되는 데이터 집합 + - 테이블(table) : 특정 종류의 데이터를 구조적 목록으로 구분한 것 + - 스키마(schema) : 테이블에 어떤 데이터를 어떤 '형식'으로 저장할 것인가를 정의한 것 + - 열 (schema) : 테이블을 구성하는 각각의 정보 (= field) + - 행 (recod) : 데이터가 한 줄에 저장된 것 + + +## 1. 기본 구조 및 Basic 문법 +#### 1) 데이터 베이스 선택 +```sql +SHOW DATABASE -- 데이터 베이스 조회 +``` + +#### 1) basic 문법 +```sql +SELECT '컬럼 이름' +FROM '테이블 이름' +WHERE '조건' +GROUP BY '그룹화할 컬럼' +HAVING '그룹화한 뒤 조건' +LIMIT '제한할 개수' +``` + + +### 1) SELECT / FROM + - SELECT `[불러오고자 하는 대상 (Columns)]` + - FROM [찾을 대상이 있는 공간(Table)] +```sql +-- HR 테이블에서, 'ID','GENDER','AGE' 변수를 불러와라. +SELECT ID, GENDER, AGE +FROM HR +``` + +
+ +### 2) WHERE + : 조건문 추가 +```sql +-- HR 테이블에서, 'ID','GENDER','AGE' 변수를 불러오며, +-- 이때, 성별은 남성이며 'AGE'는 60세 이상 +SELECT ID, GENDER, AGE +FROM HR +WHERE 'GENDER' == 'male' & 'AGE' >= 60 +``` + +
+ +### 3) GROUP BY + : 컬럼들을 특정 규칙에 맞춰서 그룹화함(Aggregate) + + +### 4) ORDER BY + : 컬럼들을 특정 규칙에 맞춰서 정렬 +```sql +SELECT * +FROM user_log +WHERE user_id = '1'; +``` + + + +#### 연습 [sqlfiddle.com](http://sqlfiddle.com/) + - 1) “1”번 유저의 모든 이벤트 로그를 확인. +```sql +SELECT * +FROM user_log +WHERE user_id = '1'; +``` + +- 2) “1”번 유저의 이벤트별 로그 '횟수'를 계산 +```sql +SELECT user_id, event, event_id + COUNT (user_id) AS 'event_cnt' +FROM user_log +WHERE user_id = '1' +GROUP BY user_id, event, event_id; +``` + + + +#### Reference +[1] [비전공자를 위한 SQL](https://zzsza.github.io/development/2018/03/18/sql-for-everyone/) diff --git a/_posts/cate_15_cloud/2020-10-18-cloud.md b/_posts/cate_15_cloud/2020-10-18-cloud.md new file mode 100644 index 00000000000..2f8fa3c3ef3 --- /dev/null +++ b/_posts/cate_15_cloud/2020-10-18-cloud.md @@ -0,0 +1,53 @@ +--- +layout: post +title: Cloud Intro +date : 18 Oct 2020 +category : cloud +comments : true +--- + +# 1. Cloud 이점 +## 1) Cloud Computing + - 서버 생성 & 삭제가 용이 -> 서비스 대응 속도 향상 + - 서버 구매 대비 시간과 비용 절역 + - 확장성 / 재해 복구 / 보안성 + - 유연한 예산 운영 / 탄력성 / 민첩성 + +## 2) CapEx vs OpEx +### (1) 자본 지출(CapEx) + - 물리적 인프라 구매 사용 + - 서버 구매 후 서비스 운용 + - 높은 초기 비용 + +### (2) 운영 지출(CapEx) -> Cloud + - 필요에 따라 서비스, 제품 구독 + - 서비스에 필요한 제품을 구매 + - 소비기반 모델(종량제) -> 선결제 비용이 없음 + - 사용한 만큼 결제 + +------------------------------------ + +# 2. Iaas / Paas / Sass +
+ + +
+ +## 1) Iaas : Infrastructure as a service + - 운영체제(os)부터 사용자가 모두 관리(가장 유연) + - 관리에 따른 리소스가 많이 사용됨 + +## 2) Paas : Platform as a Service + - 클라우드 제공자가 플랫폼을 제공 + - 사용자는 운영체제, 플랫폼 관리 및 업데이트를 신경쓰지 않고 제품에만 집중 + - 다만 유연성이 떨어짐 + +## 3) Saas : Software as a Service + - 클라우드 제공자가 응용 프로그램을 제공(ms365) + + ------------------------------------ + +# 3. Cloud 모델 이해하기 + - 공용 클라우드 : AWS / Azure + - 사설 클라우드 : 사내 인트라넷 + - 하이브리드 클라우드 : diff --git a/_posts/cate_15_cloud/2020-10-18-cloud_azure_1.md b/_posts/cate_15_cloud/2020-10-18-cloud_azure_1.md new file mode 100644 index 00000000000..17c00547f66 --- /dev/null +++ b/_posts/cate_15_cloud/2020-10-18-cloud_azure_1.md @@ -0,0 +1,63 @@ +--- +layout: post +title: Cloud Azure 1 +date : 18 Oct 2020 +category : cloud +comments : true +--- + + +# 1. Azure Architecture 구성요소 + +### 1) Region + - 데이터 센터 모음 + - 사용자와 가장 가까운 지역에 리소스를 배포 가능 + - 한국 : 서울 / 부산에 위치해있음 + * BCDR(Business continuity and disaster recovery) + : 쌍을 이루는 지역으로 재해복구를 위해존재 + +### 2) Geography + - 데이터 상주 및 규정 준수 경계를 유지하는 개별 시장 + - 아메리카 / 유럽 / 아시아 태평양 / 중동 / 아프리카 + +### 3) 가용성 옵션 + - 서버 분산 저장 및 재해복구 등에 필요한 옵션 + +### 4) Azure Resource Manager + - Azure를 관리하는 계층 + - 리소스 또는 리소스 그룹을 생성, 구성, 관리, 삭제 + - AzureAD를 통한 접근 제어 + +-------------------- + +# 2. Azure Compute + +### 1) Azure Compute 서비스 + - Azure VM : 운영체제를 직접 관리하는 서비스 + - VM Scale Sets : Azure VM Image를 이용하여 자동으로 확장 또는 축소 가능 + - App Service : 사용자느 ㄴ소스 파일만 업로드하면 알아서 동작하는 PaaS + e.g) Web App, API App, Mobile App, Logic App, Functions등 + - Functions : App Services의 하나로 이벤트 기반으로 compute작업 수행 + +#### VM 생성 +[Azure VM 생성 가이드](https://microsoftlearningkoreanlab.github.io/AZ-900TKR-MicrosoftAzureFundamentals/Instructions/Walkthroughs/01-Create%20a%20virtual%20machine.html) + + + +### 2) Azure Container 서비스 + - Azure Container Instances + : Azure가 관리하는 Container Cluster에 Container Image를 업로드 할 수 있는 Paas 서비스(...?) + + - Azure Kubernetes service + : 많은 수의 컨테이너를 관리하기 위한 Container Orchestrator + +---- + + +# 3. Azure Network +### 1) Azure Container 서비스 +- Azure Container Instances +: Azure가 관리하는 Container Cluster에 Container Image를 업로드 할 수 있는 Paas 서비스(...?) + +- Azure Kubernetes service +: 많은 수의 컨테이너를 관리하기 위한 Container Orchestrator diff --git a/_posts/cate_15_cloud/2020-10-25-cloud_azure_2.md b/_posts/cate_15_cloud/2020-10-25-cloud_azure_2.md new file mode 100644 index 00000000000..2093f4595ba --- /dev/null +++ b/_posts/cate_15_cloud/2020-10-25-cloud_azure_2.md @@ -0,0 +1,47 @@ +--- +layout: post +title: Cloud Azure 2 +date : 25 Oct 2020 +category : cloud +comments : true +--- + + +# 7. Azure Architecture Bigdata & ML + +### 1) Azure BigData Services +#### (1) Azure SQL Data Warehouse +: 큰 규모의 데이터에서 복잡한 쿼리를 빠르게 실행할 수 있는 관리형 서비스 + +#### (2) Azure HDInsight +: Hadoop 파일 시스템을 사용하는 완전 관리형 분석 서비스. 방대한 양의 데이터를 보다 쉽고 빠르게 처리하며, 비용 효율적으로 처리 가능 + +#### (3) Azure Data Lake Analytics +: 빅데이터를 단순화하는 주문형 분산 작업 서비스. 데이터를 변환 및 추출에 사용 + +#### (4) Azure Databricks +: Apache Spark 환경을 사용하여 AI 솔루션을 빌드하며, 각종 ML 프레임워크와 라이브러리 제공 + +### 2) ML +#### (1) *Azure Machine Learning Service* +: 머신 러닝의 모델을 개발하고 교육, 테스트 배표, 관리, 추적을 하는데 사용되는 클라우드 기반 솔루션 + +#### (2) Azure Machine Learning Studio +: 사용자가 코드를 작성하지 않고, 머신러닝 솔루션을 구축하고 테스트 및 배포를 할 수 있는 솔루션. 드래그 앤 드롭 방식의 시각적 작업 영역을 제공 + +--------------------- + +# 8. Serverless + - 클라우드 서비스 공급자가 서버를 실행하고 머신의 리소스를 동적으로 관리하는 클라우드 컴퓨팅 실행 모델 + - 용량 단위 구매가 아닌, 소비 단위 구매 + - 일반적으로 실행 횟수, 실행 시간(CPU), 실행 용량(memory)을 기반으로 과금 + +### 1) Serverless 서비스 +#### (1) Azure Functions + : 기본 플랫폼이나 인프라를 구성하지 않고, 소스 코드를 실행할 수 있는 서비스. 이벤트 기반으로 동작 + +#### (2) Azure Logic App + : 앱, 데이터, 시스템, 서비스를 통합하여 작업 또는 비즈니스 프로세스 및 워크 플로를 자동화 할 수 있는 서비스 + +#### (3) Azure Event Grid + : 균일한 이벤트 소비를 위해 발행, 구독모델을 사용하는 완전 관리형 지능형 이벤트 라우팅 서비스 diff --git a/_posts/cate_15_cloud/2022-02-22-aws_iam_setting.md b/_posts/cate_15_cloud/2022-02-22-aws_iam_setting.md new file mode 100644 index 00000000000..44a03873206 --- /dev/null +++ b/_posts/cate_15_cloud/2022-02-22-aws_iam_setting.md @@ -0,0 +1,37 @@ +--- +layout: post +title: AWS_계정생성_및_IAM_User_생성하기 +date : 22 Feb 2022 +category : cloud +comments : true +--- + +: AWS에 최초 계정을 생성하고 나면, 해당 계정은 Root 계정이 된다. 이 루트 계정은 모든 권한을 가지고 있으나, AWS는 보안 및 업무에 따른 권한 이슈로 Root계정의 사용보다는 각 목적에 맞는 권한을 갖춘 IAM User를 생성해서 사용하길 강력하게 권고하고 있다. + +생성 절차별로 스텝을 따라가면 되기에, 개념과 각 스텝을 잘 설명해주신 블로그 링크를 참조하자. + + + +## 1. 루트 사용자 vs IAM 사용자 + : 루트 사용자는 모든 권한을 갖지만, 보안이 뚫렸을 경우 모든 리소스에 큰 피해가 갈 수 있다. 때문에 IAM 계정은 목적에 맞게 권한을 계정을 분할하여 생성 및 관리하게 된다. + [IAM 장점] + - AWS 계정의 공유 액세스 + - 세분화된 권한 + - 무료 + +> IAM은 AWS 리소스에 대한 액세스를 안전하게 제어하는 서비스로, 자세한 설명은 아래 링크를 참조하자. + [원잇님 블로그 : 루트 사용자 vs IAM 사용자](https://wonit.tistory.com/348) + + +## 2. 관리자 & 세부 목표 IAM User(Upload File to S3) 생성 + : AWS는 IAM User를 생성하는 역할도, 관리자 IAM User를 먼저 만들어 진행하라고 권고하기에, 관리자급 IAM 사용자 생성 및 관리자 폴더를 생성하고, 이후, 특정 세부 목표를 지닌 IAM 유저를 생성해야한다. + + +> [나도 한 번 만들어 보자's 블로그 : AWS IAM 사용자 만들기](https://ukayzm.github.io/aws-create-iam-user/) + + + + +#### Reference +[1] [AWS 공식 가이드 : 루트 사용자 vs IAM 사용자](https://wonit.tistory.com/348) +[2] [나도 한 번 만들어 보자's 블로그 : AWS IAM 사용자 만들기](https://ukayzm.github.io/aws-create-iam-user/) diff --git a/_posts/cate_15_cloud/2022-02-24-aws_file_send_to_s3.md b/_posts/cate_15_cloud/2022-02-24-aws_file_send_to_s3.md new file mode 100644 index 00000000000..c0c29298cda --- /dev/null +++ b/_posts/cate_15_cloud/2022-02-24-aws_file_send_to_s3.md @@ -0,0 +1,246 @@ +--- +layout: post +title: AWS_EC2_or_Local_S3로_파일_전송하기 +date : 24 Feb 2022 +category : cloud +comments : true +--- + +: 타인 계정의 AWS S3로 파일을 자동으로 전달해야하는 업무가 생겨났다. 일반적으로는 동일 계정의 EC2에서 S3로 파일을 전송하는 레퍼런스가 많이 있으나, 나의 로컬 서버(linux)에서 타인 계정의 S3로 접근해야하는 상황이기에, 필요한 과정을 스텝별로 정리해보며 진행해보자. + +* 반면 S3 버킷을 소유한 계정에서, S3 접근 및 업로드 권한이 있는 IAM계정을 생성하여 계정 Key값(Access key값 / Secret key)을 공유해준다면, +동일 계정내에서 파일을 업로드하는 이슈가 되기에, 아래의 2.번 IAM 설정 스탭을 진행하지 않아도 된다. + +--- + +> [계정] +$\star$ A계정 : 접근을 희망하는 계정 (나) +$\star$ B계정 : S3를 소유한 계정 (타인) + + + +# 1. Linux instence에서 AWS CLI(Command Line Interface) 설치하기 + + - AWSCLI를 설치하는 리눅스 명령어 : `$sudo apt-get install awscli`
+ 그러나 위 명령어를 바로 입력하면 `E: Unable to locate package awscli`라는 에러가 발생한다. 지정된 상위 폴더가 부재하여 발생하는 에러로 추측된다. 따라서 아래와 같은 순서로 CLI를 설치해주자. + + +## CLI 설치 Step +```bash +# 1) 경로 폴더 생성 -- 이 과정이 없을시 위 에러가 발생 +$ mkdir awscliv2 # 폴더 생성 (v2로 진행 권장) +$ cd awscliv2 # 폴더 이동 + +# 2) 설치 링크 실행 및 파일 output지정 +$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +$ unzip awscliv2.zip # 압축 해제 +$ sudo ./aws/install # cli 설치 +``` + +> [AWS CLI 설치 AWS 공식 가이드 링크(영문)](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html) + + +--- + +# 2. IAM(Identity and Access Management) 설정하기 + : CLI 설치가 완료됐다면, 목표 S3 계정에 접근하기 위한 IAM 설정해야한다. 여기에서는 파일을 전달할 A계정과 S3를 소유하고 있는 B가 각각 해야하는 작업이 다르기에 구분하여 세팅 절차를 살펴보자. + + > [타계정(B)에게 내 계정(A)의 S3 접근 권한 부여하는 방법(youtube)](https://www.youtube.com/watch?v=OhupTkhPoZM) + > [타계정(B)에게 내 계정(A)의 S3 접근 권한 부여하는 방법(docs)](https://aws.amazon.com/ko/premiumsupport/knowledge-center/s3-cross-account-upload-access/) + + > [계정] + $\star$ A계정 : 접근을 희망하는 계정 (나) + $\star$ B계정 : S3를 소유한 계정 (타인) + + +## 1) [A계정] IAM 세팅 +### (1) 관리자 IAM 계정 + : 우선 AWS는 모든 권한을 갖는 루트사용자와 일부 권한만을 갖는 IAM사용자로 나뉜다. 그리고 IAM사용자에서도 IAM 계정을 생성할 관리자와 특정 목적별 IAM 계정으로 구분되어야 하는데, 만약 관리자용 IAM 사용자가 없다면 아래 포스팅을 따라 '관리자용 IAM계정'을 먼저 만들자. + +> [TH : IAM 사용자 생성 방법](/_posts/cate_15_cloud/2022-02-24-aws_file_send_to_s3.md) +[AWS 공식 가이드 : IAM 사용자 생성 방법](https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/id_users_create.html) +[나도 한 번 만들어 보자's 블로그 : AWS IAM 사용자 만들기](https://ukayzm.github.io/aws-create-iam-user/) + + +### (2) S3에 파일을 전송할 목적의 IAM 계정 + : 관리자 IAM계정이 생성되었다면, 해당 계정으로 로그인 후 아래 절차대로 IAM 계정에 권한을 부여해주자. + + - Step 1 : A 계정 로그인 (관리자 IAM) + + + - Step 2 : 검색창에 IAM 검색 및 상단 IAM 클릭 + + + - Step 3 : 좌측 'users' 탭 클릭 및 권한을 부여할 계정 선택 + + + + - Step 4 : `Add inline policy` 버튼 클릭 및 `Json`탭 이동 + + + + - Step 5 : 정책 추가 코드 삽입 및 타겟 S3 ARN 입력 + + ``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:PutObjectAcl" + ], + "Resource": [ + "arn:aws:s3:::DOC-EXAMPLE-BUCKET", # target s3 bucket ARN + "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" + ] + } + ] + } + ``` + + - Step 6 : 코드로 새롭게 추가한 정책명 입력 및 생성 + + + +--- + +## 2) [B계정] 접근 권한을 부여할 S3에 정책 추가 + [A]의 IAM 계정에 정책 추가가 완료되었다면, [A]가 접근할, S3 버킷에 [A계정]에서 설정했던 정책에 대한 추가가 필요하다. + + + - Step 1 : [B계정] 로그인 및 S3 설정 진입 + + + + - Step 2 : 접근을 허용할 S3 버킷 선택 + + + - Step 3 : S3 Permission 권한 설정 + 상단 `Permission` 탭 클릭 + + 스크롤을 내려서, 우측 `edit`클릭 + + 아래 policy 붙여넣으며, 이때 Principal의 값으로는 계정 A에 있는 IAM 사용자의 ARN을 입력해야한다! + + 끝났다면 하단 `save changes` + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "DelegateS3Access", + "Effect": "Allow", + "Principal": {"AWS": "arn:aws:iam::999999999999:user/UploadData"}, ## 계정 A에서 IAM 사용자의 Amazon 리소스 이름(ARN) + "Action": ["s3:PutObject", "s3:PutObjectAcl"], + "Resource": [ + "arn:aws:s3:::DOC-EXAMPLE-BUCKET", + "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" + ] + } + ] +} +``` + +# 3. 서버에 IAM 사용자 등록 + : 위 단계까지 마쳤다면, 우리는 A계정과 B계정의 버킷이 연결된 상황이다. 이제 다음 작업으로 EC2 or Linux 서버내에 나의 A계정을 등록해주자. + + ## EC2 & Sever의 AWS CLI에 IAM 계정 등록 절차 + ```bash + # 1) 경로 폴더 이동 -- 이 과정이 없을시 위 에러가 발생 + $ cd awscliv2 # 폴더 이동 + + # 2) configure 등록 + $ aws configure + > AWS Access Key ID [None]: 직접 입력 + > AWS Secret Access Key [None]: 직접 입력 + > Default region name [None]: 직접 입력 # + > Default output format [None]: 직접 입력 + + + # 3) 목표 S3 버킷이 출력된다면, 성공!! + $ aws s3 ls + + ``` + + + +# 4. [Bash] CLI S3 접근하기 + : 여기까지 왔다면, 이제 AWS CLI를 활용하여, 목표 버킷에 접근할 수 있다. CLI를 활용하여 버킷의 접근하는 코드는 아래와 같다. + +```bash +#------------------------------# +# 1) 버킷 생성 +#------------------------------# +aws s3 mb s3://{new-s3-bucket} + +#------------------------------# +# 2) 버킷 리스트 조회 +#------------------------------# +aws s3 ls s3://{my-s3-bucket} +aws s3 ls s3://{my-s3-bucket}/{directory_name}/ # 폴더 내 파일 탐색 + +#------------------------------# +# 3) 파일 복사 +#------------------------------# +### 단순 파일 복사 +aws s3 cp {local_file_nm} s3://{my-s3-bucket} +### 버킷내 디렉토리를 만들어서 복사할 경우, {버킷명}/{디렉토리명}}/ 명시 +#### [local -> S3] +aws s3 cp {local_file_nm} s3://{my-s3-bucket}/{directory_name}/ +### [S3 -> local] +aws s3 cp s3://{my-s3-bucket}/{directory_name}/{file_name} {local_file_nm} + +#------------------------------# +# 4) 폴더 이동 +#------------------------------# +aws s3 mv s3://{my-s3-bucket}/{file_name} + +#------------------------------# +# 5) 파일 삭제 +#------------------------------# +aws s3 rm s3://{my-s3-bucket}/{file_name} + +#------------------------------# +# 6) 동기화 (recommend using sync rather than cp) +## Note this part tends to hang sometimes, so just ctrl+c and run it again. By sync, the process will resume. +#------------------------------# +# local -> S3 +aws s3 sync s3://{my-s3-bucket} local_dir/ +# S3 -> local +aws s3 sync local_dir/ s3://{my-s3-bucket} +``` + +> [EC2에서 S3 접근하기 (CLI 코드 정리)- 시나브로101블로그](https://blog.naver.com/PostView.nhn?blogId=m2seo&logNo=222051627467) + +# 5. [python] S3 접근하기 + : 끝으로 파일 업로드 과정에서 파이썬 코드로 구현하여해야 하는 경우 코드를 활용하여 file을 S3 버킷으로 업로드할 수 있다. + + ```python + import boto3 + + s3_client = boto3.client('s3') + # 파일 올리기 + s3_client.upload_file('올리고자하는파일', '나의버킷이름', '버킷에저장될이름') + # 파일 다운받기 + s3_client.download_file('나의버킷이름', '내려받을파일', '로컬에저장될이름') + ``` + --- + + + + +#### Reference +##### CLI 설치 +[1-1] [EC2 인스턴스에서 S3 접근, AWS CLI - 홍&천 블로그](https://cjsal95.tistory.com/28) +[1-2] [Moving Data Between S3 and EC2 Instances - github](https://github.com/churchlab/millstone/wiki/Moving-Data-Between-S3-and-EC2-Instances) +[1-3] [AWS : CLI 설치 AWS 공식 가이드 링크(영문)](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html) + +##### IAM 계정 세팅 +[2-1] [AWS : 타계정(B)에게 내 계정(A)의 S3 접근 권한 부여하는 방법(youtube)](https://www.youtube.com/watch?v=OhupTkhPoZM) +[2-2] [AWS : 타계정(B)에게 내 계정(A)의 S3 접근 권한 부여하는 방법(docs)](https://aws.amazon.com/ko/premiumsupport/knowledge-center/s3-cross-account-upload-access/) + +##### CLI로 S3 접근 코드 +[3-1] [EC2에서 S3 접근하기 (CLI 코드 정리)- 시나브로101블로그](https://blog.naver.com/PostView.nhn?blogId=m2seo&logNo=222051627467) diff --git a/_posts/cate_999_etc/2021-07-06-ML_interview_list.md b/_posts/cate_999_etc/2021-07-06-ML_interview_list.md new file mode 100644 index 00000000000..97112eb1a7e --- /dev/null +++ b/_posts/cate_999_etc/2021-07-06-ML_interview_list.md @@ -0,0 +1,92 @@ +--- +layout: post +title: ML interview +date : 06 July 2021 +category : ETC +comments : true +--- + +[TAN.D 면접 질문 및 공부 LIST] + +■ 인과관계와 상관관계의 차이 [O] : https://namu.wiki/w/%EC%83%81%EA%B4%80%EA%B4%80%EA%B3%84%EC%99%80%20%EC%9D%B8%EA%B3%BC%EA%B4%80%EA%B3%84#toc + : 인과관계는 변수간 선후관계가 명확해야 한다. ex) 아이스크림 판매량, 익사사망자, "기온" + + 상관관계 : 둘 이상의 변수가 양/음의 방향으로 함께 움직인다면 상관관계가 있다고 할 수 있음 + + 인과관계 : 상관관계는 곧바로 인과관계로 이어지지 않는다. + + +■ CORR 상관관계가 부재할 경우 pca 사용여부에 대한 고민[●] + : Correation값이 낮을 시 굳이 PCA를 사용할 필요 없다 + + PCA의 불필요한 분산을 줄이고 주요 분산축(가장 큰 분산축)만 남겨놓기에 그 결과에 있어서 '주성분 변수간는 서로 상관관계가 전혀없다' + + 따라서 Correalation의 결과 변수간 상관관계가 없다면, PCA를 실시해서 찾은 축들도 크게 의미 없는 축일 수 밖에 없다 + + +■ Corr 제거 후 Tree사용의 부적합성...? [●] + + Corr 존재할 때 Regression 모델 사용시 : 회귀 계수 불안정(변수 독립성X) + + Corr 존재할 때 Tree 모델 사용시 + : 분류에 중요 변수가 결정트리의 분리 조건에 나타나지 않게 되는 문제 발생(계수 불안정성으로 모델에 중요변수 미포함) + : So 분류 정확도 감소 + + +■ 일변량(단변량) / 이변량 / 다변량이란? + + 단변량 분석 + : 종속변수가 1개 ex) T-test, ANOVA, LinearRegression + + 이변량 분석 + : 독립변수만 2개 ex) 상관분석 + + 다변량 분석 + : 종속변수가 2개이상(비지도) ex) 요인분석, 군집분석, 정준상관분석, 다차원척도법 등 + + +■ Outlier detection시 독립변수가 1개일때와 2개 이상일때 방법적 차이[●] +※ https://lsjsj92.tistory.com/556 + + 독립변수가 많을 때 1: 1대응으로 outlier를 제거한다면, 너무 많은 데이터 손실을 발생함 + + 따라서 Corr을 통해 종속변수에 영향을 크게 미칠 것으로 예상되는 변수에 한하여 Outlier진행 + + +■ (추가) 변량에 따른 Outlier detection 방법[O] +※ https://m.blog.naver.com/PostView.nhn?blogId=jinwon_hong&logNo=140160660331&proxyReferer=https%3A%2F%2Fwww.google.com%2F + + 일변량 : 표준점수(Z-score)를 기준으로 제거, 이때 회기분석을 single으로 multi linear regression 진행 후 + + 이변량 : 산포도를 이용하여 독립변수와 종속변수의 관계성을 테스트하여 특정 신뢰구간에 포함되는 지 확인 + + 다변량 : 마할로노비스 D^2값을 이용해 D^2/df가 2.5~4이상인 표본 + + +■ Sigmoid를 어떻게 비전공자에게 coeff 를 활용해서 설명 할 수 있는가 [▲] +※ http://hleecaster.com/ml-logistic-regression-concept/ + - logistic도 결국은 선형회귀와 마찬가지로 변수에 계수(coefficient)를 곱하고 절편(intercept)을 더해서 예측 값을 찾고자 한다 + - 다만, logistic은 마지막 결과값에 예측치 대신, log-odds라는 걸 계산해주는 과정이 추가됨. + - log-odds 계산 및 sigmoid함수를 활용한 확률값 계산 : sigmoid(log-odd) + 1) odd = 사건이 발생할 확률을 발생하지 하지 않을 확률로 나눈 값 + - log-odd = log(odd)를 취한 값 + - 이렇게 구한 logodd를 sigmoid함수에 넣으면 1/1+e^-z 0과1사이의 확률값으로 변환됨 + + +■ Accuracy만 보는 것의 단점 --> 블로그 그래프 반드시 확인 할 것 [●] +※ https://nittaku.tistory.com/297 + - 희박한 가능성으로 발생할 상황에 대해서는 제대로 평가할 수 없음(Unbalanced data!) + - So 모든 임계치에 대해서 정확도를 평가함으로써 희박한 가능성에 따른 낮은 확률의 정확도도 포함 할 수 있게 됨 + - 임계치 0 : TN가 모두 FP이 되고, TN = 0이되면서 1-TNR가 1이됨 => ROC 커브 우측 종점 + - 임계치 1 : TP가 모두 FN가 되고, TN = 1이 되면서 1-TNR가 0이됨 => ROC커브 좌측 시작점 + + +※ 1종오류와 2종오류 + Type I error : False Positive: 실제 Negative인 정답을 Positive라고 예측 (False) + Type II error : False Negative: 실제 Positive인 정답을 Negative라고 예측 (False) + + +■ xgboost의 약한 모델?이라 하는 것이 linear인가 logistic인가?[●] + : 여러개의 이진 노드!!! 트리모델이기에 당연히 logistic!! + - 약한 Logistic모델(편향이 큰 모델)로 분류 후 오분류에 가중치를 주어 다음 모델을 생성하는 작업을 반복 + - 추후 만들어진 모델들을 결합하여 하나의 모델 구축 + + +■ CNN을 설명하시오 [▲] +※ http://taewan.kim/post/cnn/ + - ① CNN의 필요성 : 기존 Regression에서는 변수간 독립성이 반드시 확보되어야함 + - ② 그러나 이미지 데이터의 경우, 어쩔수 없이 주변값들이 서로 영향을 받을 수 밖에 없음 + - ③ 주변의 Correlation을 고려하여 이미지의 특징을 추출(by 필터) --이때 어떤 필터를 주는지에 따라 특징을 추출한 결과값이 달라짐 + - ④ 여러개의 필터를 거쳐 나온 결과 채널을 다시 새로운 input값으로 사용해가며 CNN structure 구축 + - ⑤ 최종 3차원 필터를 1차원으로 펴서 input값으로 분류 진행 "fully connected" + ++ PCA를 진행해서 주성분을 찾지 못했거나 성능을 개선하지 못했다면, 역으로 왜 주성분을 찾지 못하였는지 거꾸로 생각해보자 ++ PCA를 test데이터가 많아서 적용했다했면, 차라리 train과 test를 합쳐서 진행해볼 생각 해보자 + +- 파이썬 모듈화 프로젝트 진행 경험 diff --git a/_posts/cate_999_etc/2022-02-10-Error_could_not_be_resolved_Pylance.md b/_posts/cate_999_etc/2022-02-10-Error_could_not_be_resolved_Pylance.md new file mode 100644 index 00000000000..02f5f12a290 --- /dev/null +++ b/_posts/cate_999_etc/2022-02-10-Error_could_not_be_resolved_Pylance.md @@ -0,0 +1,40 @@ +--- +layout: post +title: Error - could not be resolved Pylance +date : 10 Feb 2022 +category : ETC +comments : true +--- +`#vscode, #python, #jupyter_notebook, #Pylance +` +## 1. 문제 상황 +: VScode로 파이썬을 작성하면, `Pylance`라는 패키지가 내 코드내의 에러를 미리 예상하여 확인할 수 있도록 도움을 준다. +그런데, 외부 폴더에 있는 모듈을 불러오는 과정에서 아래와 같은 경고성 에러가 발생한다.실제로는 외부 폴더의 경로를 `sys.path.append()`로 잡아주었기에 코드는 정상 작동하나, 해당 모듈을 클릭하거나, 모듈 내 함수가 미리보기로 출력되지 않는 불편함이 발생한다. + +
+ + + +
+ + +
+## 2. 문제 원인 + : `Pylance`는 디폴트로 내 워크스페이스의 root 경로를 포함한다. 때문에 서브 디렉토리를 경로로 추가하고 싶은 경우에는 vscode 세팅 기능을 활용하여 extraPaths를 설정해주어야 한다. + +
+## 3. 문제 해결 방법 + (1) 세팅 화면 열기 : `ctrl(cmd)` + `,` + (2) 추가 경로 옵션 검색 : `python.analysis.extraPaths`검색 + (3) 추가 경로 입력 버튼 클릭 : `Add Item` + (4) 추가 서브 디렉토리 경로 입력 : ex) `/home/th/subdirectory/` + +
+ + + +
+ + +#### Reference +[1] [stackoverflow - import 'module' could not be resolved Pylance](https://stackoverflow.com/questions/65252074/import-path-to-own-script-could-not-be-resolved-pylance-reportmissingimports) diff --git a/_posts/cate_99_seminar/2021-08-25-data_seminar.md b/_posts/cate_99_seminar/2021-08-25-data_seminar.md new file mode 100644 index 00000000000..707d0f120d3 --- /dev/null +++ b/_posts/cate_99_seminar/2021-08-25-data_seminar.md @@ -0,0 +1,101 @@ +--- +layout: post +title: 데이터로 세상을 해석하기 +date : 25 Aug 2021 +category : Seminar +comments : true +--- + +`#하용호, #데이터 +` +# 데이터로 세상을 해석하기 + +## 비즈니스 성장은 + - 결과 측정 가능 + - 상황의 제어를 내가 가능하게 하는 것 + - 반복 수행이 가능 할 것 +: 위 과정을 가능하게 하는 것 "피드백 루프(feedback loop)" +
+ +
+ +
+## 회사에 데이터 적용하기 +#### 과거 확인 -> 현재 개선 -> 미래 예측 + +## 1. 과거 확인 + - 과거분석 : 지난 매출 / 기존 출시 제품 / 고객 분석 + +#### + problem + : 대부분의 사람들은 현재를 분석하거나, 미래를 예측하는 펜시한 기술에 집중하지만, 대부분의 회사는 과거를 제대로 보는 일조차 하지 않음. + +#### + 데이터 축적 방식 + - 모든 데이터를 다 축적하려는 기업이 많음. 그러나, 완벽한 모든 데이터 구축은 오랜 시간이 걸리며, 불가능함. + - So 해결하고자 하는 주제를 명확히 정하고 이에 필요한 데이터를 모으는 것이 중요 +
+ +
+ +
+## 2. 현재 개선 + +
+ +
+ + - 현재 개선 : 성장 / 광고 효율 / 유저 획득에 관련된 업무 + - 그로스 해킹 & 퍼포먼스 마케팅 + - problem 회사에서 문제를 정의하는 방식 + : "매출을 올리자 or 비용을 줄이자" 식의 포괄적인 문제정의 + +
+#### 2-1) OMTM(One Metric That Matters) + - 모두가 집중해야할 하나의 목표(중단기적)를 잡고 문제를 해결해 나갈 것 + - 갱신 주기가 빠를 것 + - 후행지표가 아닌, 선행지표에 해당하는 KPI를 설정할 것 + +#### + OMTM을 찾는 기술적 방법 +
+ + + + +
+ +
+#### 2-2) A|B test + : OMTM을 통해 지표 및 메트릭을 잡았다면, 개선 활동은 어떻게 해야하는가 +#### + A|B TEST를 위해 확보되어야 할 3가지 + - 데이터 : 우리만 가지고 있는 배타적 데이터(ex. 고객 로그 데이터) + - 채널 : 고객에게 가치를 전달할 수단(ex. push 메세지, 광고 배너 등) + - 선택지 : 유저에게 오퍼할 선택의 충분한 양과 질(ex. 상품, 고객 대상, 컨텐츠) +
+ +
+ + +
+## 3. 미래 예측 +
+ +
+ + +
+## 현실 +
+ +
+ + +## 해결책 +
+ + +
+ + +## 정리 +
+ +
diff --git a/_tmp/2021-01-10-stock_auto_1.md b/_tmp/2021-01-10-stock_auto_1.md new file mode 100644 index 00000000000..41dddd332c8 --- /dev/null +++ b/_tmp/2021-01-10-stock_auto_1.md @@ -0,0 +1,25 @@ +--- +layout: post +title: stock_auto_1 : environment setting +date : 10 Jan 2021 +category : stock +comments : true +--- + +### 목차 + - 1) 크레온 HTS 설치(계좌 개설) + - 2) 파이썬 설치 & 라이브러리 세팅 + - 3) 크레온 API + +### 사전 세팅 +- *크레온 계좌* +- *윈도우 환경* +- *파이썬 3.86 32bit - 증권사 API 사용 목표* + + + + + + +#### Refernce +[1] [파이썬 주식 투자 자동화 1강 - 환경 설정 및 크레온 API 사용 기초](https://www.youtube.com/watch?v=4DzGOpsT3bw&t=106s) diff --git a/_tmp/2021-01-21-R squared & adj R squared.md b/_tmp/2021-01-21-R squared & adj R squared.md new file mode 100644 index 00000000000..526d9b9a931 --- /dev/null +++ b/_tmp/2021-01-21-R squared & adj R squared.md @@ -0,0 +1,15 @@ +--- +layout: post +title: R square & adjusted R square +date : 23 Jan 2021 +category : ML +comments : true +--- + : 모델 설명력 + + + + + +#### Refernce +[1] [[결정계수] R square와 adjusted R square](https://specialscene.tistory.com/63) diff --git a/_tmp/2021-02-12-ARIMA.md b/_tmp/2021-02-12-ARIMA.md new file mode 100644 index 00000000000..5b3a283f0d1 --- /dev/null +++ b/_tmp/2021-02-12-ARIMA.md @@ -0,0 +1,19 @@ +--- +layout: post +title: ARIMA +date : 12 Mar 2021 +category : ML +comments : true +--- + +# 1. 서론 : 시계열 분석(Time series analysis)이란 + : 시계열 분석은 시간을 독립변수로 활용한다. 여기서 과거 시점의 데이터가 현재 시점에 데이터에 영향을 줄 수 있다는 특징과 계절성 및 요일성등 시계열만이 지닌 특성으로 인하여 시계열 데이터를 분석하기 위해서는 추가적인 고려가 필요하다. + +# 2. ARIMA(Autoregressive Integrated Moving Average) + + + + +#### Refernce +[1] [머신 러닝으로 금 시세를 예측 해보자 feat. ARIMA](https://predictor-ver1.tistory.com/3) +[2] [ARIMA, Python으로 하는 시계열분석 (feat. 비트코인 가격예측)](https://byeongkijeong.github.io/ARIMA-with-Python/) diff --git a/_tmp/2021-02-99-Normality_test(Gussian).md b/_tmp/2021-02-99-Normality_test(Gussian).md new file mode 100644 index 00000000000..429db54429a --- /dev/null +++ b/_tmp/2021-02-99-Normality_test(Gussian).md @@ -0,0 +1,16 @@ +--- +layout: post +title: normality test : Gaussian +date : 23 Jan 2021 +category : ML +comments : true +--- +# normality test : Gaussian + + + + + +#### Refernce +[1] [Time Series Forecasting using Granger’s Causality and Vector Auto-regressive Model](https://towardsdatascience.com/granger-causality-and-vector-auto-regressive-model-for-time-series-forecasting-3226a64889a6) +[2] [정규성 검정(Normality Test)](https://bioinformaticsandme.tistory.com/37) diff --git a/_tmp/2021-03-12-AdaBoostClassifier.md b/_tmp/2021-03-12-AdaBoostClassifier.md new file mode 100644 index 00000000000..96f6671af64 --- /dev/null +++ b/_tmp/2021-03-12-AdaBoostClassifier.md @@ -0,0 +1,15 @@ +--- +layout: post +title: AdaBoostClassifier +date : 8 Feb 2021 +category : ML +comments : true +--- + + +# 1. AdaBoostClassifier + + + +#### Refernce +[1] [ㅍㅍㅅㅅ-디지털 데이터 분석툴 구글 애널리틱스 클래스](https://edu.ppss.kr/category/DATA/course/ga-class) diff --git a/_tmp/2023-01-09-python_virtual_environment.md b/_tmp/2023-01-09-python_virtual_environment.md new file mode 100644 index 00000000000..7ba063d0887 --- /dev/null +++ b/_tmp/2023-01-09-python_virtual_environment.md @@ -0,0 +1,23 @@ +--- +layout: post +title: Python - virtual environment +date : 09 Jan 2023 +category : Linux_Env +comments : true +--- +`#vscode, #python, #jupyter_notebook, #Pylance +` +## 1. +: + +
+ + + +
+ + + +#### Reference +[1] [나도코딩 - 파이썬 가상환경 사용 방법 (중요) | venv +](https://www.youtube.com/watch?v=o_vKT80BBkw) diff --git a/_tmp/2023-04-10-pyenv_start_1.md b/_tmp/2023-04-10-pyenv_start_1.md new file mode 100644 index 00000000000..e571784367b --- /dev/null +++ b/_tmp/2023-04-10-pyenv_start_1.md @@ -0,0 +1,102 @@ +--- +layout: post +title: (venv) pyenv를 활용한 다양한 버전의 python +date : 24 Jun 2021 +category : Linux_Env +comments : true +--- +# 목표 +`pyenv`는 프로젝트별로, 서로 다른 Python 버전을 필요로하는 경우, 디렉토리별로 서로 다른 가상환경을 구축하여 각기다른 python 버전을 지정하여 사용할 수 있게 만들어준다. + +# 1. pyenv 설치하기 +```sh +# 1) pyenv 설치 +##(Mac 사용자) +brew update && brew install pyenv +brew update && brew upgrade pyenv # 최신 버전 파이썬 미지원시 -> pyenv를 업그레이드 +## (Linux 사용자) +curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash +``` + +```sh +# 2) .bash_profile 파일에 pyenv 경로 포함 (Mac & Linux) +echo ' +export PYENV_ROOT="$HOME/.pyenv" +export PATH="$PYENV_ROOT/bin:$PATH" +eval "$(pyenv init -)" +' >> ~/.bash_profile + +source ~/.bash_profile +``` + +```sh +# 3) 최신 버전 파이썬 미지원시 -> pyenv를 업그레이드 +pyenv update +``` + + +# 2. pyenv 설치하기 +```sh +# 1) 설치가능한 파이썬 버전 확인 +pyenv install --list # 설치가능한 Python 항목 리스트 확인하기 +pyenv install --list | grep "^\s*3\.7" # 3.7 버전 리스트만 골라서 확인하기 +pyenv install --list | grep -v - # -이 들어가지 않은 버전, 즉 개발 중이 아닌 CPython만 확인 +pyenv install $(pyenv install --list | grep -v - | tail -1) # 가장 최신 버전 설치시 +``` + +```sh +# * 설치 중 문제가 발생시 Mac 유저 대처방안 +# Xcode Command Line Tools 설치 +xcode-select --install + +# 이미 설치된 상태라면 +# “xcode-select: error: command line tools are already installed, +# use "Software Update" to install updates”라고 뜸. +# 그럴 땐 당황하지 말고 아래 명령을 이어서 입력한다. + +# 의존성이 있는 패키지 설치 +brew install readline xz zlib sqlite3 + +# zlib 설정 +export LDFLAGS="${LDFLAGS} -L/usr/local/opt/zlib/lib" +export CPPFLAGS="${CPPFLAGS} -I/usr/local/opt/zlib/include" +export PKG_CONFIG_PATH="${PKG_CONFIG_PATH} /usr/local/opt/zlib/lib/pkgconfig" + +# 위에 써놨던 거지만... 다시 설치 시도! +pyenv install $(pyenv install --list | grep -v - | tail -1) +``` +```sh +pyenv versions # 설치된 Python 버전 확인 +``` + +# 3. 가상 환경 만들기 +```sh +# 1) pip 설치하기 +pip install --upgrade pip + +# 2) 프로젝트 폴더 생성 및 local python 버전 지정 +mkdir my-project # 가상환경을 구축할 프로젝트 파일 생성 +cd my-project # 해당 파일로 이동 +pyenv local 3.7.2 # 해당 폴더 내에서 'local'로 사용할 파이썬 버전 지정!!!! + +# 3) 가상환경 생성 +virtualenv venv # 해당 프로젝트에서 생성할 가상환경 생성 + +# 4) 가상환경 진입 & 퇴출 +source venv/bin/activate # 진입 -> 앞에 (venv)라는 표식이 붙음 +deactivate + + +매번 activate 하는 게 귀찮다면 pyenv-virtualenv를 사용하면 된다. 이렇게 하면 해당 프로젝트에 venv 폴더가 필요 없지만 pyenv의 버전으로 가상 환경이 추가된다는 점에 주의하자. +위 부분 부터 해야함... 위부분 무슨말인지 모르겠음... + +``` + +# * local default python 꼬이는 문제 + + + + +#### Reference +###### 1~ +[1] [파이썬 버전 관리](https://alphahackerhan.tistory.com/23) diff --git a/about.md b/about.md index 9d12ee3c566..b723c3916a0 100644 --- a/about.md +++ b/about.md @@ -1,4 +1,4 @@ ---- + diff --git a/assets/210825_data_seminar/IMG_2281.PNG b/assets/210825_data_seminar/IMG_2281.PNG new file mode 100644 index 00000000000..57354b281ca Binary files /dev/null and b/assets/210825_data_seminar/IMG_2281.PNG differ diff --git a/assets/210825_data_seminar/data_seminar_1.png b/assets/210825_data_seminar/data_seminar_1.png new file mode 100644 index 00000000000..4d88cfb3aff Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_1.png differ diff --git a/assets/210825_data_seminar/data_seminar_10.png b/assets/210825_data_seminar/data_seminar_10.png new file mode 100644 index 00000000000..70dcd860286 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_10.png differ diff --git a/assets/210825_data_seminar/data_seminar_11.png b/assets/210825_data_seminar/data_seminar_11.png new file mode 100644 index 00000000000..77a6f03f8e2 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_11.png differ diff --git a/assets/210825_data_seminar/data_seminar_12.png b/assets/210825_data_seminar/data_seminar_12.png new file mode 100644 index 00000000000..dbe99cae687 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_12.png differ diff --git a/assets/210825_data_seminar/data_seminar_2.png b/assets/210825_data_seminar/data_seminar_2.png new file mode 100644 index 00000000000..b5f1bb9451d Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_2.png differ diff --git a/assets/210825_data_seminar/data_seminar_3.png b/assets/210825_data_seminar/data_seminar_3.png new file mode 100644 index 00000000000..63406d4a407 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_3.png differ diff --git a/assets/210825_data_seminar/data_seminar_4.png b/assets/210825_data_seminar/data_seminar_4.png new file mode 100644 index 00000000000..328104738cf Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_4.png differ diff --git a/assets/210825_data_seminar/data_seminar_4_2.png b/assets/210825_data_seminar/data_seminar_4_2.png new file mode 100644 index 00000000000..3993c5d19f1 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_4_2.png differ diff --git a/assets/210825_data_seminar/data_seminar_5.png b/assets/210825_data_seminar/data_seminar_5.png new file mode 100644 index 00000000000..0cda943e75e Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_5.png differ diff --git a/assets/210825_data_seminar/data_seminar_6.png b/assets/210825_data_seminar/data_seminar_6.png new file mode 100644 index 00000000000..2be181fb9c5 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_6.png differ diff --git a/assets/210825_data_seminar/data_seminar_7.png b/assets/210825_data_seminar/data_seminar_7.png new file mode 100644 index 00000000000..b006f44983f Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_7.png differ diff --git a/assets/210825_data_seminar/data_seminar_8.png b/assets/210825_data_seminar/data_seminar_8.png new file mode 100644 index 00000000000..69e208158da Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_8.png differ diff --git a/assets/210825_data_seminar/data_seminar_9.png b/assets/210825_data_seminar/data_seminar_9.png new file mode 100644 index 00000000000..3a04589f1e8 Binary files /dev/null and b/assets/210825_data_seminar/data_seminar_9.png differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.39.28.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.39.28.png" new file mode 100644 index 00000000000..93114f5bb36 Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.39.28.png" differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.40.43.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.40.43.png" new file mode 100644 index 00000000000..f4c3c4a4c6b Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 7.40.43.png" differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.21.46.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.21.46.png" new file mode 100644 index 00000000000..420aeb60b42 Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.21.46.png" differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.32.52.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.32.52.png" new file mode 100644 index 00000000000..4102dae4d8c Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.32.52.png" differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.37.47.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.37.47.png" new file mode 100644 index 00000000000..0fadf70cd3a Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.37.47.png" differ diff --git "a/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.42.25.png" "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.42.25.png" new file mode 100644 index 00000000000..27d9bb99326 Binary files /dev/null and "b/assets/210825_data_seminar/\354\212\244\355\201\254\353\246\260\354\203\267 2021-08-25 \354\230\244\355\233\204 9.42.25.png" differ diff --git a/assets/DL/word2vec/word2vec_OHE.png b/assets/DL/word2vec/word2vec_OHE.png new file mode 100644 index 00000000000..01702b34a28 Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_10.png b/assets/DL/word2vec/word2vec_OHE_10.png new file mode 100644 index 00000000000..7c9553498fb Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_10.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_2.png b/assets/DL/word2vec/word2vec_OHE_2.png new file mode 100644 index 00000000000..94aede6dcbc Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_2.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_3.png b/assets/DL/word2vec/word2vec_OHE_3.png new file mode 100644 index 00000000000..3d19d04e55f Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_3.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_4.png b/assets/DL/word2vec/word2vec_OHE_4.png new file mode 100644 index 00000000000..a03b9feb7ad Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_4.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_5.png b/assets/DL/word2vec/word2vec_OHE_5.png new file mode 100644 index 00000000000..735be2fe095 Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_5.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_6.png b/assets/DL/word2vec/word2vec_OHE_6.png new file mode 100644 index 00000000000..9f33e69e037 Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_6.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_7.png b/assets/DL/word2vec/word2vec_OHE_7.png new file mode 100644 index 00000000000..c5fca0a6281 Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_7.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_8.png b/assets/DL/word2vec/word2vec_OHE_8.png new file mode 100644 index 00000000000..c7e60eb536f Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_8.png differ diff --git a/assets/DL/word2vec/word2vec_OHE_9.png b/assets/DL/word2vec/word2vec_OHE_9.png new file mode 100644 index 00000000000..4e9508b3d7e Binary files /dev/null and b/assets/DL/word2vec/word2vec_OHE_9.png differ diff --git a/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_1.png b/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_1.png new file mode 100644 index 00000000000..bae961de90c Binary files /dev/null and b/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_1.png differ diff --git a/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_2.png b/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_2.png new file mode 100644 index 00000000000..32beefd77d2 Binary files /dev/null and b/assets/DataAnalysis_Marketing/acquistion_source/acquistion_source_2.png differ diff --git a/assets/DataAnalysis_Marketing/data_analysis_process/data_analysis_process_1.png b/assets/DataAnalysis_Marketing/data_analysis_process/data_analysis_process_1.png new file mode 100644 index 00000000000..19d848655eb Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_analysis_process/data_analysis_process_1.png differ diff --git a/assets/DataAnalysis_Marketing/data_literacy/data_literacy_1.png b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_1.png new file mode 100644 index 00000000000..b6b02520c19 Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_1.png differ diff --git a/assets/DataAnalysis_Marketing/data_literacy/data_literacy_2.png b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_2.png new file mode 100644 index 00000000000..c3765487efb Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_2.png differ diff --git a/assets/DataAnalysis_Marketing/data_literacy/data_literacy_3.png b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_3.png new file mode 100644 index 00000000000..d4878ff622a Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_3.png differ diff --git a/assets/DataAnalysis_Marketing/data_literacy/data_literacy_4.png b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_4.png new file mode 100644 index 00000000000..67584d1f458 Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_4.png differ diff --git a/assets/DataAnalysis_Marketing/data_literacy/data_literacy_5.png b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_5.png new file mode 100644 index 00000000000..d9ced21a8e9 Binary files /dev/null and b/assets/DataAnalysis_Marketing/data_literacy/data_literacy_5.png differ diff --git a/assets/DataAnalysis_Marketing/push_marketing/push_mkt_1.png b/assets/DataAnalysis_Marketing/push_marketing/push_mkt_1.png new file mode 100644 index 00000000000..7feaf66fab8 Binary files /dev/null and b/assets/DataAnalysis_Marketing/push_marketing/push_mkt_1.png differ diff --git a/assets/DataAnalysis_Marketing/push_marketing/push_mkt_2.png b/assets/DataAnalysis_Marketing/push_marketing/push_mkt_2.png new file mode 100644 index 00000000000..e22574bc601 Binary files /dev/null and b/assets/DataAnalysis_Marketing/push_marketing/push_mkt_2.png differ diff --git a/assets/DataAnalysis_Marketing/report_1.png b/assets/DataAnalysis_Marketing/report_1.png new file mode 100644 index 00000000000..08db8e753d8 Binary files /dev/null and b/assets/DataAnalysis_Marketing/report_1.png differ diff --git a/assets/Deep_CF.png b/assets/Deep_CF.png new file mode 100644 index 00000000000..632c7550f64 Binary files /dev/null and b/assets/Deep_CF.png differ diff --git a/assets/Linux_Env/docker_setup/docker_setup_01.png b/assets/Linux_Env/docker_setup/docker_setup_01.png new file mode 100644 index 00000000000..8077cd6a00d Binary files /dev/null and b/assets/Linux_Env/docker_setup/docker_setup_01.png differ diff --git a/assets/Linux_Env/docker_setup/docker_setup_02.png b/assets/Linux_Env/docker_setup/docker_setup_02.png new file mode 100644 index 00000000000..77c5a84826e Binary files /dev/null and b/assets/Linux_Env/docker_setup/docker_setup_02.png differ diff --git a/assets/Linux_Env/file_permission.png b/assets/Linux_Env/file_permission.png new file mode 100644 index 00000000000..d756a58ef55 Binary files /dev/null and b/assets/Linux_Env/file_permission.png differ diff --git a/assets/Linux_Env/linux_file_permission_2.png b/assets/Linux_Env/linux_file_permission_2.png new file mode 100644 index 00000000000..e6e2dbadb69 Binary files /dev/null and b/assets/Linux_Env/linux_file_permission_2.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_1.png b/assets/ML/acf_pacf/acf_pacf_1.png new file mode 100644 index 00000000000..ed8d71b7d3b Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_1.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_2.png b/assets/ML/acf_pacf/acf_pacf_2.png new file mode 100644 index 00000000000..951b50a7314 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_2.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_3.png b/assets/ML/acf_pacf/acf_pacf_3.png new file mode 100644 index 00000000000..7856307fba9 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_3.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_4.png b/assets/ML/acf_pacf/acf_pacf_4.png new file mode 100644 index 00000000000..8fc31ad274a Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_4.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_acf_int.png b/assets/ML/acf_pacf/acf_pacf_acf_int.png new file mode 100644 index 00000000000..cd7daaf8523 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_acf_int.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_acf_int1.png b/assets/ML/acf_pacf/acf_pacf_acf_int1.png new file mode 100644 index 00000000000..d5d8c71c0f7 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_acf_int1.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_diff1.png b/assets/ML/acf_pacf/acf_pacf_diff1.png new file mode 100644 index 00000000000..da637029b41 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_diff1.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_diff2.png b/assets/ML/acf_pacf/acf_pacf_diff2.png new file mode 100644 index 00000000000..4b3ee86cf3e Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_diff2.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_diff3.png b/assets/ML/acf_pacf/acf_pacf_diff3.png new file mode 100644 index 00000000000..a3a8fde8a50 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_diff3.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_pacf_int.png b/assets/ML/acf_pacf/acf_pacf_pacf_int.png new file mode 100644 index 00000000000..c9f0f4e30c3 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_pacf_int.png differ diff --git a/assets/ML/acf_pacf/acf_pacf_pacf_int2.png b/assets/ML/acf_pacf/acf_pacf_pacf_int2.png new file mode 100644 index 00000000000..9952047de60 Binary files /dev/null and b/assets/ML/acf_pacf/acf_pacf_pacf_int2.png differ diff --git a/assets/ML/recommend/ContentsBased.png b/assets/ML/recommend/ContentsBased.png new file mode 100644 index 00000000000..fb2920a4890 Binary files /dev/null and b/assets/ML/recommend/ContentsBased.png differ diff --git a/assets/ML/recommend/MF.png b/assets/ML/recommend/MF.png new file mode 100644 index 00000000000..8edda54c01c Binary files /dev/null and b/assets/ML/recommend/MF.png differ diff --git a/assets/ML/recommend/MF_0.png b/assets/ML/recommend/MF_0.png new file mode 100644 index 00000000000..bdf780a14a2 Binary files /dev/null and b/assets/ML/recommend/MF_0.png differ diff --git a/assets/ML/recommend/pearson.png b/assets/ML/recommend/pearson.png new file mode 100644 index 00000000000..980f148759c Binary files /dev/null and b/assets/ML/recommend/pearson.png differ diff --git a/assets/ML/recommend/rec_3_mf_1.png b/assets/ML/recommend/rec_3_mf_1.png new file mode 100644 index 00000000000..5d846fc580d Binary files /dev/null and b/assets/ML/recommend/rec_3_mf_1.png differ diff --git a/assets/ML/recommend/rec_3_mf_2.png b/assets/ML/recommend/rec_3_mf_2.png new file mode 100644 index 00000000000..86f27b712ab Binary files /dev/null and b/assets/ML/recommend/rec_3_mf_2.png differ diff --git a/assets/ML/recommend/rec_3_mf_3.png b/assets/ML/recommend/rec_3_mf_3.png new file mode 100644 index 00000000000..b2e5f95b7be Binary files /dev/null and b/assets/ML/recommend/rec_3_mf_3.png differ diff --git a/assets/ML/recommend/rec_3_mf_4.png b/assets/ML/recommend/rec_3_mf_4.png new file mode 100644 index 00000000000..660a7567a9d Binary files /dev/null and b/assets/ML/recommend/rec_3_mf_4.png differ diff --git a/assets/ML/recommend/rec_3_mf_5.png b/assets/ML/recommend/rec_3_mf_5.png new file mode 100644 index 00000000000..a1d00dc9527 Binary files /dev/null and b/assets/ML/recommend/rec_3_mf_5.png differ diff --git a/assets/ML/recommend/svd.png b/assets/ML/recommend/svd.png new file mode 100644 index 00000000000..b0e057a4d0e Binary files /dev/null and b/assets/ML/recommend/svd.png differ diff --git a/assets/ML/recommend/svd_1.png b/assets/ML/recommend/svd_1.png new file mode 100644 index 00000000000..ab49b03f936 Binary files /dev/null and b/assets/ML/recommend/svd_1.png differ diff --git a/assets/ML/recommend/svd_2.png b/assets/ML/recommend/svd_2.png new file mode 100644 index 00000000000..2aa84f996be Binary files /dev/null and b/assets/ML/recommend/svd_2.png differ diff --git a/assets/ML/recommend/svd_3.png b/assets/ML/recommend/svd_3.png new file mode 100644 index 00000000000..a807ff0c1af Binary files /dev/null and b/assets/ML/recommend/svd_3.png differ diff --git a/assets/RNN_process.png b/assets/RNN_process.png new file mode 100644 index 00000000000..631834f2c3d Binary files /dev/null and b/assets/RNN_process.png differ diff --git a/assets/als_title_image.png b/assets/als_title_image.png new file mode 100644 index 00000000000..ae94dba109b Binary files /dev/null and b/assets/als_title_image.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_1.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_1.png new file mode 100644 index 00000000000..345125b1fb2 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_1.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_2.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_2.png new file mode 100644 index 00000000000..9939e484ab3 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_2.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_3.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_3.png new file mode 100644 index 00000000000..0d53ec3057c Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_3.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_4.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_4.png new file mode 100644 index 00000000000..46d817e01f7 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_4.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_5.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_5.png new file mode 100644 index 00000000000..9572b9b93e7 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_5.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_6.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_6.png new file mode 100644 index 00000000000..8fed8b8b12b Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_6.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_7.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_7.png new file mode 100644 index 00000000000..1fd971b9424 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_7.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_8.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_8.png new file mode 100644 index 00000000000..ad6426b1889 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_8.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_1.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_1.png new file mode 100644 index 00000000000..c980f0c7831 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_1.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_2.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_2.png new file mode 100644 index 00000000000..67a59059df2 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_2.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_3.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_3.png new file mode 100644 index 00000000000..ac518d1d5fa Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_3.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_4.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_4.png new file mode 100644 index 00000000000..d259d31f639 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_4.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_5.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_5.png new file mode 100644 index 00000000000..e26952bbcb0 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_5.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_6.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_6.png new file mode 100644 index 00000000000..7ae59095187 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_b_6.png differ diff --git a/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_check.png b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_check.png new file mode 100644 index 00000000000..ff58ab1b5f3 Binary files /dev/null and b/assets/cloud/aws/upload_file_to_s3/upload_file_to_s3_check.png differ diff --git a/assets/cloud/cloud_1.png b/assets/cloud/cloud_1.png new file mode 100644 index 00000000000..d6e99df8235 Binary files /dev/null and b/assets/cloud/cloud_1.png differ diff --git a/assets/cloud/cloud_2.png b/assets/cloud/cloud_2.png new file mode 100644 index 00000000000..65016dff58d Binary files /dev/null and b/assets/cloud/cloud_2.png differ diff --git a/assets/csr_matrix_indptr.png b/assets/csr_matrix_indptr.png new file mode 100644 index 00000000000..865123fab00 Binary files /dev/null and b/assets/csr_matrix_indptr.png differ diff --git a/assets/df_sample_1.png b/assets/df_sample_1.png new file mode 100644 index 00000000000..f4155ca8739 Binary files /dev/null and b/assets/df_sample_1.png differ diff --git a/assets/df_sample_2.png b/assets/df_sample_2.png new file mode 100644 index 00000000000..5319e455e17 Binary files /dev/null and b/assets/df_sample_2.png differ diff --git a/assets/etc/error/pylance/pylance_error_1.png b/assets/etc/error/pylance/pylance_error_1.png new file mode 100644 index 00000000000..bb92954c23b Binary files /dev/null and b/assets/etc/error/pylance/pylance_error_1.png differ diff --git a/assets/etc/error/pylance/pylance_error_2.png b/assets/etc/error/pylance/pylance_error_2.png new file mode 100644 index 00000000000..bcadfd06a3d Binary files /dev/null and b/assets/etc/error/pylance/pylance_error_2.png differ diff --git a/assets/fonts/RIDIBatang.otf b/assets/fonts/RIDIBatang.otf new file mode 100644 index 00000000000..a213e49104c Binary files /dev/null and b/assets/fonts/RIDIBatang.otf differ diff --git a/assets/git_study/git_branch.png b/assets/git_study/git_branch.png new file mode 100644 index 00000000000..616f445d2ce Binary files /dev/null and b/assets/git_study/git_branch.png differ diff --git a/assets/git_study/git_collaboration_1.png b/assets/git_study/git_collaboration_1.png new file mode 100644 index 00000000000..74ecf6a0848 Binary files /dev/null and b/assets/git_study/git_collaboration_1.png differ diff --git a/assets/gtm/gtm_1_1.png b/assets/gtm/gtm_1_1.png new file mode 100644 index 00000000000..1a9984cb3d1 Binary files /dev/null and b/assets/gtm/gtm_1_1.png differ diff --git a/assets/gtm/gtm_1_2.png b/assets/gtm/gtm_1_2.png new file mode 100644 index 00000000000..911c83a3b87 Binary files /dev/null and b/assets/gtm/gtm_1_2.png differ diff --git a/assets/gtm/gtm_1_3.png b/assets/gtm/gtm_1_3.png new file mode 100644 index 00000000000..ae5ea2d787a Binary files /dev/null and b/assets/gtm/gtm_1_3.png differ diff --git a/assets/gtm/gtm_2_1.png b/assets/gtm/gtm_2_1.png new file mode 100644 index 00000000000..4baabed7d4e Binary files /dev/null and b/assets/gtm/gtm_2_1.png differ diff --git a/assets/gtm/gtm_2_2.png b/assets/gtm/gtm_2_2.png new file mode 100644 index 00000000000..e23feb8e4c8 Binary files /dev/null and b/assets/gtm/gtm_2_2.png differ diff --git a/assets/gtm/gtm_2_3.png b/assets/gtm/gtm_2_3.png new file mode 100644 index 00000000000..9a020112abc Binary files /dev/null and b/assets/gtm/gtm_2_3.png differ diff --git a/assets/gtm/gtm_2_4.png b/assets/gtm/gtm_2_4.png new file mode 100644 index 00000000000..cd3982e5f47 Binary files /dev/null and b/assets/gtm/gtm_2_4.png differ diff --git a/assets/gtm/gtm_3_1.png b/assets/gtm/gtm_3_1.png new file mode 100644 index 00000000000..42bac78f73d Binary files /dev/null and b/assets/gtm/gtm_3_1.png differ diff --git a/assets/prep/221030_transpose_dataframe/transpose_wide_long_1.png b/assets/prep/221030_transpose_dataframe/transpose_wide_long_1.png new file mode 100644 index 00000000000..00506bed4b8 Binary files /dev/null and b/assets/prep/221030_transpose_dataframe/transpose_wide_long_1.png differ diff --git a/assets/prep/221030_transpose_dataframe/transpose_wide_long_2.png b/assets/prep/221030_transpose_dataframe/transpose_wide_long_2.png new file mode 100644 index 00000000000..481c9990961 Binary files /dev/null and b/assets/prep/221030_transpose_dataframe/transpose_wide_long_2.png differ diff --git a/assets/prep/221030_transpose_dataframe/transpose_wide_long_3.png b/assets/prep/221030_transpose_dataframe/transpose_wide_long_3.png new file mode 100644 index 00000000000..4a65310acba Binary files /dev/null and b/assets/prep/221030_transpose_dataframe/transpose_wide_long_3.png differ diff --git a/assets/scaling_1.png b/assets/scaling_1.png new file mode 100644 index 00000000000..ae17d9f7c0b Binary files /dev/null and b/assets/scaling_1.png differ diff --git a/assets/statistics/220126_confidence_error/confidence_error_1.png b/assets/statistics/220126_confidence_error/confidence_error_1.png new file mode 100644 index 00000000000..0daf16461c0 Binary files /dev/null and b/assets/statistics/220126_confidence_error/confidence_error_1.png differ diff --git a/assets/statistics/220126_confidence_error/confidence_error_2.png b/assets/statistics/220126_confidence_error/confidence_error_2.png new file mode 100644 index 00000000000..31594c27d75 Binary files /dev/null and b/assets/statistics/220126_confidence_error/confidence_error_2.png differ diff --git a/assets/statistics/220126_confidence_error/confidence_error_3.png b/assets/statistics/220126_confidence_error/confidence_error_3.png new file mode 100644 index 00000000000..54296272596 Binary files /dev/null and b/assets/statistics/220126_confidence_error/confidence_error_3.png differ diff --git a/assets/statistics/220126_confidence_error/confidence_error_4.png b/assets/statistics/220126_confidence_error/confidence_error_4.png new file mode 100644 index 00000000000..6386d4cbaf7 Binary files /dev/null and b/assets/statistics/220126_confidence_error/confidence_error_4.png differ diff --git a/assets/statistics/220126_confidence_error/confidence_error_5.png b/assets/statistics/220126_confidence_error/confidence_error_5.png new file mode 100644 index 00000000000..29def4b1dfd Binary files /dev/null and b/assets/statistics/220126_confidence_error/confidence_error_5.png differ diff --git a/assets/statistics/relation_causality/corr_causality_1.png b/assets/statistics/relation_causality/corr_causality_1.png new file mode 100644 index 00000000000..df5df708519 Binary files /dev/null and b/assets/statistics/relation_causality/corr_causality_1.png differ diff --git a/assets/tableau/tableau_study_preprocess_2-1.png b/assets/tableau/tableau_study_preprocess_2-1.png new file mode 100644 index 00000000000..ada95c2f1e3 Binary files /dev/null and b/assets/tableau/tableau_study_preprocess_2-1.png differ diff --git a/assets/tableau/tableau_study_preprocess_2-2.png b/assets/tableau/tableau_study_preprocess_2-2.png new file mode 100644 index 00000000000..1747aa53f2a Binary files /dev/null and b/assets/tableau/tableau_study_preprocess_2-2.png differ diff --git a/assets/tableau/tableau_study_preprocess_2-3.png b/assets/tableau/tableau_study_preprocess_2-3.png new file mode 100644 index 00000000000..d51f5c3beb8 Binary files /dev/null and b/assets/tableau/tableau_study_preprocess_2-3.png differ diff --git a/assets/tableau/tableau_study_preprocess_3.png b/assets/tableau/tableau_study_preprocess_3.png new file mode 100644 index 00000000000..e090916d915 Binary files /dev/null and b/assets/tableau/tableau_study_preprocess_3.png differ diff --git a/assets/tableau/tableau_study_training_1_1.png b/assets/tableau/tableau_study_training_1_1.png new file mode 100644 index 00000000000..4a0ab4e9a29 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_1.png differ diff --git a/assets/tableau/tableau_study_training_1_2-1.png b/assets/tableau/tableau_study_training_1_2-1.png new file mode 100644 index 00000000000..caa3eb9fb32 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_2-1.png differ diff --git a/assets/tableau/tableau_study_training_1_2-2.png b/assets/tableau/tableau_study_training_1_2-2.png new file mode 100644 index 00000000000..5217cfec415 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_2-2.png differ diff --git a/assets/tableau/tableau_study_training_1_3-1.png b/assets/tableau/tableau_study_training_1_3-1.png new file mode 100644 index 00000000000..34e296b6484 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_3-1.png differ diff --git a/assets/tableau/tableau_study_training_1_3-2.png b/assets/tableau/tableau_study_training_1_3-2.png new file mode 100644 index 00000000000..2d4b0821b95 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_3-2.png differ diff --git a/assets/tableau/tableau_study_training_1_4-1.png b/assets/tableau/tableau_study_training_1_4-1.png new file mode 100644 index 00000000000..f0b8066d986 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_4-1.png differ diff --git a/assets/tableau/tableau_study_training_1_4-2.png b/assets/tableau/tableau_study_training_1_4-2.png new file mode 100644 index 00000000000..41aea55e559 Binary files /dev/null and b/assets/tableau/tableau_study_training_1_4-2.png differ diff --git a/assets/tableau/tableau_study_training_1_4-3.png b/assets/tableau/tableau_study_training_1_4-3.png new file mode 100644 index 00000000000..5f0021899dd Binary files /dev/null and b/assets/tableau/tableau_study_training_1_4-3.png differ diff --git a/assets/youtube_Ranking_architecture.png b/assets/youtube_Ranking_architecture.png new file mode 100644 index 00000000000..ba885d66382 Binary files /dev/null and b/assets/youtube_Ranking_architecture.png differ diff --git a/atom.xml b/atom.xml index 15eed6caff2..e7622dfd7cb 100644 --- a/atom.xml +++ b/atom.xml @@ -3,7 +3,7 @@ layout: null --- - + {{ site.title }} diff --git a/cate_Archive.md b/cate_Archive.md new file mode 100644 index 00000000000..c7b17dbcb15 --- /dev/null +++ b/cate_Archive.md @@ -0,0 +1,9 @@ +--- +layout: page +title: Archive +--- +{% for post in site.posts %} + {% if post.category == 'Archive' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/cate_stock.md b/cate_stock.md new file mode 100644 index 00000000000..70c66c16843 --- /dev/null +++ b/cate_stock.md @@ -0,0 +1,9 @@ + diff --git a/category.md b/category.md new file mode 100644 index 00000000000..63847bcf4df --- /dev/null +++ b/category.md @@ -0,0 +1,10 @@ + diff --git a/category/cate_01_Statistics.md b/category/cate_01_Statistics.md new file mode 100644 index 00000000000..e99da56fe0d --- /dev/null +++ b/category/cate_01_Statistics.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 01_Statistics +--- +{% for post in site.posts %} + {% if post.category == 'Statistics' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_02_ML.md b/category/cate_02_ML.md new file mode 100644 index 00000000000..fb7d9736ff5 --- /dev/null +++ b/category/cate_02_ML.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 02_ML +--- +{% for post in site.posts %} + {% if post.category == 'ML' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_03_DL.md b/category/cate_03_DL.md new file mode 100644 index 00000000000..6a522d167f5 --- /dev/null +++ b/category/cate_03_DL.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 03_DL +--- +{% for post in site.posts %} + {% if post.category == 'DL' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_04_Preprocess.md b/category/cate_04_Preprocess.md new file mode 100644 index 00000000000..52d2aec0b23 --- /dev/null +++ b/category/cate_04_Preprocess.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 04_Preprocess +--- +{% for post in site.posts %} + {% if post.category == 'Preprocess' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_05_Vis.md b/category/cate_05_Vis.md new file mode 100644 index 00000000000..ee2ff6eb2c8 --- /dev/null +++ b/category/cate_05_Vis.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 05_Vis +--- +{% for post in site.posts %} + {% if post.category == 'Vis' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_06_Evaluation.md b/category/cate_06_Evaluation.md new file mode 100644 index 00000000000..b5164e7cdfe --- /dev/null +++ b/category/cate_06_Evaluation.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 06_Evaluation +--- +{% for post in site.posts %} + {% if post.category == 'Evaluation' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_08_DataAnalysis_Marketing.md b/category/cate_08_DataAnalysis_Marketing.md new file mode 100644 index 00000000000..15f1b38435c --- /dev/null +++ b/category/cate_08_DataAnalysis_Marketing.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 08_DataAnalysis_Marketing +--- +{% for post in site.posts %} + {% if post.category == 'DataAnalysis_Marketing' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_09_Crawler.md b/category/cate_09_Crawler.md new file mode 100644 index 00000000000..32bcd3ad789 --- /dev/null +++ b/category/cate_09_Crawler.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 09_Crawler +--- +{% for post in site.posts %} + {% if post.category == 'Crawler' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_10_Git.md b/category/cate_10_Git.md new file mode 100644 index 00000000000..711e903495e --- /dev/null +++ b/category/cate_10_Git.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 10_Git +--- +{% for post in site.posts %} + {% if post.category == 'Git' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_11_Linux_Env.md b/category/cate_11_Linux_Env.md new file mode 100644 index 00000000000..076e9dcdb5f --- /dev/null +++ b/category/cate_11_Linux_Env.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 11_Linux_Env +--- +{% for post in site.posts %} + {% if post.category == 'Linux_Env' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_12_GA_GTM.md b/category/cate_12_GA_GTM.md new file mode 100644 index 00000000000..006c5b30c03 --- /dev/null +++ b/category/cate_12_GA_GTM.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 12_GA_GTM +--- +{% for post in site.posts %} + {% if post.category == 'GA_GTM' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_13_Tableau.md b/category/cate_13_Tableau.md new file mode 100644 index 00000000000..df0864163f1 --- /dev/null +++ b/category/cate_13_Tableau.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 13_Tableau +--- +{% for post in site.posts %} + {% if post.category == 'Tableau' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_14_SQL.md b/category/cate_14_SQL.md new file mode 100644 index 00000000000..bf151c9bcf5 --- /dev/null +++ b/category/cate_14_SQL.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 14_SQL +--- +{% for post in site.posts %} + {% if post.category == 'SQL' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_15_cloud.md b/category/cate_15_cloud.md new file mode 100644 index 00000000000..ce6b854468c --- /dev/null +++ b/category/cate_15_cloud.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 15_Cloud +--- +{% for post in site.posts %} + {% if post.category == 'cloud' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_999_ETC.md b/category/cate_999_ETC.md new file mode 100644 index 00000000000..0e67a39f9e1 --- /dev/null +++ b/category/cate_999_ETC.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 999_ETC +--- +{% for post in site.posts %} + {% if post.category == 'ETC' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/category/cate_99_seminar.md b/category/cate_99_seminar.md new file mode 100644 index 00000000000..242b761802a --- /dev/null +++ b/category/cate_99_seminar.md @@ -0,0 +1,9 @@ +--- +layout: page +title: 099_Seminar +--- +{% for post in site.posts %} + {% if post.category == 'Seminar' %} + * {{ post.date | date_to_string }} » [ {{ post.title }} ]({{ post.url }}) + {% endif %} +{% endfor %} diff --git a/prj_code/recommend/ALS Implementation.ipynb b/prj_code/recommend/ALS Implementation.ipynb new file mode 100644 index 00000000000..ec34c855455 --- /dev/null +++ b/prj_code/recommend/ALS Implementation.ipynb @@ -0,0 +1,738 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ALS Implementation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.core.interactiveshell import InteractiveShell\n", + "InteractiveShell.ast_node_interactivity = \"all\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Initialize parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- r_lambda: normalization parameter\n", + "- alpha: confidence level\n", + "- nf: dimension of latent vector of each user and item\n", + "- initilzed values(40, 200, 40) are the best parameters from the paper" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "r_lambda = 40\n", + "nf = 200\n", + "alpha = 40" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. rating matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10, 11)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "\n", + "# sample rating matrix\n", + "R = np.array([[0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0],\n", + " [0, 3, 4, 0, 3, 0, 0, 2, 2, 0, 0],\n", + " [0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0],\n", + " [0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5],\n", + " [0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4],\n", + " [0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0],\n", + " [0, 0, 0, 3, 0, 0, 0, 0, 4, 5, 0]])\n", + "R.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Initalize user and item latent factor matrix\n", + " : 아주 작은 랜덤한 값들로 행렬의 값을 초기화 시킴 -> 이를 통해 한쪽 \n", + "정보를 상수로 고정한 상태에서 반대편 matrix를 학습\n", + " - nu : number of users (10)\n", + " - ni : number of items (11)\n", + " - nf : dimension of latent vector" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([[0.00152801, 0.00757564, 0.00923784, ..., 0.00490042, 0.00697526,\n", + " 0.00954676],\n", + " [0.0091762 , 0.00020842, 0.00542215, ..., 0.00064578, 0.00903261,\n", + " 0.00724798],\n", + " [0.00148628, 0.00628547, 0.00604668, ..., 0.00497305, 0.00232862,\n", + " 0.00901012],\n", + " ...,\n", + " [0.00235099, 0.00393322, 0.00918248, ..., 0.00974353, 0.00444581,\n", + " 0.00186488],\n", + " [0.00547913, 0.00562956, 0.00104005, ..., 0.00659107, 0.00523891,\n", + " 0.00125358],\n", + " [0.00193838, 0.00580671, 0.00466999, ..., 0.00584544, 0.00520098,\n", + " 0.00723732]]),\n", + " array([[0.00942033, 0.00838059, 0.00283322, ..., 0.00669 , 0.00111067,\n", + " 0.00387789],\n", + " [0.00243604, 0.00722863, 0.00577154, ..., 0.00728208, 0.00484407,\n", + " 0.00569207],\n", + " [0.00219446, 0.00927742, 0.00120476, ..., 0.00207732, 0.00900426,\n", + " 0.00639849],\n", + " ...,\n", + " [0.00116326, 0.00210305, 0.00749175, ..., 0.0019529 , 0.00388187,\n", + " 0.00557575],\n", + " [0.00464582, 0.00564343, 0.00940545, ..., 0.00574422, 0.00814628,\n", + " 0.00392712],\n", + " [0.00887629, 0.00436732, 0.0051157 , ..., 0.00296383, 0.00787589,\n", + " 0.00424186]]))" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nu = R.shape[0]\n", + "ni = R.shape[1]\n", + "\n", + "# initialize X and Y with very small values\n", + "X = np.random.rand(nu, nf) * 0.01 # 10x200\n", + "Y = np.random.rand(ni, nf) * 0.01 # 11x200\n", + "\n", + "X, Y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Initialize Binary Rating Matrix\n", + "### (선호도 행렬 P 설정)\n", + " : 주어진 학습용 평점 테이블을 0과1로 이뤄진 binary rating matrix P로 변경
\n", + " - Convert original rating matrix R into P\n", + " - Pui = 1 if Rui > 0 \n", + " - Pui = 0 if Rui = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0],\n", + " [0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0],\n", + " [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],\n", + " [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],\n", + " [0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "P = np.copy(R)\n", + "P[P > 0] = 1\n", + "P" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Initialize Confidence Matrix \n", + "### (신로도 행렬 C 설정)\n", + " : 주어진 학습 평점 테이블에 confidence level을 적용한 C행렬 계산\n", + "\n", + " - 신뢰도 행렬을 이횽해 평점이 부재한 테이터도 낮은 신뢰도 하에서 분석에 활용 가능\n", + " \n", + " - Initialize Confidence Matrix C\n", + " - Cui = 1 + alpha * R \n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 1 1 1 161 161 1 1 1 1 1 1]\n", + " [ 1 1 1 1 1 1 1 1 1 1 41]\n", + " [ 1 1 1 1 1 1 1 41 1 161 1]\n", + " [ 1 121 161 1 121 1 1 81 81 1 1]\n", + " [ 1 201 201 1 1 1 1 1 1 1 1]\n", + " [ 1 1 1 1 1 1 201 1 1 201 1]\n", + " [ 1 1 161 1 1 1 1 1 1 1 201]\n", + " [ 1 1 1 1 1 161 1 1 1 1 161]\n", + " [ 1 1 1 1 1 1 201 1 1 201 1]\n", + " [ 1 1 1 121 1 1 1 1 161 201 1]]\n" + ] + }, + { + "data": { + "text/plain": [ + "(10, 11)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "C = 1 +alpha * R\n", + "print(C)\n", + "C.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]])" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "i = 0\n", + "Ci = np.diag(C[:, i])\n", + "Ci" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Loss Function 설정\n", + " - C: confidence matrix\n", + " - P: binary rating matrix\n", + " - X: user latent matrix\n", + " - Y: item latent matrix\n", + " - r_lambda: regularization lambda\n", + " - xTy: predict matrix\n", + " - Total_loss = (confidence_level * predict loss) + regularization loss" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def loss_function(C, P, xTy, X, Y, r_lambda) :\n", + " predict_error = np.square(P-xTy) # (관측치 - 예측치)^2\n", + " confidence_error = np.sum(C*predict_error) # 오차값이 크더라도, 신뢰도가 낮다면 적게 반영하며, 오차값이 작더라도 신뢰도가 크다면 오차를 크게 반영\n", + " regularization = r_lambda * (np.sum(np.square(X)) + np.sum(np.square(Y)))\n", + " total_loss = confidence_error + regularization\n", + " return np.sum(predict_error), confidence_error, regularization, total_loss" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Optimization Function for user and Item\n", + "- X[u] = (yTCuy + lambda*I)^-1yTCuy\n", + "- Y[i] = (xTCix + lambda*I)^-1xTCix\n", + "- two formula is the same when it changes X to Y and u to i" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def optimize_user(X, Y, C, P, nu, nf, r_lambda) :\n", + " \"\"\"\n", + " optimize user matrix\n", + " \"\"\"\n", + " yT = np.transpose(Y)\n", + " for u in range(nu):\n", + " Cu = np.diag(C[u]) # np.diag : 대각 행렬 C행렬을 순차적으로 곱해주기 위해서\n", + " yT_Cu_y = np.matmul(np.matmul(yT, Cu), Y)\n", + " lI = np.dot(r_lambda, np.identity(nf)) # 정규화\n", + " yT_Cu_pu = np.matmul(np.matmul(yT, Cu), P[u])\n", + " X[u] = np.linalg.solve(yT_Cu_y + lI, yT_Cu_pu)\n", + "\n", + "def optimize_item(X, Y, C, P, ni, nf, r_lambda):\n", + " \"\"\"\n", + " optimize item matrix\n", + " \"\"\"\n", + " xT = np.transpose(X)\n", + " for i in range(ni):\n", + " Ci = np.diag(C[:, i])\n", + " xT_Ci_x = np.matmul(np.matmul(xT, Ci), X)\n", + " lI = np.dot(r_lambda, np.identity(nf))\n", + " xT_Ci_pi = np.matmul(np.matmul(xT, Ci), P[:, i])\n", + " Y[i] = np.linalg.solve(xT_Ci_x + lI, xT_Ci_pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "xT = np.transpose(X)\n", + "for i in range(ni):\n", + " Ci = np.diag(C[:, i])\n", + " xT_Ci_x = np.matmul(np.matmul(xT, Ci), X)\n", + " lI = np.dot(r_lambda, np.identity(nf))\n", + " xT_Ci_pi = np.matmul(np.matmul(xT, Ci), P[:, i])\n", + " Y[i] = np.linalg.solve(xT_Ci_x + lI, xT_Ci_pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(200, 200)" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "(200, 200)" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "(200,)" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "(10,)" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "xT_Ci_x.shape\n", + "lI.shape\n", + "xT_Ci_pi.shape\n", + "P[:, i].shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. Train\n", + " - usually ALS algorithm repeat train steps for 10~15times" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "----------------step 0----------------\n", + "predict error: 22.628862\n", + "confidence error: 3442.769641\n", + "regularization: 19.336987\n", + "total loss: 3462.106628\n", + "----------------step 1----------------\n", + "predict error: 30.957115\n", + "confidence error: 285.638645\n", + "regularization: 639.397642\n", + "total loss: 925.036287\n", + "----------------step 2----------------\n", + "predict error: 34.024191\n", + "confidence error: 137.844707\n", + "regularization: 650.759387\n", + "total loss: 788.604093\n", + "----------------step 3----------------\n", + "predict error: 32.130058\n", + "confidence error: 119.829810\n", + "regularization: 650.760389\n", + "total loss: 770.590198\n", + "----------------step 4----------------\n", + "predict error: 29.562359\n", + "confidence error: 109.343120\n", + "regularization: 653.473816\n", + "total loss: 762.816936\n", + "----------------step 5----------------\n", + "predict error: 27.065492\n", + "confidence error: 102.318145\n", + "regularization: 656.420266\n", + "total loss: 758.738411\n", + "----------------step 6----------------\n", + "predict error: 24.979342\n", + "confidence error: 97.495774\n", + "regularization: 658.869386\n", + "total loss: 756.365160\n", + "----------------step 7----------------\n", + "predict error: 23.385537\n", + "confidence error: 94.218673\n", + "regularization: 660.713441\n", + "total loss: 754.932114\n", + "----------------step 8----------------\n", + "predict error: 22.229139\n", + "confidence error: 92.022439\n", + "regularization: 662.038800\n", + "total loss: 754.061239\n", + "----------------step 9----------------\n", + "predict error: 21.412424\n", + "confidence error: 90.562597\n", + "regularization: 662.969505\n", + "total loss: 753.532103\n", + "----------------step 10----------------\n", + "predict error: 20.842715\n", + "confidence error: 89.594429\n", + "regularization: 663.615173\n", + "total loss: 753.209602\n", + "----------------step 11----------------\n", + "predict error: 20.447335\n", + "confidence error: 88.951612\n", + "regularization: 664.059640\n", + "total loss: 753.011252\n", + "----------------step 12----------------\n", + "predict error: 20.173677\n", + "confidence error: 88.524063\n", + "regularization: 664.363353\n", + "total loss: 752.887416\n", + "----------------step 13----------------\n", + "predict error: 19.984921\n", + "confidence error: 88.239687\n", + "regularization: 664.568851\n", + "total loss: 752.808538\n", + "----------------step 14----------------\n", + "predict error: 19.855567\n", + "confidence error: 88.051269\n", + "regularization: 664.705824\n", + "total loss: 752.757093\n", + "final predict\n", + "[array([[ 0. , 0.72032512, 0.68269947, 0.85762853, 0.83815542,\n", + " 0.10181531, 0.59195313, 0.68814191, 0.81214261, 0.81933355,\n", + " 0.31502819],\n", + " [ 0. , 0.33849742, 0.4203328 , 0.10926002, 0.15903737,\n", + " 0.39295661, -0.03107137, 0.14938506, 0.13520519, 0.03213185,\n", + " 0.48344609],\n", + " [ 0. , 0.45893165, 0.42512237, 0.63134459, 0.58573528,\n", + " 0.03131133, 0.75184842, 0.565898 , 0.62718551, 0.86785963,\n", + " 0.15815588],\n", + " [ 0. , 0.92276577, 0.94220536, 0.89631614, 0.9085991 ,\n", + " 0.36455237, 0.60395343, 0.77779863, 0.87863937, 0.8569369 ,\n", + " 0.63078793],\n", + " [ 0. , 0.84991773, 0.92668688, 0.62297821, 0.67987804,\n", + " 0.53927838, 0.25511659, 0.57283428, 0.62753503, 0.47104537,\n", + " 0.78325062],\n", + " [ 0. , 0.28644591, 0.23428542, 0.54255595, 0.46980037,\n", + " -0.08740135, 0.88181556, 0.51035059, 0.55057874, 0.93890376,\n", + " -0.01495784],\n", + " [ 0. , 0.74545732, 0.87504234, 0.37839909, 0.46102918,\n", + " 0.6893944 , 0.06476064, 0.40754246, 0.41179828, 0.22633798,\n", + " 0.89517999],\n", + " [ 0. , 0.57024678, 0.74254797, 0.09797614, 0.19782909,\n", + " 0.78189794, -0.11997311, 0.206703 , 0.15858969, -0.02985975,\n", + " 0.92881811],\n", + " [ 0. , 0.28644591, 0.23428542, 0.54255595, 0.46980037,\n", + " -0.08740135, 0.88181556, 0.51035059, 0.55057874, 0.93890376,\n", + " -0.01495784],\n", + " [ 0. , 0.68408656, 0.63934804, 0.86949708, 0.83205805,\n", + " 0.06577733, 0.75973607, 0.72386032, 0.83627777, 0.96352715,\n", + " 0.2641367 ]])]\n" + ] + } + ], + "source": [ + "predict_errors = []\n", + "confidence_errors = []\n", + "regularization_list = []\n", + "total_losses = []\n", + "\n", + "for i in range(15):\n", + " if i!=0: \n", + " optimize_user(X, Y, C, P, nu, nf, r_lambda)\n", + " optimize_item(X, Y, C, P, ni, nf, r_lambda)\n", + " predict = np.matmul(X, np.transpose(Y))\n", + " predict_error, confidence_error, regularization, total_loss = loss_function(C, P, predict, X, Y, r_lambda)\n", + " \n", + " predict_errors.append(predict_error)\n", + " confidence_errors.append(confidence_error)\n", + " regularization_list.append(regularization)\n", + " total_losses.append(total_loss)\n", + " \n", + " print('----------------step %d----------------' % i)\n", + " print(\"predict error: %f\" % predict_error)\n", + " print(\"confidence error: %f\" % confidence_error)\n", + " print(\"regularization: %f\" % regularization)\n", + " print(\"total loss: %f\" % total_loss)\n", + " \n", + "predict = np.matmul(X, np.transpose(Y))\n", + "print('final predict')\n", + "print([predict])" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Predict Error')" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Confidence Error')" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Regularization')" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Total Loss')" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib import pyplot as plt\n", + "%matplotlib inline\n", + "\n", + "plt.subplots_adjust(wspace=100.0, hspace=20.0)\n", + "fig = plt.figure()\n", + "fig.set_figheight(10)\n", + "fig.set_figwidth(10)\n", + "predict_error_line = fig.add_subplot(2, 2, 1)\n", + "confidence_error_line = fig.add_subplot(2, 2, 2)\n", + "regularization_error_line = fig.add_subplot(2, 2, 3)\n", + "total_loss_line = fig.add_subplot(2, 2, 4)\n", + "\n", + "predict_error_line.set_title(\"Predict Error\") \n", + "predict_error_line.plot(predict_errors)\n", + "\n", + "confidence_error_line.set_title(\"Confidence Error\")\n", + "confidence_error_line.plot(confidence_errors)\n", + "\n", + "regularization_error_line.set_title(\"Regularization\")\n", + "regularization_error_line.plot(regularization_list)\n", + "\n", + "total_loss_line.set_title(\"Total Loss\")\n", + "total_loss_line.plot(total_losses)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 참조\n", + "[1] https://yeomko.tistory.com/8?category=805638\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/public/css/lanyon.css b/public/css/lanyon.css index b0b42b81b17..5a5f726761a 100644 --- a/public/css/lanyon.css +++ b/public/css/lanyon.css @@ -41,11 +41,21 @@ body { } html { - font-family: "PT Serif", Georgia, "Times New Roman", serif; + /* + font-family: "PT Serif", Georgia, "Times New Roman", serif; # 이전에 사용하던 폰트 + font-family: "PT Sans", Helvetica, Arial, sans-serif; + font-family: 'Nanum Myeongjo', serif; + */ + font-family: 'IBM Plex Sans KR', sans-serif; + font-weight: 300; + /* font-size: 80%; */ } h1, h2, h3, h4, h5, h6 { - font-family: "PT Sans", Helvetica, Arial, sans-serif; + /* font-family: "PT Sans", Helvetica, Arial, sans-serif; + font-family: 'Nanum Myeongjo', serif; + */ + font-family: 'IBM Plex Sans KR', sans-serif; font-weight: 400; color: #313131; letter-spacing: -.025rem; @@ -73,13 +83,13 @@ h1, h2, h3, h4, h5, h6 { */ .container { - max-width: 28rem; + max-width: 48rem; /*38rem;*/ } -@media (min-width: 38em) { +/* @media (min-width: 38em) { .container { max-width: 32rem; } -} +} */ @media (min-width: 56em) { .container { max-width: 38rem; @@ -148,7 +158,11 @@ h1, h2, h3, h4, h5, h6 { width: 14rem; visibility: hidden; overflow-y: auto; + /* font-family: "PT Sans", Helvetica, Arial, sans-serif; + font-family: 'Nanum Myeongjo', serif; + */ + font-family: 'IBM Plex Sans KR', sans-serif; font-size: .875rem; /* 15px */ color: rgba(255,255,255,.6); background-color: #202020; @@ -227,8 +241,8 @@ a.sidebar-nav-item:focus { display: inline-block; width: 32px; height: 32px; - content: ""; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23555' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat; + content: "≡"; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23555' xmlns='https://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat; } .sidebar-toggle:active, @@ -241,7 +255,7 @@ a.sidebar-nav-item:focus { .sidebar-toggle:active:before, #sidebar-checkbox:focus ~ .sidebar-toggle::before, #sidebar-checkbox:checked ~ .sidebar-toggle::before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='https://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat; } @media (min-width: 30.1em) { @@ -363,7 +377,11 @@ a.sidebar-nav-item:focus { overflow: hidden; /* clearfix */ margin-left: -1rem; margin-right: -1rem; + /* font-family: "PT Sans", Helvetica, Arial, sans-serif; + font-family: 'Nanum Myeongjo', serif; + */ + font-family: 'IBM Plex Sans KR', sans-serif; color: #ccc; text-align: center; } diff --git a/public/css/poole.css b/public/css/poole.css index 8ec27e7a844..8d7bdd70b01 100644 --- a/public/css/poole.css +++ b/public/css/poole.css @@ -49,7 +49,7 @@ body { html { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 16px; + font-size: 10px; line-height: 1.5; } @media (min-width: 38em) { diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 2cd56085afa..00000000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon_1.ico b/public/favicon_1.ico new file mode 100644 index 00000000000..957a86f25c7 Binary files /dev/null and b/public/favicon_1.ico differ diff --git a/public/favicon_2.ico b/public/favicon_2.ico new file mode 100644 index 00000000000..edca868fc29 Binary files /dev/null and b/public/favicon_2.ico differ diff --git a/study/WEB_HTML/1.html b/study/WEB_HTML/1.html new file mode 100644 index 00000000000..b06ba8ec532 --- /dev/null +++ b/study/WEB_HTML/1.html @@ -0,0 +1,7 @@ +hello web +

뚱이 is Pig

+

+ 옛날 옛적에 뚱이가 살았드레요. + + 그 뚱이는 돼지더레요. +