Various updates (Bootstrap 3.4.1, lts-12.26 for Stack), small refactors

This commit is contained in:
Chris Hodapp 2019-10-27 09:49:24 -04:00
parent a667e1d000
commit 6e53321f7e
13 changed files with 1272 additions and 786 deletions

View File

@ -1,18 +1,17 @@
/*! /*!
* Bootstrap v3.3.2 (http://getbootstrap.com) * Bootstrap v3.4.1 (https://getbootstrap.com/)
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */
.btn-default, .btn-default,
.btn-primary, .btn-primary,
.btn-success, .btn-success,
.btn-info, .btn-info,
.btn-warning, .btn-warning,
.btn-danger { .btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
} }
.btn-default:active, .btn-default:active,
.btn-primary:active, .btn-primary:active,
@ -26,8 +25,29 @@
.btn-info.active, .btn-info.active,
.btn-warning.active, .btn-warning.active,
.btn-danger.active { .btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-default.disabled,
.btn-primary.disabled,
.btn-success.disabled,
.btn-info.disabled,
.btn-warning.disabled,
.btn-danger.disabled,
.btn-default[disabled],
.btn-primary[disabled],
.btn-success[disabled],
.btn-info[disabled],
.btn-warning[disabled],
.btn-danger[disabled],
fieldset[disabled] .btn-default,
fieldset[disabled] .btn-primary,
fieldset[disabled] .btn-success,
fieldset[disabled] .btn-info,
fieldset[disabled] .btn-warning,
fieldset[disabled] .btn-danger {
-webkit-box-shadow: none;
box-shadow: none;
} }
.btn-default .badge, .btn-default .badge,
.btn-primary .badge, .btn-primary .badge,
@ -42,15 +62,15 @@
background-image: none; background-image: none;
} }
.btn-default { .btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #dbdbdb; border-color: #dbdbdb;
text-shadow: 0 1px 0 #fff;
border-color: #ccc; border-color: #ccc;
} }
.btn-default:hover, .btn-default:hover,
@ -64,16 +84,31 @@
border-color: #dbdbdb; border-color: #dbdbdb;
} }
.btn-default.disabled, .btn-default.disabled,
.btn-default:disabled, .btn-default[disabled],
.btn-default[disabled] { fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
background-color: #e0e0e0; background-color: #e0e0e0;
background-image: none; background-image: none;
} }
.btn-primary { .btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
@ -90,16 +125,31 @@
border-color: #245580; border-color: #245580;
} }
.btn-primary.disabled, .btn-primary.disabled,
.btn-primary:disabled, .btn-primary[disabled],
.btn-primary[disabled] { fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
background-color: #265a88; background-color: #265a88;
background-image: none; background-image: none;
} }
.btn-success { .btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
@ -116,16 +166,31 @@
border-color: #3e8f3e; border-color: #3e8f3e;
} }
.btn-success.disabled, .btn-success.disabled,
.btn-success:disabled, .btn-success[disabled],
.btn-success[disabled] { fieldset[disabled] .btn-success,
.btn-success.disabled:hover,
.btn-success[disabled]:hover,
fieldset[disabled] .btn-success:hover,
.btn-success.disabled:focus,
.btn-success[disabled]:focus,
fieldset[disabled] .btn-success:focus,
.btn-success.disabled.focus,
.btn-success[disabled].focus,
fieldset[disabled] .btn-success.focus,
.btn-success.disabled:active,
.btn-success[disabled]:active,
fieldset[disabled] .btn-success:active,
.btn-success.disabled.active,
.btn-success[disabled].active,
fieldset[disabled] .btn-success.active {
background-color: #419641; background-color: #419641;
background-image: none; background-image: none;
} }
.btn-info { .btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
@ -142,16 +207,31 @@
border-color: #28a4c9; border-color: #28a4c9;
} }
.btn-info.disabled, .btn-info.disabled,
.btn-info:disabled, .btn-info[disabled],
.btn-info[disabled] { fieldset[disabled] .btn-info,
.btn-info.disabled:hover,
.btn-info[disabled]:hover,
fieldset[disabled] .btn-info:hover,
.btn-info.disabled:focus,
.btn-info[disabled]:focus,
fieldset[disabled] .btn-info:focus,
.btn-info.disabled.focus,
.btn-info[disabled].focus,
fieldset[disabled] .btn-info.focus,
.btn-info.disabled:active,
.btn-info[disabled]:active,
fieldset[disabled] .btn-info:active,
.btn-info.disabled.active,
.btn-info[disabled].active,
fieldset[disabled] .btn-info.active {
background-color: #2aabd2; background-color: #2aabd2;
background-image: none; background-image: none;
} }
.btn-warning { .btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
@ -168,16 +248,31 @@
border-color: #e38d13; border-color: #e38d13;
} }
.btn-warning.disabled, .btn-warning.disabled,
.btn-warning:disabled, .btn-warning[disabled],
.btn-warning[disabled] { fieldset[disabled] .btn-warning,
.btn-warning.disabled:hover,
.btn-warning[disabled]:hover,
fieldset[disabled] .btn-warning:hover,
.btn-warning.disabled:focus,
.btn-warning[disabled]:focus,
fieldset[disabled] .btn-warning:focus,
.btn-warning.disabled.focus,
.btn-warning[disabled].focus,
fieldset[disabled] .btn-warning.focus,
.btn-warning.disabled:active,
.btn-warning[disabled]:active,
fieldset[disabled] .btn-warning:active,
.btn-warning.disabled.active,
.btn-warning[disabled].active,
fieldset[disabled] .btn-warning.active {
background-color: #eb9316; background-color: #eb9316;
background-image: none; background-image: none;
} }
.btn-danger { .btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
@ -194,87 +289,103 @@
border-color: #b92c28; border-color: #b92c28;
} }
.btn-danger.disabled, .btn-danger.disabled,
.btn-danger:disabled, .btn-danger[disabled],
.btn-danger[disabled] { fieldset[disabled] .btn-danger,
.btn-danger.disabled:hover,
.btn-danger[disabled]:hover,
fieldset[disabled] .btn-danger:hover,
.btn-danger.disabled:focus,
.btn-danger[disabled]:focus,
fieldset[disabled] .btn-danger:focus,
.btn-danger.disabled.focus,
.btn-danger[disabled].focus,
fieldset[disabled] .btn-danger.focus,
.btn-danger.disabled:active,
.btn-danger[disabled]:active,
fieldset[disabled] .btn-danger:active,
.btn-danger.disabled.active,
.btn-danger[disabled].active,
fieldset[disabled] .btn-danger.active {
background-color: #c12e2a; background-color: #c12e2a;
background-image: none; background-image: none;
} }
.thumbnail, .thumbnail,
.img-thumbnail { .img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
} }
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus { .dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
background-color: #e8e8e8;
} }
.dropdown-menu > .active > a, .dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus { .dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
background-color: #2e6da4;
} }
.navbar-default { .navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px; border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
} }
.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a { .navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
} }
.navbar-brand, .navbar-brand,
.navbar-nav > li > a { .navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
} }
.navbar-inverse { .navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px;
} }
.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a,
.navbar-inverse .navbar-nav > .active > a { .navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
} }
.navbar-inverse .navbar-brand, .navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a { .navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
} }
.navbar-static-top, .navbar-static-top,
.navbar-fixed-top, .navbar-fixed-top,
@ -287,120 +398,120 @@
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus { .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff; color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
} }
.alert { .alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
} }
.alert-success { .alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #b2dba1; border-color: #b2dba1;
} }
.alert-info { .alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #9acfea; border-color: #9acfea;
} }
.alert-warning { .alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #f5e79e; border-color: #f5e79e;
} }
.alert-danger { .alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #dca7a7; border-color: #dca7a7;
} }
.progress { .progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar { .progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-success { .progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-info { .progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-warning { .progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-danger { .progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.progress-bar-striped { .progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
} }
.list-group { .list-group {
border-radius: 4px; border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
} }
.list-group-item.active, .list-group-item.active,
.list-group-item.active:hover, .list-group-item.active:hover,
.list-group-item.active:focus { .list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090; text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #2b669a; border-color: #2b669a;
@ -411,66 +522,66 @@
text-shadow: none; text-shadow: none;
} }
.panel { .panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
} }
.panel-default > .panel-heading { .panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.panel-primary > .panel-heading { .panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.panel-success > .panel-heading { .panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.panel-info > .panel-heading { .panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.panel-warning > .panel-heading { .panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.panel-danger > .panel-heading { .panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.well { .well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #dcdcdc; border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
} }
/*# sourceMappingURL=bootstrap-theme.css.map */ /*# sourceMappingURL=bootstrap-theme.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1434
css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -60,10 +60,25 @@ div.info {
font-style: italic; font-style: italic;
} }
div.result pre {
border: none;
background-color: #efefff;
}
div.result pre code {
# font-style: italic;
}
div.result table td, div.result table th {
# font-style: italic;
background-color: #efefff;
}
table td, table th { table td, table th {
padding: 0.5em; padding: 0.5em;
# border-bottom: 0.5px solid black # border-bottom: 0.5px solid black
} }
table > thead > tr:last-child > * { table > thead > tr:last-child > * {
border-bottom: 2px solid black border-bottom: 2px solid black
} }

View File

@ -281,3 +281,14 @@ https://github.com/stevemao/left-pad/issues/4
- https://twitter.com/fchollet/status/962074070513631232 - https://twitter.com/fchollet/status/962074070513631232
- How does this fit with /composition/? Does it? - How does this fit with /composition/? Does it?
- [[https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-9.html#%25_chap_1][From SICP chapter 1 intro]]: "The acts of the mind, wherein it exerts
its power over simple ideas, are chiefly these three: 1. Combining
several simple ideas into one compound one, and thus all complex
ideas are made. 2. The second is bringing two ideas, whether simple
or complex, together, and setting them by one another so as to take
a view of them at once, without uniting them into one, by which it
gets all its ideas of relations. 3. The third is separating them
from all other ideas that accompany them in their real existence:
this is called abstraction, and thus all its general ideas are
made." -John Locke, An Essay Concerning Human Understanding (1690)

View File

@ -5,29 +5,29 @@
# Table of Contents # Table of Contents
- [1. Introduction](#1.-Introduction) - [1. Introduction](#introduction)
- [1.1. Motivation](#1.1.-Motivation) - [1.1. Motivation](#motivation)
- [1.2. Organization](#1.2.-Organization) - [1.2. Organization](#organization)
- [2. Dependencies & Setup](#2.-Dependencies-&-Setup) - [2. Dependencies & Setup](#dependencies-setup)
- [3. Loading data](#3.-Loading-data) - [3. Loading data](#loading-data)
- [3.1. Aggregation](#3.1.-Aggregation) - [3.1. Aggregation](#aggregation)
- [4. Utility Matrix](#4.-Utility-Matrix) - [4. Utility Matrix](#utility-matrix)
- [5. Slope One Predictors](#5.-Slope-One-Predictors) - [5. Slope One Predictors](#slope-one-predictors)
- [5.1. Weighted Slope One](#5.1.-Weighted-Slope-One) - [5.1. Weighted Slope One](#weighted-slope-one)
- [5.2. Linear Algebra Tricks](#5.2.-Linear-Algebra-Tricks) - [5.2. Linear Algebra Tricks](#linear-algebra-tricks)
- [5.3. Implementation](#5.3.-Implementation) - [5.3. Implementation](#implementation)
- [6. "SVD" algorithm](#6.-%22SVD%22-algorithm) - [6. "SVD" algorithm](#svd-algorithm)
- [6.1. Model & Background](#6.1.-Model-&-Background) - [6.1. Model & Background](#model-background)
- [6.2. Motivation](#6.2.-Motivation) - [6.2. Motivation](#motivation)
- [6.3. Prediction & Error Function](#6.3.-Prediction-&-Error-Function) - [6.3. Prediction & Error Function](#prediction-error-function)
- [6.4. Gradients & Gradient Descent Updates](#6.4.-Gradients-&-Gradient-Descent-Updates) - [6.4. Gradients & Gradient Descent Updates](#gradients-gradient-descent-updates)
- [6.5. Implementation](#6.5.-Implementation) - [6.5. Implementation](#implementation-1)
- [6.6. Running & Testing](#6.6.-Running-&-Testing) - [6.6. Running & Testing](#running-testing)
- [6.7. Visualization of Latent Space](#6.7.-Visualization-of-Latent-Space) - [6.7. Visualization of Latent Space](#visualization-of-latent-space)
- [6.8. Bias](#6.8.-Bias) - [6.8. Bias](#bias)
- [7. Implementations in scikit-surprise](#7.-Implementations-in-scikit-surprise) - [7. Implementations in scikit-surprise](#implementations-in-scikit-surprise)
- [8. Overall results](#8.-Overall-results) - [8. Overall results](#overall-results)
- [9. Further Work](#9.-Further-Work) - [9. Further Work](#further-work)
# 1. Introduction # 1. Introduction

View File

@ -15,8 +15,10 @@ because it's just green threads and cooperative threading is a model
that's fresh out of the '90s, and Python /still/ has the [[https://wiki.python.org/moin/GlobalInterpreterLock][GIL]] - and that's fresh out of the '90s, and Python /still/ has the [[https://wiki.python.org/moin/GlobalInterpreterLock][GIL]] - and
because Elixir, Erlang, Haskell, [[https://github.com/clojure/core.async/][Clojure]] (also [[http://blog.paralleluniverse.co/2013/05/02/quasar-pulsar/][this]]), [[http://docs.paralleluniverse.co/quasar/][Java/Kotlin]], and because Elixir, Erlang, Haskell, [[https://github.com/clojure/core.async/][Clojure]] (also [[http://blog.paralleluniverse.co/2013/05/02/quasar-pulsar/][this]]), [[http://docs.paralleluniverse.co/quasar/][Java/Kotlin]], and
Go all handle async and M:N threading fine, and have for years. The Go all handle async and M:N threading fine, and have for years. The
Python folks have their own set of complaints, like [[http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/][I don't understand Python folks have their own set of complaints, like
Python's Asyncio]]. [[http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/][I don't understand Python's Asyncio]] and
[[http://jordanorelli.com/post/31533769172/why-i-went-from-python-to-go-and-not-nodejs][Why I went from Python to Go (and not node.js)]].
At least it is in good company [[https://nullprogram.com/blog/2018/05/31/#threads][with Emacs still]].
On the other hand, it's still a useful enough paradigm that it's in On the other hand, it's still a useful enough paradigm that it's in
the works for [[https://doc.rust-lang.org/nightly/unstable-book/language-features/generators.html][Rust]] (sort of... it had green threads which were removed the works for [[https://doc.rust-lang.org/nightly/unstable-book/language-features/generators.html][Rust]] (sort of... it had green threads which were removed
@ -75,8 +77,8 @@ coroutines and futures. My summary on what I figured out is below.
** Python already had generator-based coroutines. ** Python already had generator-based coroutines.
Python now has a language feature it refers to as "coroutines" in Python now has a language feature it refers to as "coroutines" in
asyncio (and in calls like ~asyncio.iscoroutine()~, but Python 2.5 it asyncio (and in calls like ~asyncio.iscoroutine()~, but in Python 2.5
also already supported similar-but-not-entirely-the-same form of it also already supported similar-but-not-entirely-the-same form of
coroutine, and even earlier in a limited form via generators. See [[https://www.python.org/dev/peps/pep-0342/][PEP coroutine, and even earlier in a limited form via generators. See [[https://www.python.org/dev/peps/pep-0342/][PEP
342]] and [[http://www.dabeaz.com/coroutines/Coroutines.pdf][Beazley's slides]]. 342]] and [[http://www.dabeaz.com/coroutines/Coroutines.pdf][Beazley's slides]].

View File

@ -1,33 +1,39 @@
---
title: "Recommender Systems, Part 1 (Collaborative Filtering)"
author: Chris Hodapp
date: May 6, 2018
tags: machine_learning, technobabble, notebook, literate
whatever: something
---
# Recommender Systems, Part 1 (Collaborative Filtering) This is an exported version of the Jupyter notebook available at my
- Author: Chris Hodapp GitHub: <https://github.com/Hodapp87/recommender-examples>
- Date: 2018-03-21
# Table of Contents # Table of Contents
- [1. Introduction](#1.-Introduction) - [1. Introduction](#introduction)
- [1.1. Motivation](#1.1.-Motivation) - [1.1. Motivation](#motivation)
- [1.2. Organization](#1.2.-Organization) - [1.2. Organization](#organization)
- [2. Dependencies & Setup](#2.-Dependencies-&-Setup) - [2. Dependencies & Setup](#dependencies-setup)
- [3. Loading data](#3.-Loading-data) - [3. Loading data](#loading-data)
- [3.1. Aggregation](#3.1.-Aggregation) - [3.1. Aggregation](#aggregation)
- [4. Utility Matrix](#4.-Utility-Matrix) - [4. Utility Matrix](#utility-matrix)
- [5. Slope One Predictors](#5.-Slope-One-Predictors) - [5. Slope One Predictors](#slope-one-predictors)
- [5.1. Weighted Slope One](#5.1.-Weighted-Slope-One) - [5.1. Weighted Slope One](#weighted-slope-one)
- [5.2. Linear Algebra Tricks](#5.2.-Linear-Algebra-Tricks) - [5.2. Linear Algebra Tricks](#linear-algebra-tricks)
- [5.3. Implementation](#5.3.-Implementation) - [5.3. Implementation](#implementation)
- [6. "SVD" algorithm](#6.-%22SVD%22-algorithm) - [6. "SVD" algorithm](#svd-algorithm)
- [6.1. Model & Background](#6.1.-Model-&-Background) - [6.1. Model & Background](#model-background)
- [6.2. Motivation](#6.2.-Motivation) - [6.2. Motivation](#motivation)
- [6.3. Prediction & Error Function](#6.3.-Prediction-&-Error-Function) - [6.3. Prediction & Error Function](#prediction-error-function)
- [6.4. Gradients & Gradient Descent Updates](#6.4.-Gradients-&-Gradient-Descent-Updates) - [6.4. Gradients & Gradient Descent Updates](#gradients-gradient-descent-updates)
- [6.5. Implementation](#6.5.-Implementation) - [6.5. Implementation](#implementation-1)
- [6.6. Running & Testing](#6.6.-Running-&-Testing) - [6.6. Running & Testing](#running-testing)
- [6.7. Visualization of Latent Space](#6.7.-Visualization-of-Latent-Space) - [6.7. Visualization of Latent Space](#visualization-of-latent-space)
- [6.8. Bias](#6.8.-Bias) - [6.8. Bias](#bias)
- [7. Implementations in scikit-surprise](#7.-Implementations-in-scikit-surprise) - [7. Implementations in scikit-surprise](#implementations-in-scikit-surprise)
- [8. Overall results](#8.-Overall-results) - [8. Overall results](#overall-results)
- [9. Further Work](#9.-Further-Work) - [9. Further Work](#further-work)
# 1. Introduction # 1. Introduction
@ -102,6 +108,8 @@ Below is just to inspect that data appears to be okay:
ml.info() ml.info()
``` ```
<div class=result>
<class 'pandas.core.frame.DataFrame'> <class 'pandas.core.frame.DataFrame'>
RangeIndex: 20000263 entries, 0 to 20000262 RangeIndex: 20000263 entries, 0 to 20000262
Data columns (total 4 columns): Data columns (total 4 columns):
@ -112,6 +120,8 @@ ml.info()
dtypes: datetime64[ns](1), float32(1), int32(2) dtypes: datetime64[ns](1), float32(1), int32(2)
memory usage: 381.5 MB memory usage: 381.5 MB
</div>
```python ```python
@ -122,6 +132,7 @@ ml.describe()
<div class=result>
| user_id | movie_id | rating | user_id | movie_id | rating
|--------|---------|------- |--------|---------|-------
count|2.000026e+07|2.000026e+07|2.000026e+07 count|2.000026e+07|2.000026e+07|2.000026e+07
@ -132,6 +143,7 @@ min|1.000000e+00|1.000000e+00|5.000000e-01
50%|6.914100e+04|2.167000e+03|3.500000e+00 50%|6.914100e+04|2.167000e+03|3.500000e+00
75%|1.036370e+05|4.770000e+03|4.000000e+00 75%|1.036370e+05|4.770000e+03|4.000000e+00
max|1.384930e+05|1.312620e+05|5.000000e+00 max|1.384930e+05|1.312620e+05|5.000000e+00
</div>
@ -145,6 +157,7 @@ ml[:10]
<div class=result>
| user_id | movie_id | rating | time | user_id | movie_id | rating | time
|--------|---------|-------|----- |--------|---------|-------|-----
0|1|2|3.5|2005-04-02 23:53:47 0|1|2|3.5|2005-04-02 23:53:47
@ -157,6 +170,7 @@ ml[:10]
7|1|223|4.0|2005-04-02 23:46:13 7|1|223|4.0|2005-04-02 23:46:13
8|1|253|4.0|2005-04-02 23:35:40 8|1|253|4.0|2005-04-02 23:35:40
9|1|260|4.0|2005-04-02 23:33:46 9|1|260|4.0|2005-04-02 23:33:46
</div>
@ -171,8 +185,12 @@ max_user, max_movie, max_user * max_movie
<div class=result>
(138494, 131263, 18179137922) (138494, 131263, 18179137922)
</div>
Computing what percent we have of all 'possible' ratings (i.e. every single movie & every single user), this data is rather sparse: Computing what percent we have of all 'possible' ratings (i.e. every single movie & every single user), this data is rather sparse:
@ -182,8 +200,12 @@ Computing what percent we have of all 'possible' ratings (i.e. every single movi
print("%.2f%%" % (100 * ml.shape[0] / (max_user * max_movie))) print("%.2f%%" % (100 * ml.shape[0] / (max_user * max_movie)))
``` ```
<div class=result>
0.11% 0.11%
</div>
## 3.1. Aggregation ## 3.1. Aggregation
@ -218,6 +240,7 @@ movie_stats.sort_values("num_ratings", ascending=False)[:25]
<div class=result>
| movie_title | num_ratings | avg_rating | movie_id | | | | movie_title | num_ratings | avg_rating | movie_id | | |
|------------|------------|-----------|---------|-|-|- |------------|------------|-----------|---------|-|-|-
296|Pulp Fiction (1994)|67310.0|4.174231 296|Pulp Fiction (1994)|67310.0|4.174231
@ -245,6 +268,7 @@ movie_stats.sort_values("num_ratings", ascending=False)[:25]
608|Fargo (1996)|43272.0|4.112359 608|Fargo (1996)|43272.0|4.112359
47|Seven (a.k.a. Se7en) (1995)|43249.0|4.053493 47|Seven (a.k.a. Se7en) (1995)|43249.0|4.053493
380|True Lies (1994)|43159.0|3.491149 380|True Lies (1994)|43159.0|3.491149
</div>
@ -317,9 +341,13 @@ ml_mat_train
<div class=result>
<138494x131263 sparse matrix of type '<class 'numpy.float32'>' <138494x131263 sparse matrix of type '<class 'numpy.float32'>'
with 15000197 stored elements in Compressed Sparse Column format> with 15000197 stored elements in Compressed Sparse Column format>
</div>
To demonstrate that the matrix and dataframe have the same data: To demonstrate that the matrix and dataframe have the same data:
@ -333,6 +361,7 @@ ml_train[:10]
<div class=result>
| user_id | movie_id | rating | time | user_id | movie_id | rating | time
|--------|---------|-------|----- |--------|---------|-------|-----
13746918|94976|7371|4.5|2009-11-04 05:51:26 13746918|94976|7371|4.5|2009-11-04 05:51:26
@ -345,6 +374,7 @@ ml_train[:10]
15311014|105846|4226|4.5|2004-07-30 18:12:26 15311014|105846|4226|4.5|2004-07-30 18:12:26
8514776|58812|1285|4.0|2000-04-24 20:39:46 8514776|58812|1285|4.0|2000-04-24 20:39:46
3802643|25919|3275|2.5|2010-06-18 00:48:40 3802643|25919|3275|2.5|2010-06-18 00:48:40
</div>
@ -357,8 +387,12 @@ list(ml_train.iloc[:10].rating)
<div class=result>
[4.5, 3.0, 3.0, 4.5, 4.0, 2.5, 5.0, 4.5, 4.0, 2.5] [4.5, 3.0, 3.0, 4.5, 4.0, 2.5, 5.0, 4.5, 4.0, 2.5]
</div>
@ -371,8 +405,12 @@ movie_ids = list(ml_train.iloc[:10].movie_id)
<div class=result>
[4.5, 3.0, 3.0, 4.5, 4.0, 2.5, 5.0, 4.5, 4.0, 2.5] [4.5, 3.0, 3.0, 4.5, 4.0, 2.5, 5.0, 4.5, 4.0, 2.5]
</div>
Okay, enough of that; we can begin with some actual predictions. Okay, enough of that; we can begin with some actual predictions.
@ -445,6 +483,7 @@ names.merge(ml_train[ml_train.user_id == target_user], right_on="movie_id", left
<div class=result>
| movie_title | user_id | movie_id | rating | time | movie_title | user_id | movie_id | rating | time
|------------|--------|---------|-------|----- |------------|--------|---------|-------|-----
4229884|Jumanji (1995)|28812|2|5.0|1996-09-23 02:08:39 4229884|Jumanji (1995)|28812|2|5.0|1996-09-23 02:08:39
@ -458,6 +497,7 @@ names.merge(ml_train[ml_train.user_id == target_user], right_on="movie_id", left
4229957|Independence Day (a.k.a. ID4) (1996)|28812|780|5.0|1996-09-23 02:09:02 4229957|Independence Day (a.k.a. ID4) (1996)|28812|780|5.0|1996-09-23 02:09:02
4229959|Phenomenon (1996)|28812|802|5.0|1996-09-23 02:09:02 4229959|Phenomenon (1996)|28812|802|5.0|1996-09-23 02:09:02
4229960|Die Hard (1988)|28812|1036|5.0|1996-09-23 02:09:02 4229960|Die Hard (1988)|28812|1036|5.0|1996-09-23 02:09:02
</div>
@ -474,9 +514,11 @@ names[names.index == target_movie]
<div class=result>
| movie_title | movie_id | | movie_title | movie_id |
|------------|---------|- |------------|---------|-
586|Home Alone (1990) 586|Home Alone (1990)
</div>
@ -497,6 +539,7 @@ users_df
<div class=result>
| movie_id_x | user_id | rating_x | rating_y | movie_id_x | user_id | rating_x | rating_y
|-----------|--------|---------|--------- |-----------|--------|---------|---------
0|329|17593|3.0|4.0 0|329|17593|3.0|4.0
@ -510,6 +553,7 @@ users_df
522688|2|126271|3.0|4.0 522688|2|126271|3.0|4.0
522689|595|82760|2.0|4.0 522689|595|82760|2.0|4.0
522690|595|18306|4.5|5.0 522690|595|18306|4.5|5.0
</div>
@ -526,6 +570,7 @@ users_df
<div class=result>
| movie_id_x | user_id | rating_x | rating_y | rating_dev | movie_id_x | user_id | rating_x | rating_y | rating_dev
|-----------|--------|---------|---------|----------- |-----------|--------|---------|---------|-----------
0|329|17593|3.0|4.0|1.0 0|329|17593|3.0|4.0|1.0
@ -539,6 +584,7 @@ users_df
522688|2|126271|3.0|4.0|1.0 522688|2|126271|3.0|4.0|1.0
522689|595|82760|2.0|4.0|2.0 522689|595|82760|2.0|4.0|2.0
522690|595|18306|4.5|5.0|0.5 522690|595|18306|4.5|5.0|0.5
</div>
@ -556,6 +602,7 @@ names.join(rating_dev, how="inner").sort_values("rating_dev")
<div class=result>
| movie_title | rating_dev | movie_title | rating_dev
|------------|----------- |------------|-----------
318|Shawshank Redemption, The (1994)|-1.391784 318|Shawshank Redemption, The (1994)|-1.391784
@ -579,6 +626,7 @@ names.join(rating_dev, how="inner").sort_values("rating_dev")
173|Judge Dredd (1995)|0.518570 173|Judge Dredd (1995)|0.518570
19|Ace Ventura: When Nature Calls (1995)|0.530155 19|Ace Ventura: When Nature Calls (1995)|0.530155
160|Congo (1995)|0.559034 160|Congo (1995)|0.559034
</div>
@ -599,6 +647,7 @@ df.join(names, on="movie_id").sort_values("movie_title")
<div class=result>
| user_id | movie_id | rating | rating_adj | movie_title | user_id | movie_id | rating | rating_adj | movie_title
|--------|---------|-------|-----------|------------ |--------|---------|-------|-----------|------------
4229920|28812|344|3.0|3.141987|Ace Ventura: Pet Detective (1994) 4229920|28812|344|3.0|3.141987|Ace Ventura: Pet Detective (1994)
@ -622,6 +671,7 @@ df.join(names, on="movie_id").sort_values("movie_title")
4229892|28812|50|3.0|1.683520|Usual Suspects, The (1995) 4229892|28812|50|3.0|1.683520|Usual Suspects, The (1995)
4229903|28812|208|3.0|3.250881|Waterworld (1995) 4229903|28812|208|3.0|3.250881|Waterworld (1995)
4229919|28812|339|4.0|3.727966|While You Were Sleeping (1995) 4229919|28812|339|4.0|3.727966|While You Were Sleeping (1995)
</div>
@ -636,8 +686,12 @@ df["rating_adj"].mean()
<div class=result>
4.087520122528076 4.087520122528076
</div>
As mentioned above, we also happen to have the user's actual rating on *Home Alone* in the test set (i.e. we didn't train on it), so we can compare here: As mentioned above, we also happen to have the user's actual rating on *Home Alone* in the test set (i.e. we didn't train on it), so we can compare here:
@ -650,8 +704,12 @@ ml_test[(ml_test.user_id == target_user) & (ml_test.movie_id == target_movie)]["
<div class=result>
4.0 4.0
</div>
That's quite close - though that may just be luck. It's hard to say from one point. That's quite close - though that may just be luck. It's hard to say from one point.
@ -670,6 +728,7 @@ names.join(num_ratings, how="inner").sort_values("num_ratings")
<div class=result>
| movie_title | num_ratings | movie_title | num_ratings
|------------|------------ |------------|------------
802|Phenomenon (1996)|3147 802|Phenomenon (1996)|3147
@ -693,6 +752,7 @@ names.join(num_ratings, how="inner").sort_values("num_ratings")
593|Silence of the Lambs, The (1991)|12120 593|Silence of the Lambs, The (1991)|12120
480|Jurassic Park (1993)|13546 480|Jurassic Park (1993)|13546
356|Forrest Gump (1994)|13847 356|Forrest Gump (1994)|13847
</div>
@ -723,6 +783,7 @@ df
<div class=result>
| user_id | movie_id | rating | rating_adj | num_ratings | rating_weighted | user_id | movie_id | rating | rating_adj | num_ratings | rating_weighted
|--------|---------|-------|-----------|------------|---------------- |--------|---------|-------|-----------|------------|----------------
4229918|28812|329|4.0|3.767164|6365|23978.000326 4229918|28812|329|4.0|3.767164|6365|23978.000326
@ -746,6 +807,7 @@ df
4229912|28812|296|4.0|2.883755|11893|34296.500678 4229912|28812|296|4.0|2.883755|11893|34296.500678
4229884|28812|2|5.0|4.954595|7422|36773.001211 4229884|28812|2|5.0|4.954595|7422|36773.001211
4229953|28812|595|4.0|3.515051|9036|31761.999825 4229953|28812|595|4.0|3.515051|9036|31761.999825
</div>
@ -758,8 +820,12 @@ df["rating_weighted"].sum() / df["num_ratings"].sum()
<div class=result>
4.02968199025023 4.02968199025023
</div>
It changes the answer, but only very slightly. It changes the answer, but only very slightly.
@ -958,8 +1024,12 @@ To show that it actually gives the same result as above, and that the approximat
<div class=result>
(4.0875210502743862, 4.0875210502743862) (4.0875210502743862, 4.0875210502743862)
</div>
This computes training error on a small part (1%) of the data, since doing it over the entire thing would be horrendously slow: This computes training error on a small part (1%) of the data, since doing it over the entire thing would be horrendously slow:
@ -1036,9 +1106,13 @@ print("Training error: MAE={:.3f}, RMSE={:.3f}".format(err_mae_train, err_rms_t
print("Testing error: MAE={:.3f}, RMSE={:.3f}".format(err_mae_test, err_rms_test)) print("Testing error: MAE={:.3f}, RMSE={:.3f}".format(err_mae_test, err_rms_test))
``` ```
<div class=result>
Training error: MAE=0.640, RMSE=0.834 Training error: MAE=0.640, RMSE=0.834
Testing error: MAE=0.657, RMSE=0.856 Testing error: MAE=0.657, RMSE=0.856
</div>
# 6. "SVD" algorithm # 6. "SVD" algorithm
@ -1270,6 +1344,8 @@ svd40 = SVDModel(max_movie, max_user, ml["rating"].mean(), num_factors=num_facto
svd40.train(movies_train, users_train, ratings_train, epoch_callback=at_epoch) svd40.train(movies_train, users_train, ratings_train, epoch_callback=at_epoch)
``` ```
<div class=result>
6982/s 8928/s 10378/s 12877/s 15290/s 11574/s 13230/s 6982/s 8928/s 10378/s 12877/s 15290/s 11574/s 13230/s
Epoch 01/20; Training: MAE=0.674 RMSE=0.874, Testing: MAE=0.677 RMSE=0.879 Epoch 01/20; Training: MAE=0.674 RMSE=0.874, Testing: MAE=0.677 RMSE=0.879
4700/s 8568/s 7968/s 10415/s 12948/s 13004/s 13892/s 4700/s 8568/s 7968/s 10415/s 12948/s 13004/s 13892/s
@ -1311,6 +1387,8 @@ svd40.train(movies_train, users_train, ratings_train, epoch_callback=at_epoch)
52078/s 18671/s 9292/s 11493/s 12515/s 11760/s 13039/s 52078/s 18671/s 9292/s 11493/s 12515/s 11760/s 13039/s
Epoch 20/20; Training: MAE=0.549 RMSE=0.717, Testing: MAE=0.600 RMSE=0.787 Epoch 20/20; Training: MAE=0.549 RMSE=0.717, Testing: MAE=0.600 RMSE=0.787
</div>
```python ```python
@ -1330,6 +1408,8 @@ svd4 = SVDModel(max_movie, max_user, ml["rating"].mean(), 4)
svd4.train(ml_train["movie_id"].values, ml_train["user_id"].values, ml_train["rating"].values, epoch_callback=at_epoch) svd4.train(ml_train["movie_id"].values, ml_train["user_id"].values, ml_train["rating"].values, epoch_callback=at_epoch)
``` ```
<div class=result>
48199/s 33520/s 16937/s 13842/s 13607/s 15574/s 15431/s 48199/s 33520/s 16937/s 13842/s 13607/s 15574/s 15431/s
Epoch 01/20; Training: MAE=0.674 RMSE=0.875, Testing: MAE=0.677 RMSE=0.878 Epoch 01/20; Training: MAE=0.674 RMSE=0.875, Testing: MAE=0.677 RMSE=0.878
25537/s 28976/s 36900/s 32309/s 10572/s 11244/s 12795/s 25537/s 28976/s 36900/s 32309/s 10572/s 11244/s 12795/s
@ -1371,6 +1451,8 @@ svd4.train(ml_train["movie_id"].values, ml_train["user_id"].values, ml_train["ra
6090/s 11341/s 15532/s 18298/s 17158/s 14908/s 16898/s 6090/s 11341/s 15532/s 18298/s 17158/s 14908/s 16898/s
Epoch 20/20; Training: MAE=0.599 RMSE=0.783, Testing: MAE=0.618 RMSE=0.809 Epoch 20/20; Training: MAE=0.599 RMSE=0.783, Testing: MAE=0.618 RMSE=0.809
</div>
To limit the data, we can use just the top movies (by number of ratings): To limit the data, we can use just the top movies (by number of ratings):
@ -1400,7 +1482,7 @@ plt.show()
``` ```
![png](../images/output_94_0.png) ![png](../images/2018-04-08-recommenders/output_94_0.png)
And here are the other two: And here are the other two:
@ -1416,7 +1498,7 @@ plt.show()
``` ```
![png](../images/output_96_0.png) ![png](../images/2018-04-08-recommenders/output_96_0.png)
Below is another way of visualizing. Neither the code nor the result are very pretty, but it divides the entire latent space into a 2D grid, identifies the top few movies (ranked by number of ratings) in each grid square, and prints the resultant grid. Below is another way of visualizing. Neither the code nor the result are very pretty, but it divides the entire latent space into a 2D grid, identifies the top few movies (ranked by number of ratings) in each grid square, and prints the resultant grid.
@ -1479,6 +1561,7 @@ latent_factor_grid(svd4.q[:2,:])
<div class=result>
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
|--|--|--|--|--|--|--|--|--|--|---|---|---|---|---|--- |--|--|--|--|--|--|--|--|--|--|---|---|---|---|---|---
0|||||||||||||||| 0||||||||||||||||
@ -1497,6 +1580,7 @@ latent_factor_grid(svd4.q[:2,:])
13||||||||Sound of Music; Spy Kids 2: The Island of Lost...|Bring It On; Legally Blonde|Fly Away Home; Parent Trap|Sense and Sensibility; Sex and the City||||| 13||||||||Sound of Music; Spy Kids 2: The Island of Lost...|Bring It On; Legally Blonde|Fly Away Home; Parent Trap|Sense and Sensibility; Sex and the City|||||
14|||||||Babe; Babe: Pig in the City||||Twilight||||| 14|||||||Babe; Babe: Pig in the City||||Twilight|||||
15|||||||||||||||| 15||||||||||||||||
</div>
@ -1514,6 +1598,7 @@ latent_factor_grid(svd4.q[2:,:])
<div class=result>
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
|--|--|--|--|--|--|--|--|--|--|---|---|---|---|---|--- |--|--|--|--|--|--|--|--|--|--|---|---|---|---|---|---
0|||||||||||||||| 0||||||||||||||||
@ -1532,6 +1617,7 @@ latent_factor_grid(svd4.q[2:,:])
13||||||Nightmare on Elm Street 4: The Dream Master; F...|Wes Craven's New Nightmare (Nightmare on Elm S...|Friday the 13th; Exorcist III|Candyman; Texas Chainsaw Massacre 2|Mars Attacks!; Halloween|Evil Dead II (Dead by Dawn); Re-Animator|Night of the Living Dead; Dead Alive (Braindead)||Eraserhead|| 13||||||Nightmare on Elm Street 4: The Dream Master; F...|Wes Craven's New Nightmare (Nightmare on Elm S...|Friday the 13th; Exorcist III|Candyman; Texas Chainsaw Massacre 2|Mars Attacks!; Halloween|Evil Dead II (Dead by Dawn); Re-Animator|Night of the Living Dead; Dead Alive (Braindead)||Eraserhead||
14|||||||Nightmare on Elm Street 3: Dream Warriors; Fre...|Hellbound: Hellraiser II|Nightmare on Elm Street||||||| 14|||||||Nightmare on Elm Street 3: Dream Warriors; Fre...|Hellbound: Hellraiser II|Nightmare on Elm Street|||||||
15|||||||Bride of Chucky (Child's Play 4)||||Texas Chainsaw Massacre||||| 15|||||||Bride of Chucky (Child's Play 4)||||Texas Chainsaw Massacre|||||
</div>
@ -1553,6 +1639,7 @@ bias.iloc[:10]
<div class=result>
| movie_title | num_ratings | avg_rating | bias | movie_id | | | | | movie_title | num_ratings | avg_rating | bias | movie_id | | | |
|------------|------------|-----------|-----|---------|-|-|-|- |------------|------------|-----------|-----|---------|-|-|-|-
318|Shawshank Redemption, The (1994)|63366.0|4.446990|1.015911 318|Shawshank Redemption, The (1994)|63366.0|4.446990|1.015911
@ -1565,6 +1652,7 @@ bias.iloc[:10]
50|Usual Suspects, The (1995)|47006.0|4.334372|0.910651 50|Usual Suspects, The (1995)|47006.0|4.334372|0.910651
102217|Bill Hicks: Revelations (1993)|50.0|3.990000|0.900622 102217|Bill Hicks: Revelations (1993)|50.0|3.990000|0.900622
527|Schindler's List (1993)|50054.0|4.310175|0.898633 527|Schindler's List (1993)|50054.0|4.310175|0.898633
</div>
@ -1578,6 +1666,7 @@ bias.iloc[:-10:-1]
<div class=result>
| movie_title | num_ratings | avg_rating | bias | movie_id | | | | | movie_title | num_ratings | avg_rating | bias | movie_id | | | |
|------------|------------|-----------|-----|---------|-|-|-|- |------------|------------|-----------|-----|---------|-|-|-|-
8859|SuperBabies: Baby Geniuses 2 (2004)|209.0|0.837321|-2.377202 8859|SuperBabies: Baby Geniuses 2 (2004)|209.0|0.837321|-2.377202
@ -1589,6 +1678,7 @@ bias.iloc[:-10:-1]
4775|Glitter (2001)|685.0|1.124088|-2.047287 4775|Glitter (2001)|685.0|1.124088|-2.047287
31698|Son of the Mask (2005)|467.0|1.252677|-2.022763 31698|Son of the Mask (2005)|467.0|1.252677|-2.022763
5739|Faces of Death 6 (1996)|174.0|1.261494|-2.004086 5739|Faces of Death 6 (1996)|174.0|1.261494|-2.004086
</div>
@ -1636,6 +1726,7 @@ pd.DataFrame.from_records(
<div class=result>
| Library | Algorithm | MAE (test) | RMSE (test) | Library | Algorithm | MAE (test) | RMSE (test)
|--------|----------|-----------|------------ |--------|----------|-----------|------------
0||Slope One|0.656514|0.856294 0||Slope One|0.656514|0.856294
@ -1643,6 +1734,7 @@ pd.DataFrame.from_records(
2|Surprise|Random|1.144775|1.433753 2|Surprise|Random|1.144775|1.433753
3|Surprise|Slope One|0.704730|0.923331 3|Surprise|Slope One|0.704730|0.923331
4|Surprise|SVD|0.694890|0.900350 4|Surprise|SVD|0.694890|0.900350
</div>

35
site.hs
View File

@ -1,7 +1,7 @@
{-| {-|
Module : Main Module : Main
Description : Static HTML generation for my blog Description : Static HTML generation for my blog
Copyright : (c) 2016 Chris Hodapp Copyright : (c) 2019 Chris Hodapp
License : ?? License : ??
Stability : experimental Stability : experimental
Portability : POSIX Portability : POSIX
@ -33,7 +33,7 @@ pandocMathCompiler =
, Ext_tex_math_double_backslash , Ext_tex_math_double_backslash
, Ext_latex_macros] , Ext_latex_macros]
defaultExtensions = writerExtensions defaultHakyllWriterOptions defaultExtensions = writerExtensions defaultHakyllWriterOptions
newExtensions = foldr S.insert defaultExtensions mathExtensions newExtensions = foldr enableExtension defaultExtensions mathExtensions
writerOptions = defaultHakyllWriterOptions { writerOptions = defaultHakyllWriterOptions {
writerExtensions = newExtensions, writerExtensions = newExtensions,
writerHTMLMathMethod = MathJax "" writerHTMLMathMethod = MathJax ""
@ -49,15 +49,7 @@ main = do
tags <- buildTags "posts/*" (fromCapture "tags/*.html") tags <- buildTags "posts/*" (fromCapture "tags/*.html")
let postCtxTags = postCtxWithTags tags let postCtxTags = postCtxWithTags tags
match "images/**" $ do match ("images/**" .||. "assets/**" .||. "assets_external/**" .||. "css/*" .||. "js/**") $ do
route idRoute
compile copyFileCompiler
match "assets/**" $ do
route idRoute
compile copyFileCompiler
match "assets_external/**" $ do
route idRoute route idRoute
compile copyFileCompiler compile copyFileCompiler
@ -65,14 +57,6 @@ main = do
route $ customRoute $ takeFileName . toFilePath route $ customRoute $ takeFileName . toFilePath
compile copyFileCompiler compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
match "js/**" $ do
route idRoute
compile copyFileCompiler
match "pages/*" $ do match "pages/*" $ do
route $ setExtension "html" route $ setExtension "html"
compile $ pandocMathCompiler compile $ pandocMathCompiler
@ -83,8 +67,9 @@ main = do
route idRoute route idRoute
compile copyFileCompiler compile copyFileCompiler
-- We want .lhs files to be directly accessible, so copy them through unmodified. -- We want .lhs files to be directly accessible, so copy them
match "posts/*.lhs" $ version "raw" $ do -- through unmodified.
match ("posts/*.lhs" .||. "drafts/*.lhs") $ version "raw" $ do
route idRoute route idRoute
compile $ getResourceBody >>= relativizeUrls compile $ getResourceBody >>= relativizeUrls
@ -97,11 +82,6 @@ main = do
>>= loadAndApplyTemplate "templates/default.html" postCtxTags >>= loadAndApplyTemplate "templates/default.html" postCtxTags
>>= relativizeUrls >>= relativizeUrls
-- We want .lhs files to be directly accessible, so copy them through unmodified.
match "drafts/*.lhs" $ version "raw" $ do
route idRoute
compile $ getResourceBody >>= relativizeUrls
match "drafts/*" $ do match "drafts/*" $ do
route $ setExtension "html" route $ setExtension "html"
compile $ pandocMathCompiler compile $ pandocMathCompiler
@ -131,6 +111,9 @@ main = do
listField "posts" postCtxTags (return posts) `mappend` listField "posts" postCtxTags (return posts) `mappend`
constField "title" "Home" `mappend` constField "title" "Home" `mappend`
defaultContext defaultContext
-- so... "posts" is a list field which is added
-- into indexCtx with contents derived from
-- 'posts' above.
getResourceBody getResourceBody
>>= applyAsTemplate indexCtx >>= applyAsTemplate indexCtx

View File

@ -1,7 +1,9 @@
packages: packages:
- ./ - ./
resolver: lts-8.3 resolver: lts-12.26
nix: nix:
enable: true enable: true
packages: [zlib] packages: [zlib]
extra-deps: