diff --git a/Dates/.gitignore b/Dates/.gitignore new file mode 100644 index 0000000..b184dd6 --- /dev/null +++ b/Dates/.gitignore @@ -0,0 +1 @@ +*.apkg diff --git a/Dates/1900s.ods b/Dates/1900s.ods new file mode 100644 index 0000000..01d0de9 Binary files /dev/null and b/Dates/1900s.ods differ diff --git a/Dates/Date Flashcards.ipynb b/Dates/Date Flashcards.ipynb new file mode 100644 index 0000000..6ab87c9 --- /dev/null +++ b/Dates/Date Flashcards.ipynb @@ -0,0 +1,250 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate date flashcards for Anki\n", + "https://github.com/kerrickstaley/genanki" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import date" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "522800796" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import random\n", + "\n", + "def get_id():\n", + " return random.randrange(1<<32)\n", + "get_id()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import genanki\n", + "\n", + "front_back = genanki.Model(\n", + " get_id(),\n", + " 'Front Back Model',\n", + " fields=[\n", + " {'name': 'Date'},\n", + " {'name': 'Day'},\n", + " ],\n", + " templates=[\n", + " {\n", + " 'name': 'Date Card',\n", + " 'qfmt': '{{Date}}',\n", + " 'afmt': '{{Day}}',\n", + " },\n", + " ]\n", + ")\n", + "\n", + "def make_deck(cards, name):\n", + " # Cards is a list of fields\n", + " deck = genanki.Deck(get_id(), name)\n", + " \n", + " for card in cards:\n", + " note = genanki.Note(\n", + " model=front_back,\n", + " fields=card\n", + " )\n", + " deck.add_note(note)\n", + " \n", + " return deck\n", + "\n", + "def write_decks(decks, name='dates'):\n", + " genanki.Package(decks).write_to_file(f'{name}.apkg')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "date(2019, 8, 28).weekday()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import calendar\n", + "\n", + "def make_august_weekday_deck(days_string):\n", + " wkday_map = {\n", + " 'M': 0,\n", + " 'T': 1,\n", + " 'W': 2,\n", + " 'R': 3, \n", + " 'F': 4, \n", + " 'S': 5,\n", + " 'U': 6\n", + " }\n", + " \n", + " days = sorted([wkday_map[day] for day in days_string])\n", + " \n", + " names = [calendar.day_abbr[i] for i in days]\n", + " name = 'August, 2019 (' + ', '.join(names) + ')'\n", + " \n", + " cards = []\n", + " for i in range(31):\n", + " day = date(2019, 8, i+1)\n", + " if day.weekday() not in days:\n", + " continue\n", + " date_string = day.strftime('%B %d, %Y')\n", + " day_string = day.strftime('%A')\n", + " cards.append([date_string, day_string])\n", + " \n", + " return make_deck(cards, name)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def make_august_decks():\n", + " \n", + " schedule = 'MRSWUTF'\n", + " \n", + " decks = []\n", + " \n", + " for i in range(1, len(schedule)):\n", + " decks.append(make_august_weekday_deck(schedule[0:i+1]))\n", + " \n", + " write_decks(decks, 'August')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "make_august_decks()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "from calendar import monthrange\n", + "def make_month_deck(month, year=2019):\n", + " \n", + " name = date(year, month, 1).strftime('%B, %Y')\n", + " \n", + " cards = []\n", + " for i in range(monthrange(2019, month)[1]):\n", + " day = date(2019, month, i+1)\n", + " date_string = day.strftime('%B %d, %Y')\n", + " day_string = day.strftime('%A')\n", + " cards.append([date_string, day_string])\n", + " \n", + " return make_deck(cards, name)\n", + "\n", + "def make_months_deck(months, year=2019):\n", + " \n", + " name = ', '.join([date(year, month, 1).strftime('%B') for month in months]) + date(year, 1, 1).strftime(' - %Y')\n", + " \n", + " cards = []\n", + " for month in months:\n", + " for i in range(monthrange(2019, month)[1]):\n", + " day = date(2019, month, i+1)\n", + " date_string = day.strftime('%B %d, %Y')\n", + " day_string = day.strftime('%A')\n", + " cards.append([date_string, day_string])\n", + " \n", + " return make_deck(cards, name)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "write_decks([make_month_deck(9)], 'September')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "write_decks([make_months_deck([8, 9])], 'Aug,Sept')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Dates/Double Day Flashcards.ipynb b/Dates/Double Day Flashcards.ipynb new file mode 100644 index 0000000..ed7cfe0 --- /dev/null +++ b/Dates/Double Day Flashcards.ipynb @@ -0,0 +1,304 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate date flashcards for Anki\n", + "https://github.com/kerrickstaley/genanki" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from datetime import date" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2263097491" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import random\n", + "\n", + "def get_id():\n", + " return random.randrange(1<<32)\n", + "get_id()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "import genanki\n", + "\n", + "# Show any date from month with day\n", + "# Show other date from month with blank day\n", + "\n", + "dday = genanki.Model(\n", + " get_id(),\n", + " 'Double Day',\n", + " fields=[\n", + " {'name': 'Date1'},\n", + " {'name': 'Day1'},\n", + " {'name': 'Date2'},\n", + " {'name': 'Day2'},\n", + " ],\n", + " templates=[\n", + " {\n", + " 'name': 'Double Day Card',\n", + " 'qfmt': \"\"\"\n", + "
\n", + "
\n", + "\n", + "
\n", + "
{{Date1}}
\n", + "
{{Day1}}
\n", + " \n", + "
\n", + "
\n", + "\n", + "
\n", + "
{{Date2}}
\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\"\"\",\n", + " 'afmt': \"\"\"\n", + "
\n", + "
\n", + "\n", + "
\n", + "
{{Date1}}
\n", + "
{{Day1}}
\n", + " \n", + "
\n", + "
\n", + "\n", + "
\n", + "
{{Date2}}
\n", + "
{{Day2}}
\n", + "
\n", + "\n", + "
\n", + "
\"\"\"\n", + " },\n", + " ]\n", + ")\n", + "\n", + "def make_deck(cards, name):\n", + " # Cards is a list of fields\n", + " deck = genanki.Deck(get_id(), name)\n", + " \n", + " for card in cards:\n", + " note = genanki.Note(\n", + " model=dday,\n", + " fields=card\n", + " )\n", + " deck.add_note(note)\n", + " \n", + " return deck\n", + "\n", + "def write_decks(decks, name='dates'):\n", + " genanki.Package(decks).write_to_file(f'{name}.apkg')" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def write_deck(deck):\n", + " genanki.Package([deck]).write_to_file(f'doubledates.apkg')\n", + "\n", + "write_deck(make_double_deck())" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "date(2019, 8, 28).weekday()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import random\n", + "from datetime import datetime, timedelta\n", + "from calendar import monthrange, month_name\n", + "\n", + "def make_double_deck(n=11000):\n", + " year = 2019\n", + " \n", + " cards = []\n", + " \n", + " for i in range(n):\n", + " month = random.choice(range(12)) + 1\n", + " max_day = monthrange(year, month)[1]\n", + " day = random.choice(range(max_day)) + 1\n", + " \n", + " reference_day = day\n", + " while day == reference_day:\n", + " reference_day = random.choice(range(max_day)) + 1\n", + " \n", + " month_str = month_name[month]\n", + " reference_day_str = date(year, month, reference_day).strftime('%A')\n", + " day_str = date(year, month, day).strftime('%A')\n", + " cards.append((\n", + " f\"{month_str} {reference_day}, {year}\",\n", + " f\"{reference_day_str}\",\n", + " f\"{month_str} {day}, {year}\",\n", + " f\"{day_str}\",\n", + " \n", + " ))\n", + " \n", + " return make_deck(cards, \"Doubles\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Thursday'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "date(2019, 9, 26).strftime(\"%A\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "write_decks([make_month_deck(9)], 'September')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "write_decks([make_double_deck([i + 1 for i in range (12)])])" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "4\n", + "0\n", + "2\n", + "5\n", + "0\n", + "3\n", + "6\n", + "1\n", + "4\n", + "6\n" + ] + } + ], + "source": [ + "from datetime import date\n", + "for i in range(12):\n", + " a = date(2019, i + 1, 1)\n", + " print(a.weekday())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Dates/Exploration.ipynb b/Dates/Exploration.ipynb new file mode 100644 index 0000000..24084a8 --- /dev/null +++ b/Dates/Exploration.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "from calendar import day_abbr" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "datetime(2099, 1, 4).weekday()" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 28, 56, 84]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[i * 28 for i in range(4)]" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "73\n", + "15\n", + "76\n", + "71\n", + "26\n", + "5\n", + "41\n", + "17\n", + "13\n", + "75\n", + "92\n", + "91\n", + "9\n", + "52\n", + "57\n", + "67\n", + "32\n", + "47\n", + "82\n", + "89\n" + ] + } + ], + "source": [ + "import random\n", + "for i in range(20):\n", + " print(random.randint(0, 99))" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "5\n", + "5\n", + "5\n", + "5\n", + "0\n", + "3\n", + "1\n", + "3\n", + "3\n", + "4\n", + "2\n", + "5\n", + "3\n", + "2\n", + "0\n", + "6\n", + "3\n", + "5\n", + "0\n" + ] + } + ], + "source": [ + "x = [\n", + " 73,\n", + " 15,\n", + " 76,\n", + " 71,\n", + " 26,\n", + " 5,\n", + " 41,\n", + " 17,\n", + " 13,\n", + " 75,\n", + " 92,\n", + " 91,\n", + " 9,\n", + " 52,\n", + " 57,\n", + " 67,\n", + " 32,\n", + " 47,\n", + " 82,\n", + " 89\n", + "]\n", + "for y in x:\n", + " print(datetime(2000 + y, 7, 11).weekday())" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2000: Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2001: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2002: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2003: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2004: Thu Sun Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2005: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2006: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2007: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2008: Tue Fri Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2009: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2010: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2011: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2012: Sun Wed Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2013: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2014: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2015: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2016: Fri Mon Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2017: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2018: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2019: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2020: Wed Sat Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2021: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2022: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2023: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2024: Mon Thu Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2025: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2026: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2027: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2028: Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2029: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2030: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2031: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2032: Thu Sun Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2033: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2034: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2035: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2036: Tue Fri Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2037: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2038: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2039: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2040: Sun Wed Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2041: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2042: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2043: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2044: Fri Mon Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2045: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2046: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2047: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2048: Wed Sat Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2049: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2050: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2051: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2052: Mon Thu Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2053: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2054: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2055: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2056: Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2057: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2058: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2059: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2060: Thu Sun Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2061: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2062: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2063: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2064: Tue Fri Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2065: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2066: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2067: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2068: Sun Wed Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2069: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2070: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2071: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2072: Fri Mon Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2073: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2074: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2075: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2076: Wed Sat Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2077: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2078: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2079: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2080: Mon Thu Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2081: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2082: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2083: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2084: Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2085: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2086: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2087: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2088: Thu Sun Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2089: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2090: Sun Wed Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "2091: Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2092: Tue Fri Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2093: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n", + "2094: Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "2095: Sat Tue Tue Fri Sun Wed Fri Mon Thu Sat Tue Thu \n", + "2096: Sun Wed Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "2097: Tue Fri Fri Mon Wed Sat Mon Thu Sun Tue Fri Sun \n", + "2098: Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "2099: Thu Sun Sun Wed Fri Mon Wed Sat Tue Thu Sun Tue \n" + ] + } + ], + "source": [ + "for year in range(2000, 2100):\n", + " line = f\"{year}: \"\n", + " for month in range(1, 13):\n", + " line += day_abbr[datetime(year, month, 1).weekday()] + ' '\n", + " print(line)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n", + "Fri Mon Mon Thu Sat Tue Thu Sun Wed Fri Mon Wed \n", + "Wed Sat Sat Tue Thu Sun Tue Fri Mon Wed Sat Mon \n", + "Mon Thu Thu Sun Tue Fri Sun Wed Sat Mon Thu Sat \n", + "Sat Tue Wed Sat Mon Thu Sat Tue Fri Sun Wed Fri \n" + ] + } + ], + "source": [ + "for year in range(1000, 2401, 100):\n", + " line = \"\"\n", + " for month in range(1, 13):\n", + " line += day_abbr[datetime(year, month, 1).weekday()] + ' '\n", + " print(line)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Dates/Exploration.ods b/Dates/Exploration.ods new file mode 100644 index 0000000..577c072 Binary files /dev/null and b/Dates/Exploration.ods differ diff --git a/Dates/Machine Learning.ipynb b/Dates/Machine Learning.ipynb new file mode 100644 index 0000000..b4d02a1 --- /dev/null +++ b/Dates/Machine Learning.ipynb @@ -0,0 +1,708 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "from datetime import datetime, date, timedelta\n", + "import random" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def rand_date(start=date(1400, 1, 1), end=date(2400, 1, 1)):\n", + " diff = end - start\n", + " return start + random.random() * diff" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def convert_to_vector(xdate):\n", + " yr1 = xdate.year // 1000\n", + " yr2 = (xdate.year // 100) % 10\n", + " yr3 = (xdate.year // 10) % 10\n", + " yr4 = (xdate.year) % 10\n", + " \n", + " month = xdate.month\n", + " \n", + " day1 = xdate.day // 10\n", + " day2 = xdate.day % 10\n", + " \n", + " weekday = xdate.weekday()\n", + " \n", + " to_encode = [\n", + " (yr1, 10),\n", + " (yr2, 10),\n", + " (yr3, 10),\n", + " (yr4, 10),\n", + " (month, 12),\n", + " (day1, 10),\n", + " (day2, 10)\n", + " ]\n", + " \n", + " xs = []\n", + " for val, num_vals in to_encode:\n", + " one_hot = np.zeros(num_vals)\n", + " one_hot[val-1] = 1\n", + " xs.append(one_hot)\n", + " \n", + " x = np.concatenate(xs)\n", + " \n", + " y = np.zeros(7)\n", + " y[weekday] = 1\n", + " return x, y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Encoding: One-hot, separate integers\n", + "\n", + "Training: Month, year, other years, other decades\n", + "\n", + "Raw\n", + "\n", + "Start small, build up\n", + "\n", + "One month, same month plus another, keep adding months until a year, then add new years\n", + "One month, add a month, add a year, add several month, add several years, add decades\n", + "Start without leap years, then include leap years\n", + "\n", + "Whole idea is to go simple and complex\n", + "Introduce new concepts before past concepts are solidified\n", + "Don't want to confuse things - easily possible\n", + "\n", + "Simplest would be a single month in non leap-year\n", + "When introducing leap years, do half leap years and half non-leap years\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + } + ], + "source": [ + "from keras.models import Sequential\n", + "from keras.layers import Dense\n", + "from keras.callbacks import Callback\n", + "from keras import backend as K" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "model = Sequential()\n", + "model.add(Dense(100, input_shape=(10*6 + 12,), activation='tanh'))\n", + "model.add(Dense(100, activation='tanh'))\n", + "model.add(Dense(100, activation='tanh'))\n", + "model.add(Dense(7, activation='softmax'))\n", + "\n", + "model.compile('adam', 'categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + "def reset_model():\n", + " global model\n", + " session = K.get_session()\n", + " for layer in model.layers: \n", + " if hasattr(layer, 'kernel_initializer'):\n", + " layer.kernel.initializer.run(session=session)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_random(batch_size):\n", + " dates = []\n", + " xs = []\n", + " ys = []\n", + " for i in range(batch_size):\n", + " rdate = rand_date()\n", + " x, y = convert_to_vector(rdate)\n", + " dates.append(rdate)\n", + " xs.append(x)\n", + " ys.append(y)\n", + "\n", + " xs = np.array(xs)\n", + " ys = np.array(ys)\n", + " return xs, ys\n", + "\n", + "\n", + "def get_range_gen(start_date, end_date):\n", + " def generate_range(batch_size):\n", + " dates = []\n", + " xs = []\n", + " ys = []\n", + " for i in range(batch_size):\n", + " rdate = rand_date(start_date, end_date)\n", + " x, y = convert_to_vector(rdate)\n", + " dates.append(rdate)\n", + " xs.append(x)\n", + " ys.append(y)\n", + "\n", + " xs = np.array(xs)\n", + " ys = np.array(ys)\n", + " return xs, ys\n", + " return generate_range\n", + "\n", + "\n", + "def get_month_gen(year, month):\n", + " start = date(year, month, 1)\n", + " if month == 12:\n", + " end = date(year + 1, 1, 1)\n", + " else:\n", + " end = date(year, month + 1, 1)\n", + " return get_range_generator(start, end)\n", + "\n", + "\n", + "def combine_gens(generators, p=None):\n", + " if p is None:\n", + " p = [1/len(generators)] * len(generators)\n", + " \n", + " def generate(batch_size):\n", + " generator = np.random.choice(generators, p=p)\n", + " return generator(batch_size)\n", + " \n", + " return generate\n", + "\n", + "\n", + "def get_months_gen(year, months, p=None):\n", + " gens = []\n", + " for month in months:\n", + " gens.append(get_month_generator(year, month))\n", + " return combine_generators(gens, p)\n", + "\n", + "\n", + "def get_year_gen(year):\n", + " return get_range_generator(date(year, 1, 1), date(year+1, 1, 1))\n", + "\n", + "\n", + "def get_years_gen(start_year, end_year):\n", + " return get_range_generator(date(start_year, 1, 1), date(end_year + 1, 1, 1))\n", + "\n", + "\n", + "def get_years_gen_p(years, p=None):\n", + " gens = []\n", + " for year in years:\n", + " gens.append(get_year_generator(year))\n", + " return combine_generators(years, p)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import deque" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "def train_until_acc(model, data_gen, desired_acc, output=True, limit=1000000):\n", + " running_acc = 0\n", + " num_samples = 0\n", + " batch_size = 32\n", + " accs = deque(maxlen=10)\n", + " accs.append(desired_acc-0.01) # so we don't get the divide by zero error\n", + " \n", + " batch_num = 0\n", + " while sum(accs)/len(accs) < desired_acc:\n", + " xs, ys = data_gen(batch_size)\n", + " loss, acc = model.train_on_batch(xs, ys)\n", + " accs.append(acc)\n", + " num_samples += batch_size\n", + " batch_num += 1\n", + " if batch_num % 100 == 0:\n", + " print(\"Minibatch\", batch_num, sum(accs)/len(accs))\n", + " if num_samples > limit: # 1 mil by default\n", + " break\n", + " return num_samples\n", + "\n", + "\n", + "def run_schedule(schedule):\n", + " reset_model()\n", + " \n", + " total_samples = 0\n", + " for name, data_gen, accuracy in schedule:\n", + " num_samples = train_until_acc(model, data_gen, accuracy)\n", + " total_samples += num_samples\n", + " print('Trained {} in {} samples'.format(name, num_samples))\n", + " print('Training complete after {} samples'.format(total_samples))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.special import softmax\n", + "\n", + "def get_schedule_generator(x):\n", + " class P:\n", + " def __init__(self, x):\n", + " self.x = x\n", + " def __getitem__(self, key):\n", + " x.add_constraints()\n", + " return softmax(x[key])\n", + " \n", + " x = X(x)\n", + " p = P(x)\n", + " \n", + " schedule = [\n", + " ('Aug', get_month_generator(2019, 8), 0.99)\n", + " ]\n", + " class StagedValue:\n", + " def __init__(self, num):\n", + " self.num = num\n", + " class Stager:\n", + " def __init__(self):\n", + " self.total = 0\n", + " self.constraints = []\n", + " def __getitem__(self, key):\n", + " self.total += key\n", + " new_constraints = None # TODO Implement new constraints\n", + " self.constraints.append(new_constraints)\n", + " return StagedValue(key)\n", + " \n", + " # TODO How do I get this for multiple situations\n", + " schedule = [ # Have a schedule generator. Maybe iterate through after staging to activate\n", + " ('Aug', get_month_generator(2019, 8), 0.99),\n", + " ('Sep', get_months_generator(2019, [8, 9], p=p[2]), 0.99),\n", + " ('All', get_month_generator(2019, [8, 9]), 0.99)\n", + " ]\n", + " \n", + " # need to create function that accepts the right number of parameters and stuff\n", + " # use sparse matrix to represent constraints\n", + " class X:\n", + " def __init__(self, x):\n", + " self.x = x\n", + " self.current = 0\n", + " def __getitem__(self, key):\n", + " values = self.x[self.current: self.current+key]\n", + " self.current += key\n", + " return values\n", + " def __len__(self):\n", + " return self.current\n", + " \n", + " def get_schedule(x):\n", + " x = X(x)\n", + " processed_schedule = []\n", + " for name, func, params, probability in schedule:\n", + " # process into actual schedule\n", + " new_params = []\n", + " for param in params:\n", + " if type(param) is StagedValue:\n", + " new_params.append(x[param.num])\n", + " else:\n", + " new_params.append(param)\n", + " schedule_item = (name, func(*params), probability)\n", + " processed_schedule.append(schedule_item)\n", + " return processed_schedule\n", + " \n", + " return get_schedule, constraints, x0\n", + " \n", + " \n", + " \n", + " schedule = [ # Have a schedule generator. Maybe iterate through after staging to activate\n", + " ('Aug', get_month_generator(2019, 8), 0.99),\n", + " ('Sep', get_months_generator(2019, [8, 9], p=p[2]), x[1]),\n", + " ('Oct', get_month_generator(2019, [8, 9, 10], p=p[3]), x[1]),\n", + " ('Oct', get_month_generator(2019, [8, 9, 10]), 0.99)\n", + " ]\n", + " \n", + " schedule = [\n", + " ('2019-1', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-2', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-3', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-4', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-5', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-6', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-7', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-8', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-9', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-10', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-11', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019-12', get_months_gen(2019, range(1, 13), p=x[12]), x[1]),\n", + " ('2019', get_year_generator(2019), 0.99),\n", + "# ('2020', get_years_gen(2019, 2020), x[1]),\n", + "# ('2020s', get_years_gen(2019, 2029), x[1]),\n", + "# ('2000-2100', get_years_gen(2000, 2100), x[1]),\n", + "# ('1900-2100', get_years_gen(1900, 2100), x[1]),\n", + "# ('1-2100', get_years_gen(1, 2100), x[1]),\n", + " ]\n", + " \n", + " \n", + " return schedule, len(x)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Optimize the last two, so the new one and the most recent before that. That way, there's a lag time, but most of it is set. We can also save the progresss of the model to make the running occur faster" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'get_years_gen' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'Jun'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mget_months_gen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2019\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m6\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.85\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'2019'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mget_year_generator\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2019\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.85\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 15\u001b[1;33m \u001b[1;33m(\u001b[0m\u001b[1;34m'2020'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mget_years_gen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2019\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2020\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.85\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 16\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'2020s'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mget_years_gen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2019\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2029\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.85\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 17\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'2000-2100'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mget_years_gen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2000\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2100\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.85\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mNameError\u001b[0m: name 'get_years_gen' is not defined" + ] + } + ], + "source": [ + "schedule = [\n", + " ('Jul', get_months_gen(2019, [7]), 0.99),\n", + " ('Aug', get_months_gen(2019, [8]), 0.85),\n", + " ('Sep', get_months_gen(2019, [9]), 0.85),\n", + " ('Oct', get_months_gen(2019, [10]), 0.85),\n", + " ('Nov', get_months_gen(2019, [11]), 0.85),\n", + " ('Dec', get_months_gen(2019, [12]), 0.85),\n", + " ('Jan', get_months_gen(2019, [1]), 0.85),\n", + " ('Feb', get_months_gen(2019, [2]), 0.85),\n", + " ('Mar', get_months_gen(2019, [3]), 0.85),\n", + " ('Apr', get_months_gen(2019, [4]), 0.85),\n", + " ('May', get_months_gen(2019, [5]), 0.85),\n", + " ('Jun', get_months_gen(2019, [6]), 0.85),\n", + " ('2019', get_year_generator(2019), 0.85),\n", + " ('2020', get_years_gen(2019, 2020), 0.85),\n", + " ('2020s', get_years_gen(2019, 2029), 0.85),\n", + " ('2000-2100', get_years_gen(2000, 2100), 0.85),\n", + " ('1900-2100', get_years_gen(1900, 2100), 0.85),\n", + " ('1-2100', get_years_gen(1, 2100), 0.85),\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "run_schedule(schedule)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Minibatch 100 0.5375\n", + "Trained July in 6208 samples\n", + "Trained Aug in 3072 samples\n", + "Trained Sep in 32 samples\n", + "Minibatch 100 0.571875\n", + "Trained Oct in 6016 samples\n", + "Trained Nov in 32 samples\n", + "Trained Dec in 64 samples\n", + "Trained Jan in 32 samples\n", + "Minibatch 100 0.79375\n", + "Trained Feb in 3328 samples\n", + "Trained Mar in 64 samples\n", + "Trained Apr in 32 samples\n", + "Trained May in 32 samples\n", + "Trained Jun in 1568 samples\n", + "Trained Jul-Dec in 32 samples\n", + "Trained 2019 in 3008 samples\n", + "Minibatch 100 0.75\n", + "Trained 2020 in 5312 samples\n", + "Minibatch 100 0.584375\n", + "Minibatch 200 0.778125\n", + "Minibatch 300 0.79375\n", + "Trained 2020s in 9856 samples\n", + "Minibatch 100 0.509375\n", + "Minibatch 200 0.6625\n", + "Minibatch 300 0.6875\n", + "Minibatch 400 0.75625\n", + "Minibatch 500 0.796875\n", + "Minibatch 600 0.7875\n", + "Trained 2000-2100 in 19904 samples\n", + "Trained 1900-2100 in 2944 samples\n", + "Minibatch 100 0.45625\n", + "Minibatch 200 0.5125\n", + "Minibatch 300 0.6125\n", + "Minibatch 400 0.65\n", + "Minibatch 500 0.65625\n", + "Minibatch 600 0.68125\n", + "Minibatch 700 0.696875\n", + "Minibatch 800 0.721875\n", + "Minibatch 900 0.734375\n", + "Minibatch 1000 0.746875\n", + "Minibatch 1100 0.778125\n", + "Minibatch 1200 0.80625\n", + "Minibatch 1300 0.825\n", + "Trained 1-2100 in 42400 samples\n", + "Minibatch 100 0.815625\n", + "Minibatch 200 0.85625\n", + "Minibatch 300 0.85625\n", + "Minibatch 400 0.884375\n", + "Minibatch 500 0.853125\n", + "Minibatch 600 0.85\n", + "Minibatch 700 0.890625\n", + "Minibatch 800 0.9\n", + "Minibatch 900 0.90625\n", + "Minibatch 1000 0.90625\n", + "Minibatch 1100 0.884375\n", + "Minibatch 1200 0.925\n", + "Minibatch 1300 0.940625\n", + "Minibatch 1400 0.925\n", + "Minibatch 1500 0.946875\n", + "Minibatch 1600 0.9375\n", + "Minibatch 1700 0.94375\n", + "Minibatch 1800 0.965625\n", + "Minibatch 1900 0.95\n", + "Minibatch 2000 0.953125\n", + "Minibatch 2100 0.928125\n", + "Minibatch 2200 0.940625\n", + "Minibatch 2300 0.959375\n", + "Minibatch 2400 0.9625\n", + "Minibatch 2500 0.959375\n", + "Minibatch 2600 0.96875\n", + "Minibatch 2700 0.971875\n", + "Minibatch 2800 0.96875\n", + "Minibatch 2900 0.971875\n", + "Minibatch 3000 0.971875\n", + "Minibatch 3100 0.9625\n", + "Minibatch 3200 0.984375\n", + "Minibatch 3300 0.946875\n", + "Minibatch 3400 0.95\n", + "Minibatch 3500 0.978125\n", + "Minibatch 3600 0.975\n", + "Minibatch 3700 0.98125\n", + "Minibatch 3800 0.975\n", + "Minibatch 3900 0.98125\n", + "Minibatch 4000 0.98125\n", + "Minibatch 4100 0.990625\n", + "Minibatch 4200 0.990625\n", + "Minibatch 4300 0.978125\n", + "Trained 1-2100 in 138720 samples\n", + "Training complete after 242656 samples\n" + ] + } + ], + "source": [ + "from itertools import chain\n", + "\n", + "reset_model()\n", + "\n", + "schedule = [\n", + " ('July', get_month_generator(2019, 7), 0.85),\n", + " ('Aug', get_months_gen(2019, range(7, 9)), 0.85),\n", + " ('Sep', get_months_gen(2019, range(7, 10)), 0.85),\n", + " ('Oct', get_months_gen(2019, range(7, 11)), 0.85),\n", + " ('Nov', get_months_gen(2019, range(7, 12)), 0.85),\n", + " ('Dec', get_months_gen(2019, range(7, 13)), 0.85),\n", + " ('Jan', get_months_gen(2019, chain(range(1, 2), range(7, 13))), 0.85),\n", + " ('Feb', get_months_gen(2019, chain(range(1, 3), range(7, 13))), 0.85),\n", + " ('Mar', get_months_gen(2019, chain(range(1, 4), range(7, 13))), 0.85),\n", + " ('Apr', get_months_gen(2019, chain(range(1, 5), range(7, 13))), 0.85),\n", + " ('May', get_months_gen(2019, chain(range(1, 6), range(7, 13))), 0.85),\n", + " ('Jun', get_months_gen(2019, chain(range(1, 7), range(7, 13))), 0.85),\n", + " ('Jul-Dec', get_months_gen(2019, chain(range(1, 8), range(7, 13))), 0.85),\n", + " ('2019', get_year_generator(2019), 0.85),\n", + " ('2020', get_years_gen(2019, 2020), 0.85),\n", + " ('2020s', get_years_gen(2019, 2029), 0.85),\n", + " ('2000-2100', get_years_gen(2000, 2100), 0.85),\n", + " ('1900-2100', get_years_gen(1900, 2100), 0.85),\n", + " ('1-2100', get_years_gen(1, 2100), 0.85),\n", + " ('1-2100', get_years_gen(1, 2100), 0.999),\n", + "]\n", + "\n", + "bad_schedule = [\n", + " ('1-2100', get_years_gen(1, 2100), 0.85)\n", + "]\n", + "\n", + "schedule_2 = list(map(lambda item: (item[0], item[1], 0.5), schedule))\n", + "schedule_2[-1] = schedule[-1]\n", + "\n", + "schedule_3 = list(map(lambda item: (item[0], item[1], 0.2), schedule))\n", + "schedule_3[-1] = schedule[-1]\n", + "\n", + "run_schedule(schedule)\n", + "\n", + "# print('\\n\\n\\n')\n", + "# reset_model()\n", + "# run_schedule(model, schedule_2)\n", + "# print('\\n\\n\\n')\n", + "# reset_model()\n", + "# run_schedule(model, schedule_3)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0., 0., 0., 0., 0., 0., 1.])" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "convert_to_vector(date(2019,7,28))[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[3.21856205e-04, 4.16064868e-04, 3.76252714e-03, 1.97594166e-02,\n", + " 8.88420641e-01, 7.28261918e-02, 1.44934375e-02]], dtype=float32)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.predict(convert_to_vector(date(2035,5,18))[0].reshape((1, -1)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So far, it seems that a model with 0.85 threshold trains with 160k samples and a model with 0.5 threshold trains with 120k samples.\n", + "\n", + "I tested a model with no grading. It got 100k batches (3,200k samples) without having improved its' accuracy at all." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Can we train some type of model that takes in training histories and outputs the ideal training history?" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/1\n", + "100000/100000 [==============================] - 19s 190us/step - loss: 0.4153 - acc: 0.8324\n" + ] + } + ], + "source": [ + "stuff = model.fit(xs, ys)\n", + "\n", + "stuff\n", + "print(stuff.history['acc'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next steps:\n", + "\n", + "- Overfit on a single sample of say 1000, then as soon as its' prediction is better than chance, move along to another set. \n", + " - Compare to pure random\n", + "- Overfit on a sample of just a few, and then start throwing in new ones? - This was the whole strategy from before\n", + " - This would work, but we want our sample to be better than just chance, how do we determine the sample?\n", + "\n", + "1. Just do in order with random distributions up until a certain threshold\n", + " - Test different thresholds for progression, 50% accuracy, 90%, etc\n", + "2. Change distribution to reflect the learning that needs to happen\n", + " - If you get a certain month right 90% of the time, only show it 10% of the time or something like that - determine this distrubtion\n", + "3. Learn the distribution using some kind of statistics or model\n", + "4. Create an ml model that perfects this situation\n", + "\n", + "Also, should be considering taking a month where we know the date and asking for another date. So if we know that today is the 18th and a Thursday, we can infer that tomorrow is the 19th and a Friday." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Dates/Personal Trainer.ipynb b/Dates/Personal Trainer.ipynb new file mode 100644 index 0000000..43535ef --- /dev/null +++ b/Dates/Personal Trainer.ipynb @@ -0,0 +1,117 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import date\n", + "from calendar import day_abbr, monthrange\n", + "\n", + "\n", + "def month_wkdy(month, days_string='MTWRFSU', year=2019):\n", + " wkday_map = {\n", + " 'M': 0,\n", + " 'T': 1,\n", + " 'W': 2,\n", + " 'R': 3, \n", + " 'F': 4, \n", + " 'S': 5,\n", + " 'U': 6\n", + " }\n", + " \n", + " days = sorted([wkday_map[day] for day in days_string])\n", + " \n", + " names = [day_abbr[i] for i in days]\n", + " \n", + " name = date(year, month, 1).strftime('%B, %Y (' + ', '.join(names) + ')')\n", + " \n", + " cards = []\n", + " for i in range(monthrange(2019, month)[1]):\n", + " day = date(2019, month, i+1)\n", + " if day.weekday() not in days:\n", + " continue\n", + " date_string = day.strftime('%B %d, %Y')\n", + " day_string = day.strftime('%A')\n", + " cards.append([date_string, day_string])\n", + " \n", + " return cards\n", + "\n", + "def aug_wkdy(days_string):\n", + " return month_wkdy(8, days_string)\n", + "\n", + "def sept_wkdy(days_string):\n", + " return month_wkdy(9, days_string)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "\n", + "def train(cards):\n", + " while True:\n", + " date, day = random.choice(cards)\n", + " if input(date):\n", + " break\n", + " if input(day):\n", + " break\n", + " print()\n", + "\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "September 05, 2019\n", + "Thursday\n", + "\n", + "September 05, 2019\n" + ] + } + ], + "source": [ + "train(sept_wkdy('MR'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Dates/Presidents.ipynb b/Dates/Presidents.ipynb new file mode 100644 index 0000000..a624371 --- /dev/null +++ b/Dates/Presidents.ipynb @@ -0,0 +1,229 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate date flashcards for Anki\n", + "https://github.com/kerrickstaley/genanki" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1270607229" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import random\n", + "\n", + "def get_id():\n", + " return random.randrange(1<<32)\n", + "get_id()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import genanki\n", + "\n", + "front_back = genanki.Model(\n", + " get_id(),\n", + " 'Front Back Model',\n", + " fields=[\n", + " {'name': 'Front'},\n", + " {'name': 'Back'},\n", + " ],\n", + " templates=[\n", + " {\n", + " 'name': 'Card',\n", + " 'qfmt': '{{Front}}',\n", + " 'afmt': '{{Back}}',\n", + " },\n", + " ]\n", + ")\n", + "\n", + "def make_deck(cards, name):\n", + " # Cards is a list of fields\n", + " deck = genanki.Deck(get_id(), name)\n", + " \n", + " for card in cards:\n", + " note = genanki.Note(\n", + " model=front_back,\n", + " fields=card\n", + " )\n", + " deck.add_note(note)\n", + " \n", + " return deck\n", + "\n", + "def write_decks(decks, name):\n", + " genanki.Package(decks).write_to_file(f'{name}.apkg')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "presidents = [ \n", + " \"George Washington\",\n", + " \"John Adams\",\n", + " \"Thomas Jefferson\",\n", + " \"James Madison\",\n", + " \"James Monroe\",\n", + " \"John Quincy Adams\",\n", + " \"Andrew Jackson\",\n", + " \"Martin Van Buren\",\n", + " \"William Henry Harrison\",\n", + " \"John Tyler\",\n", + " \"James K. Polk\",\n", + " \"Zachary Taylor\",\n", + " \"Millard Fillmore\",\n", + " \"Franklin Pierce\",\n", + " \"James Buchanan\",\n", + " \"Abraham Lincoln\",\n", + " \"Andrew Johnson\",\n", + " \"Ulysses S. Grant\",\n", + " \"Rutherford B. Hayes\",\n", + " \"James A. Garfield\",\n", + " \"Chester A. Arthur\",\n", + " \"Grover Cleaveland (First term)\",\n", + " \"Benjamin Harrison\",\n", + " \"Grover Cleaveland (Second term)\",\n", + " \"William McKinley\",\n", + " \"Theodore Roosevelt\",\n", + " \"William Howard Taft\",\n", + " \"Woodrow Wilson\",\n", + " \"Warren G. Harding\",\n", + " \"Calvin Coolidge\",\n", + " \"Herbert Hoover\",\n", + " \"Franklin D. Roosevelt\",\n", + " \"Harry S. Truman\",\n", + " \"Dwight D. Eisenhower\",\n", + " \"John F. Kennedy\",\n", + " \"Lyndon B. Johnson\",\n", + " \"Richard Nixon\",\n", + " \"Gerald Ford\",\n", + " \"Jimmy Carter\",\n", + " \"Ronald Reagan\",\n", + " \"George H. W. Bush\",\n", + " \"Bill Clinton\",\n", + " \"George W. Bush\",\n", + " \"Barack Obama\",\n", + " \"Donald Trump\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def ordinal(n):\n", + " s = str(n)\n", + " if 10 < n < 20:\n", + " s += 'th'\n", + " elif n % 10 == 1:\n", + " s += 'st'\n", + " elif n % 10 == 2:\n", + " s += 'nd'\n", + " elif n % 10 == 3:\n", + " s += 'rd'\n", + " else:\n", + " s += 'th'\n", + " return s\n", + "\n", + "def ordgen():\n", + " i = 1\n", + " while True:\n", + " yield ordinal(i)\n", + " i += 1\n", + "name_first = []\n", + "num_first = []\n", + "for name, num in zip(presidents, ordgen()):\n", + " card = [name, num]\n", + " card2 = [num, name]\n", + " name_first.append(card)\n", + " num_first.append(card2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_first" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "from IPython.display import clear_output\n", + "while True:\n", + " clear_output()\n", + " x, y = random.choice(name_first)\n", + " if input(x) != '':\n", + " break\n", + " if input(y) != '':\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "write_decks([make_deck(name_first, 'Name first'), make_deck(num_first, 'Number first')], 'presidents')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}