SaulLu commited on
Commit
baf9de9
1 Parent(s): ade07a8

add website

Browse files
README.md CHANGED
@@ -3,8 +3,7 @@ title: Test Demo
3
  emoji: 🔥
4
  colorFrom: indigo
5
  colorTo: red
6
- sdk: streamlit
7
- app_file: app.py
8
  pinned: false
9
  ---
10
 
3
  emoji: 🔥
4
  colorFrom: indigo
5
  colorTo: red
6
+ sdk: static
 
7
  pinned: false
8
  ---
9
 
_config.yml ADDED
@@ -0,0 +1 @@
 
1
+ theme: jekyll-theme-cayman
_site/404.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>Your awesome title | Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="Your awesome title" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
11
+ <meta property="og:description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
12
+ <link rel="canonical" href="http://localhost:4000/404.html" />
13
+ <meta property="og:url" content="http://localhost:4000/404.html" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta property="twitter:title" content="Your awesome title" />
17
+ <script type="application/ld+json">
18
+ {"@type":"WebPage","headline":"Your awesome title","url":"http://localhost:4000/404.html","description":"Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.","@context":"https://schema.org"}</script>
19
+ <!-- End Jekyll SEO tag -->
20
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
21
+ <body><header class="site-header" role="banner">
22
+
23
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
24
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
25
+ <label for="nav-trigger">
26
+ <span class="menu-icon">
27
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
28
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
29
+ </svg>
30
+ </span>
31
+ </label>
32
+
33
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
34
+ </nav></div>
35
+ </header>
36
+ <main class="page-content" aria-label="Content">
37
+ <div class="wrapper">
38
+ <style type="text/css" media="screen">
39
+ .container {
40
+ margin: 10px auto;
41
+ max-width: 600px;
42
+ text-align: center;
43
+ }
44
+ h1 {
45
+ margin: 30px 0;
46
+ font-size: 4em;
47
+ line-height: 1;
48
+ letter-spacing: -1px;
49
+ }
50
+ </style>
51
+
52
+ <div class="container">
53
+ <h1>404</h1>
54
+
55
+ <p><strong>Page not found :(</strong></p>
56
+ <p>The requested page could not be found.</p>
57
+ </div>
58
+
59
+ </div>
60
+ </main><footer class="site-footer h-card">
61
+ <data class="u-url" href="/"></data>
62
+
63
+ <div class="wrapper">
64
+
65
+ <h2 class="footer-heading">Your awesome title</h2>
66
+
67
+ <div class="footer-col-wrapper">
68
+ <div class="footer-col footer-col-1">
69
+ <ul class="contact-list">
70
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
71
+ </div>
72
+
73
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
74
+ </div>
75
+
76
+ <div class="footer-col footer-col-3">
77
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
78
+ </div>
79
+ </div>
80
+
81
+ </div>
82
+
83
+ </footer>
84
+ </body>
85
+
86
+ </html>
_site/about/index.html ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>About | Your awesome title</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="About" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
11
+ <meta property="og:description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
12
+ <link rel="canonical" href="http://localhost:4000/about/" />
13
+ <meta property="og:url" content="http://localhost:4000/about/" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta property="twitter:title" content="About" />
17
+ <script type="application/ld+json">
18
+ {"@type":"WebSite","headline":"About","url":"http://localhost:4000/about/","description":"Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.","name":"Your awesome title","@context":"https://schema.org"}</script>
19
+ <!-- End Jekyll SEO tag -->
20
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
21
+ <body><header class="site-header" role="banner">
22
+
23
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
24
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
25
+ <label for="nav-trigger">
26
+ <span class="menu-icon">
27
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
28
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
29
+ </svg>
30
+ </span>
31
+ </label>
32
+
33
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
34
+ </nav></div>
35
+ </header>
36
+ <main class="page-content" aria-label="Content">
37
+ <div class="wrapper">
38
+ <article class="post">
39
+
40
+ <header class="post-header">
41
+ <h1 class="post-title">About</h1>
42
+ </header>
43
+
44
+ <div class="post-content">
45
+ <p>This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at <a href="https://jekyllrb.com/">jekyllrb.com</a></p>
46
+
47
+ <p>You can find the source code for Minima at GitHub:
48
+ <a href="https://github.com/jekyll">jekyll</a> /
49
+ <a href="https://github.com/jekyll/minima">minima</a></p>
50
+
51
+ <p>You can find the source code for Jekyll at GitHub:
52
+ <a href="https://github.com/jekyll">jekyll</a> /
53
+ <a href="https://github.com/jekyll/jekyll">jekyll</a></p>
54
+
55
+
56
+ </div>
57
+
58
+ </article>
59
+
60
+ </div>
61
+ </main><footer class="site-footer h-card">
62
+ <data class="u-url" href="/"></data>
63
+
64
+ <div class="wrapper">
65
+
66
+ <h2 class="footer-heading">Your awesome title</h2>
67
+
68
+ <div class="footer-col-wrapper">
69
+ <div class="footer-col footer-col-1">
70
+ <ul class="contact-list">
71
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
72
+ </div>
73
+
74
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
75
+ </div>
76
+
77
+ <div class="footer-col footer-col-3">
78
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
79
+ </div>
80
+ </div>
81
+
82
+ </div>
83
+
84
+ </footer>
85
+ </body>
86
+
87
+ </html>
_site/assets/main.css ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Reset some basic elements */
2
+ body, h1, h2, h3, h4, h5, h6, p, blockquote, pre, hr, dl, dd, ol, ul, figure { margin: 0; padding: 0; }
3
+
4
+ /** Basic styling */
5
+ body { font: 400 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; color: #111; background-color: #fdfdfd; -webkit-text-size-adjust: 100%; -webkit-font-feature-settings: "kern" 1; -moz-font-feature-settings: "kern" 1; -o-font-feature-settings: "kern" 1; font-feature-settings: "kern" 1; font-kerning: normal; display: flex; min-height: 100vh; flex-direction: column; }
6
+
7
+ /** Set `margin-bottom` to maintain vertical rhythm */
8
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre, ul, ol, dl, figure, .highlight { margin-bottom: 15px; }
9
+
10
+ /** `main` element */
11
+ main { display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */ }
12
+
13
+ /** Images */
14
+ img { max-width: 100%; vertical-align: middle; }
15
+
16
+ /** Figures */
17
+ figure > img { display: block; }
18
+
19
+ figcaption { font-size: 14px; }
20
+
21
+ /** Lists */
22
+ ul, ol { margin-left: 30px; }
23
+
24
+ li > ul, li > ol { margin-bottom: 0; }
25
+
26
+ /** Headings */
27
+ h1, h2, h3, h4, h5, h6 { font-weight: 400; }
28
+
29
+ /** Links */
30
+ a { color: #2a7ae2; text-decoration: none; }
31
+ a:visited { color: #1756a9; }
32
+ a:hover { color: #111; text-decoration: underline; }
33
+ .social-media-list a:hover { text-decoration: none; }
34
+ .social-media-list a:hover .username { text-decoration: underline; }
35
+
36
+ /** Blockquotes */
37
+ blockquote { color: #828282; border-left: 4px solid #e8e8e8; padding-left: 15px; font-size: 18px; letter-spacing: -1px; font-style: italic; }
38
+ blockquote > :last-child { margin-bottom: 0; }
39
+
40
+ /** Code formatting */
41
+ pre, code { font-size: 15px; border: 1px solid #e8e8e8; border-radius: 3px; background-color: #eef; }
42
+
43
+ code { padding: 1px 5px; }
44
+
45
+ pre { padding: 8px 12px; overflow-x: auto; }
46
+ pre > code { border: 0; padding-right: 0; padding-left: 0; }
47
+
48
+ /** Wrapper */
49
+ .wrapper { max-width: -webkit-calc(800px - (30px * 2)); max-width: calc(800px - (30px * 2)); margin-right: auto; margin-left: auto; padding-right: 30px; padding-left: 30px; }
50
+ @media screen and (max-width: 800px) { .wrapper { max-width: -webkit-calc(800px - (30px)); max-width: calc(800px - (30px)); padding-right: 15px; padding-left: 15px; } }
51
+
52
+ /** Clearfix */
53
+ .wrapper:after, .footer-col-wrapper:after { content: ""; display: table; clear: both; }
54
+
55
+ /** Icons */
56
+ .svg-icon { width: 16px; height: 16px; display: inline-block; fill: #828282; padding-right: 5px; vertical-align: text-top; }
57
+
58
+ .social-media-list li + li { padding-top: 5px; }
59
+
60
+ /** Tables */
61
+ table { margin-bottom: 30px; width: 100%; text-align: left; color: #3f3f3f; border-collapse: collapse; border: 1px solid #e8e8e8; }
62
+ table tr:nth-child(even) { background-color: #f7f7f7; }
63
+ table th, table td { padding: 10px 15px; }
64
+ table th { background-color: #f0f0f0; border: 1px solid #dedede; border-bottom-color: #c9c9c9; }
65
+ table td { border: 1px solid #e8e8e8; }
66
+
67
+ /** Site header */
68
+ .site-header { border-top: 5px solid #424242; border-bottom: 1px solid #e8e8e8; min-height: 55.95px; position: relative; }
69
+
70
+ .site-title { font-size: 26px; font-weight: 300; line-height: 54px; letter-spacing: -1px; margin-bottom: 0; float: left; }
71
+ .site-title, .site-title:visited { color: #424242; }
72
+
73
+ .site-nav { float: right; line-height: 54px; }
74
+ .site-nav .nav-trigger { display: none; }
75
+ .site-nav .menu-icon { display: none; }
76
+ .site-nav .page-link { color: #111; line-height: 1.5; }
77
+ .site-nav .page-link:not(:last-child) { margin-right: 20px; }
78
+ @media screen and (max-width: 600px) { .site-nav { position: absolute; top: 9px; right: 15px; background-color: #fdfdfd; border: 1px solid #e8e8e8; border-radius: 5px; text-align: right; }
79
+ .site-nav label[for="nav-trigger"] { display: block; float: right; width: 36px; height: 36px; z-index: 2; cursor: pointer; }
80
+ .site-nav .menu-icon { display: block; float: right; width: 36px; height: 26px; line-height: 0; padding-top: 10px; text-align: center; }
81
+ .site-nav .menu-icon > svg { fill: #424242; }
82
+ .site-nav input ~ .trigger { clear: both; display: none; }
83
+ .site-nav input:checked ~ .trigger { display: block; padding-bottom: 5px; }
84
+ .site-nav .page-link { display: block; padding: 5px 10px; margin-left: 20px; }
85
+ .site-nav .page-link:not(:last-child) { margin-right: 0; } }
86
+
87
+ /** Site footer */
88
+ .site-footer { border-top: 1px solid #e8e8e8; padding: 30px 0; }
89
+
90
+ .footer-heading { font-size: 18px; margin-bottom: 15px; }
91
+
92
+ .contact-list, .social-media-list { list-style: none; margin-left: 0; }
93
+
94
+ .footer-col-wrapper { font-size: 15px; color: #828282; margin-left: -15px; }
95
+
96
+ .footer-col { float: left; margin-bottom: 15px; padding-left: 15px; }
97
+
98
+ .footer-col-1 { width: -webkit-calc(35% - (30px / 2)); width: calc(35% - (30px / 2)); }
99
+
100
+ .footer-col-2 { width: -webkit-calc(20% - (30px / 2)); width: calc(20% - (30px / 2)); }
101
+
102
+ .footer-col-3 { width: -webkit-calc(45% - (30px / 2)); width: calc(45% - (30px / 2)); }
103
+
104
+ @media screen and (max-width: 800px) { .footer-col-1, .footer-col-2 { width: -webkit-calc(50% - (30px / 2)); width: calc(50% - (30px / 2)); }
105
+ .footer-col-3 { width: -webkit-calc(100% - (30px / 2)); width: calc(100% - (30px / 2)); } }
106
+ @media screen and (max-width: 600px) { .footer-col { float: none; width: -webkit-calc(100% - (30px / 2)); width: calc(100% - (30px / 2)); } }
107
+ /** Page content */
108
+ .page-content { padding: 30px 0; flex: 1; }
109
+
110
+ .page-heading { font-size: 32px; }
111
+
112
+ .post-list-heading { font-size: 28px; }
113
+
114
+ .post-list { margin-left: 0; list-style: none; }
115
+ .post-list > li { margin-bottom: 30px; }
116
+
117
+ .post-meta { font-size: 14px; color: #828282; }
118
+
119
+ .post-link { display: block; font-size: 24px; }
120
+
121
+ /** Posts */
122
+ .post-header { margin-bottom: 30px; }
123
+
124
+ .post-title { font-size: 42px; letter-spacing: -1px; line-height: 1; }
125
+ @media screen and (max-width: 800px) { .post-title { font-size: 36px; } }
126
+
127
+ .post-content { margin-bottom: 30px; }
128
+ .post-content h2 { font-size: 32px; }
129
+ @media screen and (max-width: 800px) { .post-content h2 { font-size: 28px; } }
130
+ .post-content h3 { font-size: 26px; }
131
+ @media screen and (max-width: 800px) { .post-content h3 { font-size: 22px; } }
132
+ .post-content h4 { font-size: 20px; }
133
+ @media screen and (max-width: 800px) { .post-content h4 { font-size: 18px; } }
134
+
135
+ /** Syntax highlighting styles */
136
+ .highlight { background: #fff; }
137
+ .highlighter-rouge .highlight { background: #eef; }
138
+ .highlight .c { color: #998; font-style: italic; }
139
+ .highlight .err { color: #a61717; background-color: #e3d2d2; }
140
+ .highlight .k { font-weight: bold; }
141
+ .highlight .o { font-weight: bold; }
142
+ .highlight .cm { color: #998; font-style: italic; }
143
+ .highlight .cp { color: #999; font-weight: bold; }
144
+ .highlight .c1 { color: #998; font-style: italic; }
145
+ .highlight .cs { color: #999; font-weight: bold; font-style: italic; }
146
+ .highlight .gd { color: #000; background-color: #fdd; }
147
+ .highlight .gd .x { color: #000; background-color: #faa; }
148
+ .highlight .ge { font-style: italic; }
149
+ .highlight .gr { color: #a00; }
150
+ .highlight .gh { color: #999; }
151
+ .highlight .gi { color: #000; background-color: #dfd; }
152
+ .highlight .gi .x { color: #000; background-color: #afa; }
153
+ .highlight .go { color: #888; }
154
+ .highlight .gp { color: #555; }
155
+ .highlight .gs { font-weight: bold; }
156
+ .highlight .gu { color: #aaa; }
157
+ .highlight .gt { color: #a00; }
158
+ .highlight .kc { font-weight: bold; }
159
+ .highlight .kd { font-weight: bold; }
160
+ .highlight .kp { font-weight: bold; }
161
+ .highlight .kr { font-weight: bold; }
162
+ .highlight .kt { color: #458; font-weight: bold; }
163
+ .highlight .m { color: #099; }
164
+ .highlight .s { color: #d14; }
165
+ .highlight .na { color: #008080; }
166
+ .highlight .nb { color: #0086B3; }
167
+ .highlight .nc { color: #458; font-weight: bold; }
168
+ .highlight .no { color: #008080; }
169
+ .highlight .ni { color: #800080; }
170
+ .highlight .ne { color: #900; font-weight: bold; }
171
+ .highlight .nf { color: #900; font-weight: bold; }
172
+ .highlight .nn { color: #555; }
173
+ .highlight .nt { color: #000080; }
174
+ .highlight .nv { color: #008080; }
175
+ .highlight .ow { font-weight: bold; }
176
+ .highlight .w { color: #bbb; }
177
+ .highlight .mf { color: #099; }
178
+ .highlight .mh { color: #099; }
179
+ .highlight .mi { color: #099; }
180
+ .highlight .mo { color: #099; }
181
+ .highlight .sb { color: #d14; }
182
+ .highlight .sc { color: #d14; }
183
+ .highlight .sd { color: #d14; }
184
+ .highlight .s2 { color: #d14; }
185
+ .highlight .se { color: #d14; }
186
+ .highlight .sh { color: #d14; }
187
+ .highlight .si { color: #d14; }
188
+ .highlight .sx { color: #d14; }
189
+ .highlight .sr { color: #009926; }
190
+ .highlight .s1 { color: #d14; }
191
+ .highlight .ss { color: #990073; }
192
+ .highlight .bp { color: #999; }
193
+ .highlight .vc { color: #008080; }
194
+ .highlight .vg { color: #008080; }
195
+ .highlight .vi { color: #008080; }
196
+ .highlight .il { color: #099; }
_site/assets/minima-social-icons.svg ADDED
_site/feed.xml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2021-10-19T11:58:07+02:00</updated><id>http://localhost:4000/feed.xml</id><title type="html">Your awesome title</title><subtitle>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</subtitle><entry><title type="html">Welcome to Jekyll!</title><link href="http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html" rel="alternate" type="text/html" title="Welcome to Jekyll!" /><published>2021-10-19T09:57:57+02:00</published><updated>2021-10-19T09:57:57+02:00</updated><id>http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll</id><content type="html" xml:base="http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html">&lt;p&gt;You’ll find this post in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt;, which launches a web server and auto-regenerates your site when a file is updated.&lt;/p&gt;
2
+
3
+ &lt;p&gt;Jekyll requires blog post files to be named according to the following format:&lt;/p&gt;
4
+
5
+ &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YEAR-MONTH-DAY-title.MARKUP&lt;/code&gt;&lt;/p&gt;
6
+
7
+ &lt;p&gt;Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YEAR&lt;/code&gt; is a four-digit number, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MONTH&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DAY&lt;/code&gt; are both two-digit numbers, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MARKUP&lt;/code&gt; is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.&lt;/p&gt;
8
+
9
+ &lt;p&gt;Jekyll also offers powerful support for code snippets:&lt;/p&gt;
10
+
11
+ &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print_hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
12
+ &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hi, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
13
+ &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
14
+ &lt;span class=&quot;n&quot;&gt;print_hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Tom'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
15
+ &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; prints 'Hi, Tom' to STDOUT.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
16
+
17
+ &lt;p&gt;Check out the &lt;a href=&quot;https://jekyllrb.com/docs/home&quot;&gt;Jekyll docs&lt;/a&gt; for more info on how to get the most out of Jekyll. File all bugs/feature requests at &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;Jekyll’s GitHub repo&lt;/a&gt;. If you have questions, you can ask them on &lt;a href=&quot;https://talk.jekyllrb.com/&quot;&gt;Jekyll Talk&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html">You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated. Jekyll requires blog post files to be named according to the following format: YEAR-MONTH-DAY-title.MARKUP Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers, and MARKUP is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: def print_hi(name) puts &quot;Hi, #{name}&quot; end print_hi('Tom') #=&amp;gt; prints 'Hi, Tom' to STDOUT. Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk.</summary></entry></feed>
_site/index.html ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>Your awesome title | Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="Your awesome title" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
11
+ <meta property="og:description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
12
+ <link rel="canonical" href="http://localhost:4000/" />
13
+ <meta property="og:url" content="http://localhost:4000/" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta property="twitter:title" content="Your awesome title" />
17
+ <script type="application/ld+json">
18
+ {"@type":"WebSite","headline":"Your awesome title","url":"http://localhost:4000/","description":"Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.","name":"Your awesome title","@context":"https://schema.org"}</script>
19
+ <!-- End Jekyll SEO tag -->
20
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
21
+ <body><header class="site-header" role="banner">
22
+
23
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
24
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
25
+ <label for="nav-trigger">
26
+ <span class="menu-icon">
27
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
28
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
29
+ </svg>
30
+ </span>
31
+ </label>
32
+
33
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
34
+ </nav></div>
35
+ </header>
36
+ <main class="page-content" aria-label="Content">
37
+ <div class="wrapper">
38
+ <div class="home">
39
+ <h2 class="post-list-heading">Posts</h2>
40
+ <ul class="post-list"><li><span class="post-meta">Oct 19, 2021</span>
41
+ <h3>
42
+ <a class="post-link" href="/jekyll/update/2021/10/19/welcome-to-jekyll.html">
43
+ Welcome to Jekyll!
44
+ </a>
45
+ </h3></li></ul>
46
+
47
+ <p class="rss-subscribe">subscribe <a href="/feed.xml">via RSS</a></p></div>
48
+
49
+ </div>
50
+ </main><footer class="site-footer h-card">
51
+ <data class="u-url" href="/"></data>
52
+
53
+ <div class="wrapper">
54
+
55
+ <h2 class="footer-heading">Your awesome title</h2>
56
+
57
+ <div class="footer-col-wrapper">
58
+ <div class="footer-col footer-col-1">
59
+ <ul class="contact-list">
60
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
61
+ </div>
62
+
63
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
64
+ </div>
65
+
66
+ <div class="footer-col footer-col-3">
67
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
68
+ </div>
69
+ </div>
70
+
71
+ </div>
72
+
73
+ </footer>
74
+ </body>
75
+
76
+ </html>
_site/jekyll/update/2021/10/19/welcome-to-jekyll.html ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>Welcome to Jekyll! | Your awesome title</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="Welcome to Jekyll!" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated. Jekyll requires blog post files to be named according to the following format: YEAR-MONTH-DAY-title.MARKUP Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers, and MARKUP is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: def print_hi(name) puts &quot;Hi, #{name}&quot; end print_hi(&#39;Tom&#39;) #=&gt; prints &#39;Hi, Tom&#39; to STDOUT. Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk." />
11
+ <meta property="og:description" content="You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated. Jekyll requires blog post files to be named according to the following format: YEAR-MONTH-DAY-title.MARKUP Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers, and MARKUP is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: def print_hi(name) puts &quot;Hi, #{name}&quot; end print_hi(&#39;Tom&#39;) #=&gt; prints &#39;Hi, Tom&#39; to STDOUT. Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk." />
12
+ <link rel="canonical" href="http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html" />
13
+ <meta property="og:url" content="http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta property="og:type" content="article" />
16
+ <meta property="article:published_time" content="2021-10-19T09:57:57+02:00" />
17
+ <meta name="twitter:card" content="summary" />
18
+ <meta property="twitter:title" content="Welcome to Jekyll!" />
19
+ <script type="application/ld+json">
20
+ {"@type":"BlogPosting","headline":"Welcome to Jekyll!","dateModified":"2021-10-19T09:57:57+02:00","datePublished":"2021-10-19T09:57:57+02:00","url":"http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/jekyll/update/2021/10/19/welcome-to-jekyll.html"},"description":"You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated. Jekyll requires blog post files to be named according to the following format: YEAR-MONTH-DAY-title.MARKUP Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers, and MARKUP is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: def print_hi(name) puts &quot;Hi, #{name}&quot; end print_hi(&#39;Tom&#39;) #=&gt; prints &#39;Hi, Tom&#39; to STDOUT. Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk.","@context":"https://schema.org"}</script>
21
+ <!-- End Jekyll SEO tag -->
22
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
23
+ <body><header class="site-header" role="banner">
24
+
25
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
26
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
27
+ <label for="nav-trigger">
28
+ <span class="menu-icon">
29
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
30
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
31
+ </svg>
32
+ </span>
33
+ </label>
34
+
35
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
36
+ </nav></div>
37
+ </header>
38
+ <main class="page-content" aria-label="Content">
39
+ <div class="wrapper">
40
+ <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
41
+
42
+ <header class="post-header">
43
+ <h1 class="post-title p-name" itemprop="name headline">Welcome to Jekyll!</h1>
44
+ <p class="post-meta">
45
+ <time class="dt-published" datetime="2021-10-19T09:57:57+02:00" itemprop="datePublished">Oct 19, 2021
46
+ </time></p>
47
+ </header>
48
+
49
+ <div class="post-content e-content" itemprop="articleBody">
50
+ <p>You’ll find this post in your <code class="language-plaintext highlighter-rouge">_posts</code> directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run <code class="language-plaintext highlighter-rouge">jekyll serve</code>, which launches a web server and auto-regenerates your site when a file is updated.</p>
51
+
52
+ <p>Jekyll requires blog post files to be named according to the following format:</p>
53
+
54
+ <p><code class="language-plaintext highlighter-rouge">YEAR-MONTH-DAY-title.MARKUP</code></p>
55
+
56
+ <p>Where <code class="language-plaintext highlighter-rouge">YEAR</code> is a four-digit number, <code class="language-plaintext highlighter-rouge">MONTH</code> and <code class="language-plaintext highlighter-rouge">DAY</code> are both two-digit numbers, and <code class="language-plaintext highlighter-rouge">MARKUP</code> is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.</p>
57
+
58
+ <p>Jekyll also offers powerful support for code snippets:</p>
59
+
60
+ <figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">print_hi</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
61
+ <span class="nb">puts</span> <span class="s2">"Hi, </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">"</span>
62
+ <span class="k">end</span>
63
+ <span class="n">print_hi</span><span class="p">(</span><span class="s1">'Tom'</span><span class="p">)</span>
64
+ <span class="c1">#=&gt; prints 'Hi, Tom' to STDOUT.</span></code></pre></figure>
65
+
66
+ <p>Check out the <a href="https://jekyllrb.com/docs/home">Jekyll docs</a> for more info on how to get the most out of Jekyll. File all bugs/feature requests at <a href="https://github.com/jekyll/jekyll">Jekyll’s GitHub repo</a>. If you have questions, you can ask them on <a href="https://talk.jekyllrb.com/">Jekyll Talk</a>.</p>
67
+
68
+
69
+ </div><a class="u-url" href="/jekyll/update/2021/10/19/welcome-to-jekyll.html" hidden></a>
70
+ </article>
71
+
72
+ </div>
73
+ </main><footer class="site-footer h-card">
74
+ <data class="u-url" href="/"></data>
75
+
76
+ <div class="wrapper">
77
+
78
+ <h2 class="footer-heading">Your awesome title</h2>
79
+
80
+ <div class="footer-col-wrapper">
81
+ <div class="footer-col footer-col-1">
82
+ <ul class="contact-list">
83
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
84
+ </div>
85
+
86
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
87
+ </div>
88
+
89
+ <div class="footer-col footer-col-3">
90
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
91
+ </div>
92
+ </div>
93
+
94
+ </div>
95
+
96
+ </footer>
97
+ </body>
98
+
99
+ </html>
_site/large-scale-demo/index.html ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>Large scale demo | Your awesome title</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="Large scale demo" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
11
+ <meta property="og:description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
12
+ <link rel="canonical" href="http://localhost:4000/large-scale-demo/" />
13
+ <meta property="og:url" content="http://localhost:4000/large-scale-demo/" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta property="twitter:title" content="Large scale demo" />
17
+ <script type="application/ld+json">
18
+ {"@type":"WebPage","headline":"Large scale demo","url":"http://localhost:4000/large-scale-demo/","description":"Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.","@context":"https://schema.org"}</script>
19
+ <!-- End Jekyll SEO tag -->
20
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
21
+ <body><header class="site-header" role="banner">
22
+
23
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
24
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
25
+ <label for="nav-trigger">
26
+ <span class="menu-icon">
27
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
28
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
29
+ </svg>
30
+ </span>
31
+ </label>
32
+
33
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
34
+ </nav></div>
35
+ </header>
36
+ <main class="page-content" aria-label="Content">
37
+ <div class="wrapper">
38
+ <article class="post">
39
+
40
+ <header class="post-header">
41
+ <h1 class="post-title">Large scale demo</h1>
42
+ </header>
43
+
44
+ <div class="post-content">
45
+
46
+
47
+ </div>
48
+
49
+ </article>
50
+
51
+ </div>
52
+ </main><footer class="site-footer h-card">
53
+ <data class="u-url" href="/"></data>
54
+
55
+ <div class="wrapper">
56
+
57
+ <h2 class="footer-heading">Your awesome title</h2>
58
+
59
+ <div class="footer-col-wrapper">
60
+ <div class="footer-col footer-col-1">
61
+ <ul class="contact-list">
62
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
63
+ </div>
64
+
65
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
66
+ </div>
67
+
68
+ <div class="footer-col footer-col-3">
69
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
70
+ </div>
71
+ </div>
72
+
73
+ </div>
74
+
75
+ </footer>
76
+ </body>
77
+
78
+ </html>
_site/main-training/index.html ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 -->
6
+ <title>Main training | Your awesome title</title>
7
+ <meta name="generator" content="Jekyll v3.9.0" />
8
+ <meta property="og:title" content="Main training" />
9
+ <meta property="og:locale" content="en_US" />
10
+ <meta name="description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
11
+ <meta property="og:description" content="Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description." />
12
+ <link rel="canonical" href="http://localhost:4000/main-training/" />
13
+ <meta property="og:url" content="http://localhost:4000/main-training/" />
14
+ <meta property="og:site_name" content="Your awesome title" />
15
+ <meta name="twitter:card" content="summary" />
16
+ <meta property="twitter:title" content="Main training" />
17
+ <script type="application/ld+json">
18
+ {"@type":"WebPage","headline":"Main training","url":"http://localhost:4000/main-training/","description":"Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.","@context":"https://schema.org"}</script>
19
+ <!-- End Jekyll SEO tag -->
20
+ <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="Your awesome title" /></head>
21
+ <body><header class="site-header" role="banner">
22
+
23
+ <div class="wrapper"><a class="site-title" rel="author" href="/">Your awesome title</a><nav class="site-nav">
24
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
25
+ <label for="nav-trigger">
26
+ <span class="menu-icon">
27
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
28
+ <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
29
+ </svg>
30
+ </span>
31
+ </label>
32
+
33
+ <div class="trigger"><a class="page-link" href="/about/">About</a><a class="page-link" href="/large-scale-demo/">Large scale demo</a><a class="page-link" href="/main-training/">Main training</a></div>
34
+ </nav></div>
35
+ </header>
36
+ <main class="page-content" aria-label="Content">
37
+ <div class="wrapper">
38
+ <article class="post">
39
+
40
+ <header class="post-header">
41
+ <h1 class="post-title">Main training</h1>
42
+ </header>
43
+
44
+ <div class="post-content">
45
+
46
+
47
+ </div>
48
+
49
+ </article>
50
+
51
+ </div>
52
+ </main><footer class="site-footer h-card">
53
+ <data class="u-url" href="/"></data>
54
+
55
+ <div class="wrapper">
56
+
57
+ <h2 class="footer-heading">Your awesome title</h2>
58
+
59
+ <div class="footer-col-wrapper">
60
+ <div class="footer-col footer-col-1">
61
+ <ul class="contact-list">
62
+ <li class="p-name">Your awesome title</li><li><a class="u-email" href="mailto:your-email@example.com">your-email@example.com</a></li></ul>
63
+ </div>
64
+
65
+ <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/jekyll"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">jekyll</span></a></li><li><a href="https://www.twitter.com/jekyllrb"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">jekyllrb</span></a></li></ul>
66
+ </div>
67
+
68
+ <div class="footer-col footer-col-3">
69
+ <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
70
+ </div>
71
+ </div>
72
+
73
+ </div>
74
+
75
+ </footer>
76
+ </body>
77
+
78
+ </html>
efficient_training.ipynb ADDED
The diff for this file is too large to render. See raw diff
header-animate.js ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // draw background; Note: this background is based on https://codepen.io/pawelqcm/pen/oxPYox by Pawel
2
+ // Note 2: Pawel, you're awesome.
3
+ (function() {
4
+ var main_element = document.getElementById("header_main");
5
+ var content_element = document.getElementById("overlay");
6
+ var canvas = document.querySelector('canvas');
7
+ var title_elem = document.getElementsByClassName("title_elem")[0];
8
+ var title_text = document.getElementById("title_text");
9
+ ctx = canvas.getContext('2d');
10
+ if (!ctx)
11
+ console.warn("Your browser does not support canvas, content may be broken :'(");
12
+
13
+ var SENSITIVITY, SIBLINGS_LIMIT, DENSITY, TOTAL_NODES, ANCHOR_LENGTH, CURSOR_HEIGHT, CURSOR_WIDTH;
14
+ css_opts = getComputedStyle(document.documentElement);
15
+ SENSITIVITY = css_opts.getPropertyValue('--background-sensitivity') || 120;
16
+ SIBLINGS_LIMIT = css_opts.getPropertyValue('--background-siblings') || 7;
17
+ NODE_DENSITY = css_opts.getPropertyValue('--background-node-density') || 6;
18
+ CURSOR_WIDTH = css_opts.getPropertyValue('--background-cursor-width') || 250;
19
+ CURSOR_HEIGHT = css_opts.getPropertyValue('--background-cursor-height') || 250;
20
+ CURSOR_VERTICAL_SHRINK = css_opts.getPropertyValue('--background-cursor-vertical-shrink') || 0.1;
21
+ SPEED_COEF = css_opts.getPropertyValue('--background-speed') || 1;
22
+ ENERGY_DECAY = css_opts.getPropertyValue('--energy-decay') || 2;
23
+ SHOW_IF_WIDER_THAN = css_opts.getPropertyValue('--background-show-if-wider-than') || 500;
24
+ MOVE_ON_CURSOR = css_opts.getPropertyValue('--background-move-on-cursor').includes("true") || false;
25
+
26
+ var nodes = [];
27
+ choice = (choices => choices[Math.floor(Math.random() * choices.length)])
28
+ sample_color = () => choice([[40, 40, 40], [133, 133, 133]])
29
+
30
+ ANCHOR_LENGTH = 20;
31
+
32
+ var cursor = {x: 0, y: 0};
33
+
34
+ function centralize_cursor() {
35
+ var rect = document.getElementById("bug-logo").getBoundingClientRect()
36
+ var window_left = window.pageXOffset || document.documentElement.scrollLeft;
37
+ var window_top = window.pageYOffset || document.documentElement.scrollTop;
38
+ cursor.x = window_left + rect.left + rect.width / 2;
39
+ cursor.y = window_top + rect.top + rect.height / 2;
40
+ }
41
+
42
+ function Node(x, y) {
43
+ this.anchorX = x;
44
+ this.anchorY = y;
45
+ this.x = Math.random() * (x - (x - ANCHOR_LENGTH)) + (x - ANCHOR_LENGTH);
46
+ this.y = Math.random() * (y - (y - ANCHOR_LENGTH)) + (y - ANCHOR_LENGTH);
47
+ this.vx = (Math.random() * 2 - 1) * SPEED_COEF;
48
+ this.vy = (Math.random() * 2 - 1) * SPEED_COEF;
49
+ this.energy = Math.random() * 100;
50
+ this.radius = Math.random();
51
+ this.siblings = [];
52
+ [this.r, this.g, this.b] = sample_color()
53
+ this.brightness = 0;
54
+ }
55
+
56
+ Node.prototype.drawNode = function() {
57
+ var color = `rgba(${this.r}, ${this.g}, ${this.b}, ${this.brightness})`;
58
+ ctx.beginPath();
59
+ ctx.arc(this.x, this.y, 2 * this.radius + 2 * this.siblings.length / SIBLINGS_LIMIT, 0, 2 * Math.PI);
60
+ ctx.fillStyle = color;
61
+ ctx.fill();
62
+ };
63
+
64
+ Node.prototype.drawConnections = function() {
65
+ for (var i = 0; i < this.siblings.length; i++) {
66
+ var color = `rgba(133, 133, 133, ${this.brightness})`;
67
+ ctx.beginPath();
68
+ ctx.moveTo(this.x, this.y);
69
+ ctx.lineTo(this.siblings[i].x, this.siblings[i].y);
70
+ ctx.lineWidth = 1 - calcDistance(this, this.siblings[i]) / SENSITIVITY;
71
+ ctx.strokeStyle = color;
72
+ ctx.stroke();
73
+ }
74
+ };
75
+
76
+
77
+ Node.prototype.moveNode = function() {
78
+ this.energy -= ENERGY_DECAY;
79
+ if (this.energy < 1) {
80
+ this.energy = Math.random() * 100;
81
+ if (this.x - this.anchorX < -ANCHOR_LENGTH) {
82
+ this.vx = Math.random() * SPEED_COEF;
83
+ } else if (this.x - this.anchorX > ANCHOR_LENGTH) {
84
+ this.vx = Math.random() * -SPEED_COEF;
85
+ } else {
86
+ this.vx = Math.random() * SPEED_COEF * 2 - SPEED_COEF;
87
+ }
88
+ if (this.y - this.anchorY < -ANCHOR_LENGTH) {
89
+ this.vy = Math.random() * SPEED_COEF;
90
+ } else if (this.y - this.anchorY > ANCHOR_LENGTH) {
91
+ this.vy = Math.random() * -SPEED_COEF;
92
+ } else {
93
+ this.vy = Math.random() * SPEED_COEF * 2 - SPEED_COEF;
94
+ }
95
+ }
96
+ relative_speed_rate = Math.min(canvas.height / 100, 10.0)
97
+ this.x += this.vx * this.energy * relative_speed_rate;
98
+ this.y += this.vy * this.energy * relative_speed_rate;
99
+ };
100
+
101
+ function initNodes() {
102
+ centralize_cursor();
103
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
104
+ if (canvas.width >= SHOW_IF_WIDER_THAN)
105
+ total_nodes = Math.round(NODE_DENSITY * (canvas.width / 100 * canvas.height / 100));
106
+ else
107
+ total_nodes = 0;
108
+ nodes = [];
109
+ for (var i = 0; i < total_nodes; i++)
110
+ nodes.push(new Node(50 + Math.random() * (canvas.width - 100),
111
+ 5 + Math.random() * (canvas.height - 10)));
112
+ }
113
+
114
+ function calcDistance(node1, node2) {
115
+ return Math.sqrt(Math.pow(node1.x - node2.x, 2) + (Math.pow(node1.y - node2.y, 2)));
116
+ }
117
+
118
+ function findSiblings() {
119
+ var node1, node2, distance;
120
+ for (var i = 0; i < nodes.length; i++) {
121
+ node1 = nodes[i];
122
+ node1.siblings = [];
123
+ for (var j = 0; j < nodes.length; j++) {
124
+ node2 = nodes[j];
125
+ if (node1 !== node2) {
126
+ distance = calcDistance(node1, node2);
127
+ if (distance < SENSITIVITY) {
128
+ if (node1.siblings.length < SIBLINGS_LIMIT) {
129
+ node1.siblings.push(node2);
130
+ } else {
131
+ var node_sibling_distance = 0;
132
+ var max_distance = 0;
133
+ var s;
134
+ for (var k = 0; k < SIBLINGS_LIMIT; k++) {
135
+ node_sibling_distance = calcDistance(node1, node1.siblings[k]);
136
+ if (node_sibling_distance > max_distance) {
137
+ max_distance = node_sibling_distance;
138
+ s = k;
139
+ }
140
+ }
141
+ if (distance < max_distance) {
142
+ node1.siblings.splice(s, 1);
143
+ node1.siblings.push(node2);
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ function redrawScene() {
153
+ resizeWindow();
154
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
155
+ findSiblings();
156
+ var i, node, distance;
157
+ for (i = 0; i < nodes.length; i++) {
158
+ node = nodes[i];
159
+ scaled_distance = calcDistance({x: cursor.x / CURSOR_WIDTH, y: cursor.y / CURSOR_HEIGHT},
160
+ {x: node.x / CURSOR_WIDTH, y: node.y / CURSOR_HEIGHT});
161
+
162
+ node.brightness = Math.max(1 - scaled_distance, 0);
163
+ }
164
+ for (i = 0; i < nodes.length; i++) {
165
+ node = nodes[i];
166
+ if (node.brightness) {
167
+ node.drawConnections();
168
+ node.drawNode();
169
+ }
170
+ node.moveNode();
171
+ }
172
+ requestAnimationFrame(redrawScene);
173
+ }
174
+
175
+ function initHandlers() {
176
+ document.addEventListener('resize', resizeWindow);
177
+ document.addEventListener('orientationchange', resizeWindow);
178
+ if (MOVE_ON_CURSOR) {
179
+ document.addEventListener('mousemove', moveHandler);
180
+ document.addEventListener('touchmove', moveHandler);
181
+ }
182
+ }
183
+
184
+ function resizeWindow(evt) {
185
+ var new_width, new_height;
186
+ new_width = Math.round(Math.max(title_elem.getBoundingClientRect().right, window.innerWidth))
187
+ if (screen.width < 640)
188
+ title_text.style.fontSize = "20px";
189
+ else
190
+ title_text.style.fontSize = "32px";
191
+
192
+
193
+ if (!MOVE_ON_CURSOR)
194
+ new_height = Math.round(title_elem.getBoundingClientRect().top - canvas.getBoundingClientRect().top);
195
+ else
196
+ new_height = Math.round(Math.max(
197
+ content_element.offsetHeight, content_element.scrollHeight,
198
+ content_element.clientHeight, window.innerHeight));
199
+
200
+ if (canvas.width != new_width || canvas.height != new_height) {
201
+ canvas.width = new_width;
202
+ canvas.height = new_height;
203
+ main_element.style.height = (title_elem.offsetHeight + title_elem.offsetTop + 10) + "px";
204
+ initNodes();
205
+ }
206
+ if (!MOVE_ON_CURSOR)
207
+ centralize_cursor();
208
+ }
209
+
210
+ function moveHandler(evt) {
211
+ if (evt.type == "mousemove") {
212
+ cursor.x = window.pageXOffset + evt.clientX;
213
+ cursor.y = window.pageYOffset + evt.clientY;
214
+ }
215
+ else { // touch event
216
+ cursor.x = window.pageXOffset + evt.changedTouches[0].clientX;
217
+ cursor.y = window.pageYOffset + evt.changedTouches[0].clientY;
218
+ }
219
+ }
220
+
221
+ initHandlers();
222
+ initNodes();
223
+ redrawScene();
224
+
225
+ })();
index.html ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+
8
+ <title>Training Transformers Together</title>
9
+ <meta name="description" content="A NeurIPS'21 demonstration that explains how to train large models together with multiple collaborators.">
10
+ <link rel="mask-icon" href="https://learning-at-home.github.io/logo_small.png">
11
+ <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://learning-at-home.github.io/logo.png">
12
+ <link rel="icon" class="js-site-favicon" type="image/png" href="https://learning-at-home.github.io/logo.png">
13
+ <meta property="og:url" content="https://training-transformers-together.github.io">
14
+ <meta property="og:site_name" content="Training Transformers Together">
15
+ <meta property="og:title" content="Train vast neural networks together">
16
+ <meta property="og:description" content="A NeurIPS'21 demonstration that explains how to train large models together with multiple collaborators.">
17
+ <meta property="og:image" content="https://learning-at-home.github.io/logo_small.png">
18
+ <meta property="og:image:type" content="image/png">
19
+ <meta property="og:image:width" content="96">
20
+ <meta property="og:image:height" content="96">
21
+ <meta property="twitter:site" content="https://training-transformers-together.github.io">
22
+ <meta property="twitter:creator" content="Yandex, Hugging Face, University of Washington, Hivemind team & contributors">
23
+ <meta property="twitter:card" content="summary_large_image">
24
+ <meta property="twitter:title" content="Training Transformers Together">
25
+ <meta property="twitter:description" content="A NeurIPS'21 demonstration that explains how to train large models together with multiple collaborators.">
26
+ <meta property="twitter:image:src" content="https://learning-at-home.github.io/logo_horizontal.png">
27
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
28
+
29
+ <!-- Bootstrap core CSS -->
30
+ <link href="https://bootswatch.com/5/flatly/bootstrap.css" rel="stylesheet">
31
+
32
+ <!-- Custom styles for this template -->
33
+ <link href="./style.css" rel="stylesheet">
34
+ </head>
35
+
36
+ <body>
37
+ <div id="header_main" style="display: block;" class="mb-0 pb-0">
38
+ <canvas></canvas>
39
+ <div id="overlay">
40
+ <div id="header_window">
41
+ <div id="header">
42
+ <img src="https://learning-at-home.github.io/logo.png" id="bug-logo"
43
+ style="width: 40%; max-height: 320px; max-width: 320px; z-index:1000; position: relative;">
44
+ <br>
45
+ <h1 class="faded title title_elem mb-1 pb-1" style="margin-top:-25px; margin-bottom:-10px">
46
+ <p style="margin-top: 0px; font-weight:bolder; margin-bottom:0px;">
47
+ <span id="title_text">Training Transformers Together</span>
48
+ </p>
49
+ <p style="font-size: 18px; margin-top:0px; margin-bottom:5px;">
50
+ large-scale deep learning for everyone, by everyone</p>
51
+ <p style="font-size: 18px; font-weight:lighter; margin-top:0px; margin-bottom:0px;">
52
+ A NeurIPS 2021 Demonstration</p>
53
+ </h1>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ <script src="./header-animate.js"></script>
59
+
60
+ <div class="container d-flex justify-content-center mb-2 pb-2" style="max-width: 500px">
61
+ <div class="row text-center align-items-center justify-content-center">
62
+ <div class="col-3">
63
+ <a href="https://research.yandex.com/">
64
+ <img src="logos/yandex.png" class="img-fluid center-block" style="max-width: 66%" alt="Yandex Research">
65
+ </a>
66
+ </div>
67
+ <div class="col-3 px-2">
68
+ <a href="https://huggingface.co/">
69
+ <img src="logos/huggingface.png" class="img-fluid center-block" style="max-width: 66%" alt="Hugging Face">
70
+ </a>
71
+ </div>
72
+ <div class="col-3 px-3">
73
+ <a href="https://www.hse.ru/en/">
74
+ <img src="logos/hse.png" class="img-fluid center-block" style="max-width: 66%" alt="HSE University">
75
+ </a>
76
+ </div>
77
+ <div class="col-3 px-2">
78
+ <a href="http://www.washington.edu/">
79
+ <img src="logos/uwash.png" class="img-fluid center-block" alt="University of Washington">
80
+ </a>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <div class="container" style="display: block;">
86
+ <p>
87
+ There was a time when you could comfortably train state-of-the-art vision and language models at home on your workstation.
88
+ The first convolutional neural net to beat ImageNet
89
+ (<a target="_blank" href="https://proceedings.neurips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf">AlexNet</a>)
90
+ was trained for 5-6 days on two gamer-grade GPUs. In contrast, today's Top-1 ImageNet model
91
+ (<a target="_blank" href="https://arxiv.org/abs/2106.04803">CoAtNet</a>)
92
+ takes 20,000 TPU-v3 days. And things are even worse in the NLP world: training
93
+ <a target="_blank" href="https://arxiv.org/abs/2005.14165">GPT‑3</a>
94
+ on a top-tier server with 8x A100 would take decades.
95
+ </p>
96
+ <p>
97
+ So, can individual researchers and small labs still train state-of-the-art models? Yes we can!
98
+ All it takes is for a bunch of us to come together. In fact, we're doing it right now and <b>you are invited to join!</b>
99
+ </p>
100
+ <iframe id="iframe_main" src="https://hf.space/streamlitiframe/training-transformers-together/dashboard-embedded/+"
101
+ data-src="https://hf.space/streamlitiframe/training-transformers-together/dashboard-embedded/+"
102
+ data-sdk="streamlit"
103
+ title="Streamlit app" class="container p-0 flex-grow space-iframe"
104
+ allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"
105
+ sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"
106
+ style="top:-200px; left:0; bottom:0; right:0; width:100%; height:200px; border:none; margin:0; padding:0; z-index:999999;" scrolling=no>
107
+ <p>This was meant to be an IFrame, but your browser did not display it.</p>
108
+ <p>Please go to <a href="https://huggingface.co/spaces/training-transformers-together/demo">https://huggingface.co/spaces/training-transformers-together/demo</a>.</p>
109
+ </iframe>
110
+ <p>
111
+ In this demo, we train a model similar to <a target="_blank" href="https://openai.com/blog/dall-e/">OpenAI DALL-E</a> —
112
+ a Transformer model that generates images from text descriptions.
113
+ It is trained on <a target="_blank" href="https://laion.ai/laion-400-open-dataset/">LAION-400M</a>,
114
+ the world's largest openly available image-text-pair dataset with 400 million samples. Our model is based on
115
+ the <a target="_blank" href="https://github.com/lucidrains/DALLE-pytorch">dalle‑pytorch</a> implementation
116
+ by <a target="_blank" href="https://github.com/lucidrains">Phil Wang</a> with a few tweaks to make it communication-efficient.
117
+ </p>
118
+ <div class="accordion" id="accordionExample">
119
+ <div class="accordion-item">
120
+ <h2 class="accordion-header" id="headingOne">
121
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
122
+ How to train efficiently over the Internet?
123
+ </button>
124
+ </h2>
125
+ <div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
126
+ <div class="accordion-body">
127
+ <p>
128
+ Modern distributed training algorithms are designed for HPC clusters with a 10-100 gigabit per second bandwidth.
129
+ In turn, a typical Internet connection runs at 10-100 megabits per second: that’s three orders of magnitude slower.
130
+ To make distributed training efficient, you need to win back these three orders of magnitude.
131
+ This may seem daunting at first, but in reality, DL researchers have already made all the necessary pieces for solving this puzzle:
132
+ </p>
133
+ <table class="table table-hover">
134
+ <thead>
135
+ <tr>
136
+ <th scope="col">Speed&#8209;up</th>
137
+ <th scope="col">How to achieve</th>
138
+ </tr>
139
+ </thead>
140
+ <tbody>
141
+ <tr><td class="centered"><strong>4-16x</strong></td><td>
142
+ <strong>Large-batch training:</strong> <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/1904.00962">You et al. (2019)</a> proposed a way for training neural networks efficiently with larger batches, and hence, fewer communication rounds.
143
+ </td></tr>
144
+ <tr><td class="centered"><strong>4-32x</strong></td><td>
145
+ <strong>Gradient compression:</strong> from simple <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/1511.04561">8-bit quantization</a>
146
+ to advanced techniques such as <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/1712.01887">Deep Gradient Compression</a>,
147
+ <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/1905.13727">PowerSGD</a>, <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2102.02888">1-bit Adam</a>,
148
+ and many others. As a rule of thumb, these techniques can safely reduce communication by 16-32x. More extreme compression is often
149
+ possible, but it may affect stability or final quality.
150
+ </td></tr>
151
+ <tr><td class="centered"><strong>4-24x</strong></td><td>
152
+ <strong>Parameter sharing:</strong> reusing parameters between model layers results in a model with fewer parameters,
153
+ and hence, fewer gradients to communicate. <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/1909.11942">Lan et al. (2019)</a> and
154
+ <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/pdf/2107.11817.pdf">Xue et al. (2021)</a> propose efficient parameter sharing architectures
155
+ for NLP and computer vision.
156
+ </td></tr>
157
+ <tr><td class="centered"><strong>1.5-2x</strong></td><td>
158
+ <strong>Overlapping computation with communication:</strong> running network communication in background while
159
+ computing the next portion of gradients. This is a <a target="_blank" rel="noopener noreferrer" href="https://ur.booksc.eu/book/1624068/2d0506">long-standing trick from HPC</a>
160
+ that was recently adapted for DL training. <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2101.06840">Ren et al. (2021)</a> show that
161
+ updating parameters in background while computing the next batch of gradients does not harm convergence.
162
+ </td></tr>
163
+ </tbody>
164
+ </table>
165
+ <p>
166
+ These techniques are already more than enough to cover 1000x slower communication.
167
+ This means that in practice you can pick and choose which of them you want in your training run.
168
+ For this demo, we use 8x larger batches, 4x compression, 12x parameter sharing and partial overlapping.
169
+ If you don’t want parameter sharing, you can trade it for more advanced gradient compression or larger batches.
170
+ </p>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ <div class="accordion" id="accordionAnother" style="margin-top: 10px;">
176
+ <div class="accordion-item">
177
+ <h2 class="accordion-header" id="headingTwo">
178
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseOne">
179
+ How to train with different device types?
180
+ </button>
181
+ </h2>
182
+ <div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#accordionAnother">
183
+ <div class="accordion-body">
184
+ <p>
185
+ Most distributed DL frameworks assume that the computation is performed by a fleet of identical devices,
186
+ typically GPU servers or TPU cores. Under this assumption, each device can be assigned an equal part of
187
+ computation, such as processing a fixed batch size of training samples.
188
+ However, this quickly breaks down if workers use different device types. If one participant uses a GPU (e.g. P100)
189
+ and another runs on TPU-v2-8, it is difficult to find a regime where both devices will be fully utilized.
190
+ </p>
191
+ <p>
192
+ To make the best use of all available devices, we let each device accumulate gradients at its own pace
193
+ with individually tuned batch size and some other features (e.g. gradient checkpointing or using XLA).
194
+ Once workers collectively aggregate some predefined global batch size, they average their gradients
195
+ with weights proportional to each worker's individual contribution (i.e. number of samples processed).
196
+ </p>
197
+ <a class="block overflow-hidden">
198
+ <div class="w-full h-40 mb-2 bg-gray-900 group-hover:bg-gray-850 rounded-lg flex items-start justify-start overflow-hidden">
199
+ <iframe src="https://www.youtube.com/embed/zdVsg5zsGdc" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0"
200
+ style="width: 100%; height: 240px"></iframe>
201
+ </div>
202
+ </a>
203
+ <p>
204
+ This technique allows the "swarm" to automatically adjust its behavior as peers join, leave or fail.
205
+ For instance, if several high-performance peers join the experiment, other peers will need to process a smaller
206
+ number of samples per optimizer step, and hence, the collaboration will train faster with the same hyperparameters.
207
+ In turn, if one of the workers fails and loses its progress (e.g. due to a fp16 overflow), others will make
208
+ up for that by processing slightly more. For more details on how this works, please refer to
209
+ <a target="_blank" rel="noopener noreferrer" href="https://papers.nips.cc/paper/2021/hash/41a60377ba920919939d83326ebee5a1-Abstract.html">
210
+ "Deep Learning In Open Collaborations"</a> paper or the corresponding <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/blog/collaborative-training">blog post</a>.
211
+ </p>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ </div>
216
+
217
+
218
+ <h3 class="my-4">How do I join?</h3>
219
+
220
+ <p>This section will be updated <strong>on December 7</strong>.</p>
221
+
222
+ <h3 class="my-4">Practical aspects</h3>
223
+
224
+ <div class="border-bottom pb-3">
225
+ <!-- Nav tabs -->
226
+ <ul class="nav nav-tabs m-3">
227
+ <li class="nav-item">
228
+ <a class="nav-link active" data-bs-toggle="tab" href="#memory-efficiency">Memory-Efficient Training</a>
229
+ </li>
230
+ <li class="nav-item">
231
+ <a class="nav-link" data-bs-toggle="tab" href="#security">Security</a>
232
+ </li>
233
+ <li class="nav-item">
234
+ <a class="nav-link" data-bs-toggle="tab" href="#make-your-own">Make Your Own</a>
235
+ </li>
236
+ </ul>
237
+
238
+ <!-- Tab panes -->
239
+ <div class="tab-content">
240
+ <div class="tab-pane fade active show" id="memory-efficiency">
241
+ <p>
242
+ Our aim is to train a large model in a decentralized fashion on consumer hardware or low-end cloud instances.
243
+ This means we need to make the model, dataset, and other memory buffers fit onto a few GB of disk, 12-16 GB of CPU RAM,
244
+ and 8-12 GB of GPU memory. Unfortunately, this rules out many popular techniques such as
245
+ <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2101.06840">ZeRO-Offload</a>:
246
+ there is simply not enough RAM for that. Instead, we must make better use of what limited memory we have.
247
+ To do this, we use two techniques: 8-bit Optimizers for GPU memory and dataset streaming for RAM & HDD.
248
+ </p>
249
+ <p>
250
+ <b>8-bit optimizers:</b>
251
+ Using optimizers such as LAMB or Adam requires four times as much GPU memory as simply storing model parameters (8 bytes vs 2 bytes)
252
+ because of additional gradient statistics.
253
+ As such, for training large models with many parameters, the optimizer state takes the largest amount of memory.
254
+ With 8-bit optimizers, this amount is reduced by 75% (2 bytes), making it much easier to fit large models onto consumer GPUs.
255
+ </p><p>
256
+ Naturally, we can combine this technique with offloading and store 8-bit optimizer states in the CPU memory rather
257
+ than in the GPU memory (0 bytes GPU, 2 bytes CPU). To perform an optimizer update, we transfer the GPU gradients
258
+ to the CPU, update the model parameters, and then copy the new weights to the GPU.
259
+ We can do this for each weight one-by-one so that the additional CPU memory required for the
260
+ optimizer update is minimal.
261
+ This combination of offloading and 8-bit optimizers means that we conserve GPU memory (0 bytes per parameter)
262
+ and also use only a limited amount of CPU memory (2 bytes per parameter).
263
+
264
+ </p>
265
+ <p>
266
+ <b>Dataset streaming:</b>
267
+ Usually data is stored on disk and needs to be fully or partially loaded into RAM for training.
268
+ Large datasets used for pretraining measure in <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2101.00027">hundreds of gigabytes</a>
269
+ or even <a target="_blank" rel="noopener noreferrer" href="https://laion.ai/laion-400-open-dataset/">terabytes</a>.
270
+ This can pose a significant problem, as most desktop and cheap cloud instances simply do not have that much free space.
271
+ Furthermore, downloading the data over the Internet would take up hours before one can even begin training.
272
+ </p>
273
+ <center>
274
+ <img src="./logos/stream.gif" id="stream"
275
+ style="width: 80%; max-height: 200px; max-width: 640px; z-index:1000; top:-10px; position: relative;">
276
+ </center>
277
+ <p>
278
+ To circumvent these problems, it is possible to stream the data in the same way as you stream online videos.
279
+ Participants download a small random portion of the training dataset and immediately begin training on it,
280
+ while additional data is loaded in the background. As such, we can train a model with virtually no storage
281
+ overhead from the dataset, and switching to a new dataset is as simple as changing an argument of the dataset class.
282
+ </p>
283
+ <h5><b>Here's our tutorial covering these methods:</b>
284
+ <a target="_blank" rel="noopener noreferrer" href="https://colab.research.google.com/gist/justheuristic/75f6a2a731f05a213a55cd2c8a458aaf/fine-tune-a-language-model-with-dataset-streaming-and-8-bit-optimizers.ipynb">
285
+ <span>
286
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" width="150px">
287
+ </span>
288
+ </a></h5>
289
+
290
+ </div>
291
+ <div class="tab-pane fade" id="security">
292
+ <p>In this section, we discuss common concerns related to security of collaborative training:</p>
293
+
294
+ <p>
295
+ <b>Q: If I join a collaborative experiment, do I allow other people to execute code on my computer?</b>
296
+ </p>
297
+
298
+ <p>
299
+ <b>A:</b> During the training, participants only exchange data (gradients, statistics, model weights) and never send code to each other.
300
+ No other peer can execute arbitrary code on your computer.
301
+ </p>
302
+
303
+ <p>
304
+ To join the experiment, you typically need to run the code (implementing the model, data streaming, training loop, etc.)
305
+ from a repository or a Colab notebook provided by the authors of the experiment.
306
+ This is no different from running any other open source project/Colab notebook.
307
+ </p>
308
+
309
+ <p>
310
+ <b>Q: Can a malicious participant influence the training outcome?</b>
311
+ </p>
312
+
313
+ <p>
314
+ <b>A:</b> It is indeed possible unless we use some defense mechanisms.
315
+ For instance, a malicious participant can damage model weights by sending large numbers instead of correct gradients.
316
+ The same can happen due to broken hardware or misconfiguration.
317
+ </p>
318
+
319
+ <ul>
320
+ <li>
321
+ <p>
322
+ One possible defense is using <b>authentication</b> combined with <b>model checkpointing</b>.
323
+ In this case, participants should log in (e.g. with their Hugging Face account) to interact with the rest of the collaboration.
324
+ In turn, moderators can screen potential participants and add them to an allowlist.
325
+ If something goes wrong (e.g. a participant sends invalid gradients and the model diverges),
326
+ the moderators remove them from the list and revert the model to the latest checkpoint unaffected by the attack.
327
+ </p>
328
+
329
+ <!-- <p><b>Spoiler (TODO): How to implement authentication in a decentralized system efficiently?</b></p>-->
330
+
331
+ <p>
332
+ Nice bonus: using this data, the moderators can acknowledge the personal contribution of each participant.
333
+ </p>
334
+ </li>
335
+ <li>
336
+ <p>
337
+ Another defense is replacing the naive averaging of the peers' gradients with an <b>aggregation technique that is robust to outliers</b>.
338
+ <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2012.10333">Karimireddy et al. (2020)</a>
339
+ suggested such a technique (named CenteredClip) and proved that it does not significantly affect the model's convergence.
340
+ </p>
341
+
342
+ <!-- <p><b>Spoiler (TODO): How does CenteredClip protect from outliers? (Interactive Demo)</b></p>-->
343
+
344
+ <p>
345
+ In our case, CenteredClip is useful but not enough to protect from malicious participants,
346
+ since it implies that the CenteredClip procedure itself is performed by a trusted server.
347
+ By contrast, in our decentralized system, all participants can aggregate a part of the gradients,
348
+ and we cannot assume any of them to be trusted.
349
+ </p>
350
+
351
+ <p>
352
+ Recently, <a target="_blank" rel="noopener noreferrer" href="https://arxiv.org/abs/2106.11257">Gorbunov et al. (2021)</a>
353
+ proposed a robust aggregation protocol for decentralized systems that does not require this assumption.
354
+ This protocol uses CenteredClip as a subroutine but is able to detect and ban participants who performed it incorrectly.
355
+ </p>
356
+ </li>
357
+ </ul>
358
+ </div>
359
+ <div class="tab-pane fade" id="make-your-own">
360
+ <p>In this section, we provide a recipe for you to run a collaborative training experiment yourself.</p>
361
+ <p>
362
+ <b>Got confused?</b> Feel free to ask any questions in our <a target="_blank" rel="noopener noreferrer" href="https://discord.gg/uGugx9zYvN">Discord</a>!
363
+ </p>
364
+ <ol>
365
+ <li class="mb-2">
366
+ Set up dataset streaming:
367
+ <ul>
368
+ <li>
369
+ <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/docs/datasets/share_dataset.html">Upload</a> your dataset to the Hugging Face Hub
370
+ in a streaming-friendly format (<a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/datasets/laion/laion_100m_vqgan_f8">example</a>).
371
+ </li>
372
+ <li>Set up dataset streaming (see the "Memory-Efficient Training" section).</li>
373
+ </ul>
374
+ </li>
375
+ <li class="mb-2">
376
+ Write the code of training peers (<a target="_blank" rel="noopener noreferrer" href="https://github.com/learning-at-home/dalle-hivemind/blob/main/run_trainer.py">example</a>):
377
+ <ul>
378
+ <li>Implement your model, set up dataset streaming, and write the training loop.</li>
379
+ <li>
380
+ Get familiar with the <a href="https://github.com/learning-at-home/hivemind">hivemind</a> library
381
+ (<a target="_blank" rel="noopener noreferrer" href="https://learning-at-home.readthedocs.io/en/latest/user/quickstart.html">quickstart</a>).
382
+ </li>
383
+ <li>
384
+ In the training loop, wrap up your PyTorch optimizer with
385
+ <a target="_blank" rel="noopener noreferrer" href="https://learning-at-home.readthedocs.io/en/latest/modules/optim.html#hivemind.optim.experimental.optimizer.Optimizer">hivemind.Optimizer</a>
386
+ (<a target="_blank" rel="noopener noreferrer" href="https://github.com/learning-at-home/dalle-hivemind/blob/main/task.py#L121">example</a>).
387
+ </li>
388
+ </ul>
389
+ </li>
390
+ <li class="mb-2">
391
+ <b>(optional)</b> Write the code of auxiliary peers (<a target="_blank" rel="noopener noreferrer" href="https://github.com/learning-at-home/dalle-hivemind/blob/main/run_aux_peer.py">example</a>):
392
+ <ul>
393
+ <li>
394
+ Auxiliary peers are a special kind of peers responsible for
395
+ logging experiment progress (e.g., to <a target="_blank" rel="noopener noreferrer" href="https://wandb.ai/">Weights & Biases</a>)
396
+ and uploading model checkpoints (e.g., to <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/docs/transformers/model_sharing">Hugging Face Hub</a>).
397
+ </li>
398
+ <li>
399
+ Such peers don't need to calculate gradients and may be launched on cheap machines without GPUs.
400
+ </li>
401
+ <li>
402
+ They can serve as a convenient entry point to
403
+ <a href="https://learning-at-home.readthedocs.io/en/latest/modules/dht.html">hivemind.DHT</a>
404
+ (i.e., their address can be specified as <code>initial_peers</code>).
405
+ </li>
406
+ <li>
407
+ It is useful to fix their address by providing <code>host_maddrs</code> and <code>identity_path</code>
408
+ arguments to <code>hivemind.DHT</code>
409
+ (these are forwarded to the underlying <a target="_blank" rel="noopener noreferrer" href="https://libp2p.io/">libp2p</a> daemon).
410
+ </li>
411
+ </ul>
412
+ </li>
413
+ <li class="mb-2">
414
+ <b>(optional)</b> Make it easier for other people to join:
415
+ <!-- To be discussed: What about "Make it easier and safer for other people to join" as there is the authentication bullet point?-->
416
+ <ul>
417
+ <li>
418
+ Create notebooks for free GPU providers (Google Colab, Kaggle, AWS SageMaker, etc.).
419
+ People may run them online and/or download and run them on their own hardware.
420
+ </li>
421
+ <li>
422
+ <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/organizations/new">Create</a> a Hugging Face organization
423
+ with all resources related to the training
424
+ (dataset, model, inference demo, how-to-join walkthrough, links to a dashboard with loss and other metrics, etc.).
425
+ Look at <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/training-transformers-together">ours</a> for an example.
426
+ </li>
427
+ <li>
428
+ Set up an authentication system (see the "Security" section).
429
+ For example, you can ask people to join your organization with their Hugging Face accounts
430
+ (the website allows either sharing a link for joining or manually approving new participants).
431
+ This allows you to screen the peers,
432
+ acknowledge their contributions (e.g., make a leaderboard), and
433
+ ban accounts who behave maliciously. You can use our <a href="https://collaborative-training-auth.huggingface.co/docs">authentication system</a> or deploy your own
434
+ (our <a href="https://github.com/huggingface/collaborative-training-auth/tree/demo-neurips">server implementation</a> might be a good start).
435
+ </li>
436
+ <li>
437
+ Set up an inference demo for your model (e.g., using <a target="_blank" rel="noopener noreferrer" href="https://huggingface.co/spaces">Spaces</a>) or
438
+ a script that periodically uploads the inference results to show the training progress.
439
+ </li>
440
+ </ul>
441
+ </li>
442
+ </ol>
443
+ </div>
444
+ </div>
445
+
446
+ </div>
447
+
448
+ <h3 class="my-3">Organizers</h3>
449
+
450
+ This demonstration was created by
451
+ <a href="https://twitter.com/sasha_borzunov">Alexander Borzunov*</a>,
452
+ <a href="https://twitter.com/m_ryabinin">Max Ryabinin*</a>,
453
+ <a href="https://twitter.com/Tim_Dettmers">Tim Dettmers*</a>,
454
+ <a href="https://twitter.com/qlhoest">Quentin Lhoest*</a>,
455
+ <a href="https://twitter.com/LucileSaulnier">Lucile Saulnier*</a>,
456
+ <a href="https://twitter.com/michael_diskin">Michael Diskin</a>,
457
+ <a href="https://twitter.com/YJernite">Yacine Jernite</a>, and
458
+ <a href="https://twitter.com/Thom_Wolf">Thomas Wolf</a>.
459
+
460
+ <h3 class="my-3">Learn more</h3>
461
+
462
+ <ul class="mb-5">
463
+ <li>A NeurIPS 2021 <a href="https://arxiv.org/abs/2106.10207">paper</a> on collaborative deep learning.</li>
464
+ <li><a href="https://github.com/learning-at-home/hivemind">hivemind</a> is a PyTorch library for decentralized deep learning.</li>
465
+ <li><a href="https://github.com/huggingface/datasets">🤗 Datasets</a> allows uploading and streaming training data from the Hub.</li>
466
+ <li><a href="https://github.com/facebookresearch/bitsandbytes">bitsandbytes</a> contains implementations of 8-bit optimizers.</li>
467
+ <li>A <a href="https://arxiv.org/abs/2110.02861">paper</a> on blockwise quantization for communication-efficient training.</li>
468
+ <!-- To be discussed: How about mentioning the blog post containing videos that explain SahajBERT's collaborative training? -->
469
+ <!-- <li>A <a href="https://hf.co/blog/collaborative-training">blog post</a> (with videos) on a collaborative training of a LM with 40 volunteers .</li> -->
470
+ </ul>
471
+
472
+ <!-- Bootstrap core JavaScript
473
+ ================================================== -->
474
+ <!-- Placed at the end of the document so the pages load faster -->
475
+ <script src="https://getbootstrap.com/docs/5.0/dist/js/bootstrap.min.js"></script>
476
+ </body>
477
+ </html>
join-main-training.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ ---
2
+ layout: page
3
+ title: "Join main training"
4
+ permalink: /join-main-training/
5
+ ---
logos/hse.png ADDED
logos/huggingface.png ADDED
logos/stream.gif ADDED
logos/uwash.png ADDED
logos/yandex.png ADDED
quantization/quant.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Quantization reduces a bit representation to less bits for efficient storage or computation.
2
+ # Most floating point data types have a mapping from a bit representation, e.g. 0010 = 2 to a floating
3
+ # point representation 2 -> 2 / max(0010) = 2/15 = 0.133333
4
+ # As such, we can represent a floating point quantization a mapping from integers to floating point values, e.g.
5
+ # [0, 1, 2, 3] -> [-1.0, -0.25, 0.25 , 1.0]
6
+ import numpy as np
7
+ from scipy.spatial.distance import cdist
8
+
9
+ index = np.array([0, 1, 2, 3, 4, 5, 6, 7])
10
+ values = np.linspace(-1.0, 1.0, 8) # 3-bit linear quantization
11
+ print('quantization values:', values)
12
+
13
+ # To quantize an input distribution we first need to normalize its range into the range of the quantization values, in this case [-1.0, 1.0]
14
+ # We can do this through division by the abolute maximum value if our distribution is roughly symmetric (most distribution in deep learning are noramlly distributed)
15
+
16
+ rand_inputs = np.random.randn(1024, 1024).astype(np.float32)
17
+
18
+ absmax = np.max(np.abs(rand_inputs))
19
+ normed = rand_inputs / absmax
20
+ print('normalized min and max range', np.min(normed), np.max(normed))
21
+
22
+ # The next step is to round the input value to the closest quantization value.
23
+ # This can be done by performing a binary search of each element of the normalized input tensor with respect to the sorted values array:
24
+ # In this case, we simply compute the distance between all values and find the closest directly.
25
+
26
+ dist = cdist(normed.flatten().reshape(-1, 1), values.reshape(-1, 1))
27
+ closest_idx = np.argmin(dist, 1).reshape(rand_inputs.shape)
28
+
29
+ val, count = np.unique(closest_idx, return_counts=True)
30
+ print('Values:', val)
31
+ print('Count:', count)
32
+
33
+ # Closest index now represents the quantized 3 bit representation (4 different values). We can use this representation to store the data efficiently.
34
+
35
+
36
+ # ==================DEQUANTIZATION========================
37
+ # To dequantize the tensor we reverse the operations the we did
38
+ # 1. lookup the values corresponding to the 3-bit index
39
+ # 2. Denormalize by multipying by absmax
40
+
41
+ dequant = values[closest_idx]*absmax
42
+ # mean absolute error:
43
+ error = np.abs(dequant-rand_inputs).mean()
44
+ print(f'Absolute linear 3-bit quantization error: {error:.4f}')
45
+
46
+ # This yields an error of about 0.34 per value. We can do better with non-linear quantization.
47
+
48
+ # ==================NON-LINEAR QUANTIZATION========================
49
+ # In non-linear quantization the distance between quantization values is not always equal.
50
+ # This allows us to allocate more values to regions of high density. For example, the normal distribution has many values around 0.
51
+ # This can reduce the overall error in the distribution.
52
+ index = np.array([0, 1, 2, 3, 4, 5, 6, 7])
53
+ values = np.array([-1.0, -0.5, -0.25, -0.075, 0.075, 0.25, 0.5, 1.0])
54
+
55
+ dist = cdist(normed.flatten().reshape(-1, 1), values.reshape(-1, 1))
56
+ closest_idx = np.argmin(dist, 1).reshape(rand_inputs.shape)
57
+
58
+ val, count = np.unique(closest_idx, return_counts=True)
59
+ print('Values:', val)
60
+ print('Count:', count)
61
+
62
+ dequant = values[closest_idx]*absmax
63
+ error = np.abs(dequant-rand_inputs).mean()
64
+ print(f'Absolute non-linear 3-bit quantization error: {error:.4f}')
65
+
66
+ # dynamic quantization
67
+ # Adaptive from: https://github.com/facebookresearch/bitsandbytes/blob/main/bitsandbytes/functional.py
68
+ def create_dynamic_map(signed=True, n=7):
69
+ '''
70
+ Creates the dynamic quantiztion map.
71
+ The dynamic data type is made up of a dynamic exponent and
72
+ fraction. As the exponent increase from 0 to -7 the number
73
+ of bits available for the fraction shrinks.
74
+ This is a generalization of the dynamic type where a certain
75
+ number of the bits and be reserved for the linear quantization
76
+ region (the fraction). n determines the maximum number of
77
+ exponent bits.
78
+ For more details see
79
+ (8-Bit Approximations for Parallelism in Deep Learning)[https://arxiv.org/abs/1511.04561]
80
+ '''
81
+
82
+ data = []
83
+ # these are additional items that come from the case
84
+ # where all the exponent bits are zero and no
85
+ # indicator bit is present
86
+ additional_items = 2**(7-n)-1
87
+ if not signed: additional_items = 2*additional_items
88
+ for i in range(n):
89
+ fraction_items = 2**(i+7-n)+1 if signed else 2**(i+7-n+1)+1
90
+ boundaries = np.linspace(0.1, 1, fraction_items)
91
+ means = (boundaries[:-1]+boundaries[1:])/2.0
92
+ data += ((10**(-(n-1)+i))*means).tolist()
93
+ if signed:
94
+ data += (-(10**(-(n-1)+i))*means).tolist()
95
+
96
+ if additional_items > 0:
97
+ boundaries = np.linspace(0.1, 1, additional_items+1)
98
+ means = (boundaries[:-1]+boundaries[1:])/2.0
99
+ data += ((10**(-(n-1)+i))*means).tolist()
100
+ if signed:
101
+ data += (-(10**(-(n-1)+i))*means).tolist()
102
+
103
+ data.append(0)
104
+ data.append(1.0)
105
+ data.sort()
106
+ return np.array(data)
107
+
108
+ import time
109
+
110
+ values = create_dynamic_map(signed=True)
111
+
112
+ t0 = time.time()
113
+ dist = cdist(normed.flatten().reshape(-1, 1), values.reshape(-1, 1))
114
+ closest_idx = np.argmin(dist, 1).reshape(rand_inputs.shape)
115
+ quant_time = time.time()-t0
116
+
117
+ dequant = values[closest_idx]*absmax
118
+ error = np.abs(dequant-rand_inputs).mean()
119
+ print(f'Absolute dynamic 8-bit quantization error: {error:.4f}')
120
+ print(f'Total time taken: {quant_time:.4f} seconds.')
121
+
122
+ # This yields an error as low as 0.012. We could do even better when we use block-wise quantization.
123
+ # But performing block-wise quantization without optimized code is a bit slow. We can use the bitsandbytes library to do this quickly.
124
+
125
+ import torch
126
+ import bitsandbytes.functional as F
127
+
128
+ rand_inputs = torch.from_numpy(rand_inputs)
129
+ t0 = time.time()
130
+ quant_values, quant_state = F.quantize_blockwise(rand_inputs)
131
+ quant_time = time.time()-t0
132
+ dequant_values = F.dequantize_blockwise(quant_values, quant_state)
133
+
134
+ error = torch.abs(dequant_values-rand_inputs).mean().item()
135
+ print(f'Absolute dynamic block-wise 8-bit quantization error: {error:.4f}')
136
+ print(f'Total time taken (CPU): {quant_time:.4f} seconds.')
137
+
138
+ rand_inputs = rand_inputs.cuda()
139
+ t0 = time.time()
140
+ quant_values, quant_state = F.quantize_blockwise(rand_inputs)
141
+ quant_time = time.time()-t0
142
+ print(f'Total time taken (GPU): {quant_time:.4f} seconds.')
143
+
144
+
style.css ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --border-color: black;
3
+ --window-color: white;
4
+ --background-move-on-cursor: false;
5
+ --background-color: white;
6
+ --background-cursor-width: 400;
7
+ --background-cursor-height: 200;
8
+ --background-show-if-wider-than: 500;
9
+ --background-speed: 0.001;
10
+ --energy-decay: 0.3;
11
+ }
12
+ html {
13
+ font-size: 14px;
14
+ }
15
+ @media (min-width: 768px) {
16
+ html {
17
+ font-size: 16px;
18
+ }
19
+ }
20
+
21
+ body {
22
+ width: 100%;
23
+ margin: 0 auto;
24
+ background-color: var(--background-color);
25
+ }
26
+ #header_main {
27
+ position: relative;
28
+ width: 100%;
29
+ margin: 0 auto;
30
+ }
31
+ #header_main canvas, #overlay {
32
+ width: 100%;
33
+ margin: 0 auto;
34
+ position: absolute;
35
+ }
36
+
37
+ a {
38
+ text-decoration: none;
39
+ }
40
+
41
+ a:hover {
42
+ text-decoration: underline;
43
+ }
44
+
45
+ .container {
46
+ max-width: 46rem;
47
+ }
48
+
49
+ .pricing-header {
50
+ max-width: 700px;
51
+ }
52
+
53
+ .card-deck .card {
54
+ min-width: 220px;
55
+ }
56
+
57
+ .border-top { border-top: 1px solid #e5e5e5; }
58
+ .border-bottom { border-bottom: 1px solid #e5e5e5; }
59
+
60
+ .box-shadow { box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); }
61
+
62
+ .arxiv_button {
63
+ position: relative;
64
+ display: inline-block;
65
+ width: 78px;
66
+ height: 28px;
67
+ background-image: linear-gradient(180deg, #fafbfc, #eff3f6 90%);
68
+ color: #24292e;
69
+ border: 1px solid rgba(27,31,35,.2);
70
+ text-align: center;
71
+ cursor: pointer;
72
+ border-radius: 4px;
73
+ padding-right: 0px;
74
+ padding-top: 2.5px;
75
+ font-size: 12px;
76
+ font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;
77
+ font-weight: 600;
78
+ }
79
+ .arxiv_button:before {
80
+ content: "";
81
+ vertical-align:middle;
82
+ display: inline-block;
83
+ width: 24px;
84
+ height: 24px;
85
+ border: none;
86
+ margin-left: -16px;
87
+ margin-right: 0px;
88
+ margin-top: -2px;
89
+ background: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" class="ionicon s-ion-icon" viewBox="0 0 512 512"><path d="M428 224H288a48 48 0 01-48-48V36a4 4 0 00-4-4h-92a64 64 0 00-64 64v320a64 64 0 0064 64h224a64 64 0 0064-64V228a4 4 0 00-4-4z"></path><path d="M419.22 188.59L275.41 44.78a2 2 0 00-3.41 1.41V176a16 16 0 0016 16h129.81a2 2 0 001.41-3.41z"></path></svg>') right center no-repeat;
90
+ background-size: 18px 16px;
91
+ }
92
+ .arxiv_button:hover {
93
+ background-color:#e6ebf1;
94
+ background-position:-0.5em;
95
+ border-color: #9fa4a9;
96
+ border-color:rgba(27,31,35,.35);
97
+ background-image:linear-gradient(180deg, #f0f3f6, #e6ebf1 90%)
98
+ }
99
+
100
+ #header_window {
101
+ width: 80%;
102
+ min-width: 320px;
103
+ margin: 0 auto;
104
+ text-align: center;
105
+ }
106
+ .faded {
107
+ margin: 0 auto;
108
+ background: var(--window-color);
109
+ box-shadow: 0 0 5px 5px var(--window-color);
110
+ font-family: cursive;
111
+ font-family: "Gill Sans", sans-serif;
112
+ display: inline-block
113
+ }
114
+ .padded {
115
+ width: 100%;
116
+ max-width: 800px;
117
+ text-align: left;
118
+ }
119
+ .title {
120
+ font-size: 32px;
121
+ box-shadow: 0 0 5px 5px var(--window-color);
122
+ font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,
123
+ sans-serif,Apple Color Emoji,Segoe UI Emoji;
124
+ }
125
+ canvas {
126
+ background-color: var(--background-color);
127
+ width: 0px; /* will be changed on init */
128
+ overflow: hidden;
129
+ }
130
+
131
+ a {
132
+ color: #337ab7;
133
+ font-weight: 600;
134
+ }
135
+ a:hover {
136
+ color: #0056b3;
137
+ }
138
+ .nav-link {
139
+ color: #337ab7;
140
+ padding: 0.5rem 1rem;
141
+ font-weight: normal;
142
+ }
143
+ .nav-link:hover {
144
+ color: #337ab7;
145
+ }