Штош, как я и обещал, что-то красивое.
Давайте добавим сам сайт. Для гибкой настройки того, что отправляется пользователю, есть система шаблонов, которые мы будем использовать. И да, мы будем использовать язык разметки HTML, таблицы стилей и JavaScript пока не трогаю, но если вы хотите в рамках курса гайд по ним, я могу сделать, заодно мы получим красивую страничку. Пишите в комментарии!
Так вот, давайте создадим папочку templates в папку нашего проекта, там мы будем размещать все наши шаблоны. Но, чтобы это сработало, нам нужно сходить в файл настроек и добавить одну строчку.
Супер, теперь, давайте создадим стандартный шаблон, то есть такой, какой ляжет в основу всех страниц. Например там может быть стандартный вид сайта, хеддер(это менюшка сверху для навигации по сайту), подвал(там где пишут телефон техподдержки и ссылки на доки). Назовем файл base.html и положим в папку шаблонов.
Так вот, это конструкции шаблонизатора, мы можем в отдельном шаблоне задать то, что Джанго поставит вместо каждого блока, поэтому, если мы хотим сделать страницу товара и каталога, нам бы не пришлось копировать код во все файлы, а если вы захотели подправить хеддер, то его не придется менять везде, он изменится автоматически. Давайте напишем страницу-каталог. Создадим в папке шаблонов папку с названием нашего приложения. Там мы и будем хранить шаблоны нашего приложения. Создадим файл shop.html
Пока тут просто заглушки, но давайте сделаем, чтобы мы их видели при загрузке.
Для этого нам потребуется уже известный views.py. Откроем, и изменим код
Вот, теперь если мы запустим сервер, то увидим то, что у нас отображается наша заглушка в виде текста. А что, собственно произошло? Джанго render нашёл по пути шаблон, он ссылается на базовый шаблон, в базовом шаблоне два блока. Шаблонизатор заменяет блоки на то, что написано в шаблоне, который мы написали последним. Успех, осталось всего лишь то отобразить список. Кстати, если что, в исходном коде страницы нет и следа того, что мы использовали шаблоны.
Ну, хорошо, нам нужно же из базы данных получить все это добро и на страницу вывести. Давайте это и сделаем, для этого идем во views.py
Во-первых появился order_by, он, логично, сортирует наши элементы, знак "-" перед параметром означает, что я буду сортировать в обратном порядке. И третий аргумент render. Он указывает контекст, то есть то, что мы даем шаблонизатору, сейчас мы это используем.
Возвращаемся к нашему шаблону
Вот, теперь у нас есть список продуктов сверху вниз. И, пока я на этом закончу, жду ваших комментариев, хотите ли вы отдельный урок по языку разметки и таблицам стилей, а то пока наш сайт всё ещё выглядит грустным.
Давайте добавим сам сайт. Для гибкой настройки того, что отправляется пользователю, есть система шаблонов, которые мы будем использовать. И да, мы будем использовать язык разметки HTML, таблицы стилей и JavaScript пока не трогаю, но если вы хотите в рамках курса гайд по ним, я могу сделать, заодно мы получим красивую страничку. Пишите в комментарии!
Так вот, давайте создадим папочку templates в папку нашего проекта, там мы будем размещать все наши шаблоны. Но, чтобы это сработало, нам нужно сходить в файл настроек и добавить одну строчку.
TEMPLATES = [
{
#...
'DIRS': [
os.path.join(PROJECT_ROOT,'templates')
],
#...
},
]
Супер, теперь, давайте создадим стандартный шаблон, то есть такой, какой ляжет в основу всех страниц. Например там может быть стандартный вид сайта, хеддер(это менюшка сверху для навигации по сайту), подвал(там где пишут телефон техподдержки и ссылки на доки). Назовем файл base.html и положим в папку шаблонов.
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Shop{% endblock %}</title>
</head>
<body>
Здесь вы можете разместить,например,хеддер
{% block content %}{% endblock %}
</body>
</html>
Так вот, это конструкции шаблонизатора, мы можем в отдельном шаблоне задать то, что Джанго поставит вместо каждого блока, поэтому, если мы хотим сделать страницу товара и каталога, нам бы не пришлось копировать код во все файлы, а если вы захотели подправить хеддер, то его не придется менять везде, он изменится автоматически. Давайте напишем страницу-каталог. Создадим в папке шаблонов папку с названием нашего приложения. Там мы и будем хранить шаблоны нашего приложения. Создадим файл shop.html
{% extends 'base.html' %}
{% block title %}Каталог товаров{% endblock %}
{% block content %}
Lorem Ipsum...
{% endblock %}Пока тут просто заглушки, но давайте сделаем, чтобы мы их видели при загрузке.
Для этого нам потребуется уже известный views.py. Откроем, и изменим код
from django.shortcuts import render
def index(request):
return render(request,'shop/shop.html')
Вот, теперь если мы запустим сервер, то увидим то, что у нас отображается наша заглушка в виде текста. А что, собственно произошло? Джанго render нашёл по пути шаблон, он ссылается на базовый шаблон, в базовом шаблоне два блока. Шаблонизатор заменяет блоки на то, что написано в шаблоне, который мы написали последним. Успех, осталось всего лишь то отобразить список. Кстати, если что, в исходном коде страницы нет и следа того, что мы использовали шаблоны.
Ну, хорошо, нам нужно же из базы данных получить все это добро и на страницу вывести. Давайте это и сделаем, для этого идем во views.py
from django.shortcuts import render
from .models import Item
def index(request):
products_list = Item.objects.order_by('-cost')
return render(request,'shop/shop.html', {'items': products_list})
Во-первых появился order_by, он, логично, сортирует наши элементы, знак "-" перед параметром означает, что я буду сортировать в обратном порядке. И третий аргумент render. Он указывает контекст, то есть то, что мы даем шаблонизатору, сейчас мы это используем.
Возвращаемся к нашему шаблону
{% extends 'base.html' %}
{% block title %}Каталог товаров{% endblock %}
{% block content %}
{% for a in items %}
<a href = "#">{{a.name}}</a>
{% endfor %}
{% endblock %}Вот, теперь у нас есть список продуктов сверху вниз. И, пока я на этом закончу, жду ваших комментариев, хотите ли вы отдельный урок по языку разметки и таблицам стилей, а то пока наш сайт всё ещё выглядит грустным.
Да, а вам нужен отдельный урок по HTML, CSS, для создания красивых страниц?
Anonymous Poll
93%
Да
7%
Нет
Супер, я вернулся. Вы хотели увидеть как кодить красивые страницы. Этот урок будет посвящён HTML и CSS. Это самая база, так как, конечно, сейчас появилось куча языков, которые типо лучше чем эти и они компилируются прямо в них, например SCSS. А кроме того есть еще третий язык - JavaScript, но про него стоит делать отдельный пост. Поэтому в этом уроке будет самая база.
Начнем с языка разметки HTML. Он нужен для того, чтобы создавать кнопки, надписи, таблицы и тп. Его синтаксис строится на тегах, теги бывают двух видов:парные и одиночные. Парные теги выглядят в общем случае вот так:
Вместо многоточия стоит название тега. Часть тега без слэша называется открывающая, а вторая, соответственно, закрывающая. Одиночный тег пишется только открывающейся частью. У тегов могут быть параметры, они указываются в открывающейся части. Например:
Это тег ссылки, он имеет один параметр - адрес ссылки. Между первой и второй частями идет текст ссылки. Вот несколько тегов, которые стоит знать:
Окей, допустим, пока хватит, давайте напишем первую страничку. В файле index.html можем написать:
Вот, если вы откроете этот файл в браузере, то вы увидите надпись, Ура!)
Теперь вы можете просто добавлять любые теги в тело(тег body) и они будут появляться у вас на сайте. Окей, но пока всё выглядит, мягко говоря, уныло, просто элементы в столбик, на сайт apple это не похоже. Для этого нам понадобится таблица стилей.
Допишем в тег head указание на таблицу стилей.
В href напишите путь к файлу с расширением css. Например, можем создать файл style.css.
Синтаксис этого языка выглядит так: указатель на объект, в фигурных скобках через точки с запятой названия стилей, и через двоеточие значение. Пример:
Тут я для всех тегов h1 сказал, что их писать красным цветом с таким шрифтом. Но, допустим, что я не хочу задавать всем заголовкам один и тот же стиль. Тогда есть две идеи, во-первых, если мне нужно одному конкретному элементу задать стиль, например кнопке. Тогда есть атрибут id у каждого тега. Задав его можно стиль задать для объекта с помощью решётки, после неё должнен стоять id и дальше по стандарту
Также есть класс, один и тот же класс можно задать к большому числу объектов, и также как с айди, только вместо решётки нужно поставить точку, можно задавать стили.
Стилей очень много, так что вот основные, но их все можно на гуглить, потом найдете сами.
Ну вот, часто вообще из названия сразу очевидно о чем это, так что так, я могу сделать еще одну часть, где я разберу это подробнее или рассказать также коротко про JavaScript. Кроме того мне может быть интересно посмотреть что сделаете вы, так что маленькая задачка, творческая, оформите страничку нашего сайта магазина и пришлите результат, тут важно не чтобы было красиво, а чтобы вы показали, что можете сделать сами, я могу чего-то подсказать. В любом случае через время Яя сам в комментариях пришлю свой вариант с кодом. Удачи всем!
Начнем с языка разметки HTML. Он нужен для того, чтобы создавать кнопки, надписи, таблицы и тп. Его синтаксис строится на тегах, теги бывают двух видов:парные и одиночные. Парные теги выглядят в общем случае вот так:
<...></...>
Вместо многоточия стоит название тега. Часть тега без слэша называется открывающая, а вторая, соответственно, закрывающая. Одиночный тег пишется только открывающейся частью. У тегов могут быть параметры, они указываются в открывающейся части. Например:
<a href="google.com">Текст ссылки</a>
Это тег ссылки, он имеет один параметр - адрес ссылки. Между первой и второй частями идет текст ссылки. Вот несколько тегов, которые стоит знать:
<h1>Текст заголовка</h1> - заголовок,чембольше цифра в имеги тега,тем меньше текст.
<p>Текст параграфа</p> - тег параграфа.
<div>Другие теги</div> - один из важнейших тегов, может содержать в себе другие,используетсякак контейнер.
<b>Текст</b> - делает текст жирным.
<em>Текст</em> - курсив.
<html>Теги</html> - обязательный тег,который содержит в себе все теги страницы.
<head></head> - обязательный тег,которыйсодержит в основном мета информацию о странице.
<body></body> - обязательный тег,который содержит в себе элементы,которыеотображаются на страгице.
<img src = ""> - вставляет картинку.
Окей, допустим, пока хватит, давайте напишем первую страничку. В файле index.html можем написать:
<!DOCTYPE html> <!-- обязательный тег,обьявляеттип документа -->
<html>
<head>
<title>Имя страницы</title>
</head>
<body>
<h1>Первая страница!</h1>
</body>
</html>
Вот, если вы откроете этот файл в браузере, то вы увидите надпись, Ура!)
Теперь вы можете просто добавлять любые теги в тело(тег body) и они будут появляться у вас на сайте. Окей, но пока всё выглядит, мягко говоря, уныло, просто элементы в столбик, на сайт apple это не похоже. Для этого нам понадобится таблица стилей.
Допишем в тег head указание на таблицу стилей.
<link rel="stylesheet" href="">
В href напишите путь к файлу с расширением css. Например, можем создать файл style.css.
Синтаксис этого языка выглядит так: указатель на объект, в фигурных скобках через точки с запятой названия стилей, и через двоеточие значение. Пример:
h1{
color: red;
font-family: arial;
}Тут я для всех тегов h1 сказал, что их писать красным цветом с таким шрифтом. Но, допустим, что я не хочу задавать всем заголовкам один и тот же стиль. Тогда есть две идеи, во-первых, если мне нужно одному конкретному элементу задать стиль, например кнопке. Тогда есть атрибут id у каждого тега. Задав его можно стиль задать для объекта с помощью решётки, после неё должнен стоять id и дальше по стандарту
#firth{
color: red;
font-family: arial;
}Также есть класс, один и тот же класс можно задать к большому числу объектов, и также как с айди, только вместо решётки нужно поставить точку, можно задавать стили.
Стилей очень много, так что вот основные, но их все можно на гуглить, потом найдете сами.
width - ширина элемента,можноуказывать в px
height - высота
color - цвет,длятекста это обычно цвет самого текста
background-color - цвет заднего фона
font-size - размер текста
margin - отступ снаружи
padding - отступ изнутри
Ну вот, часто вообще из названия сразу очевидно о чем это, так что так, я могу сделать еще одну часть, где я разберу это подробнее или рассказать также коротко про JavaScript. Кроме того мне может быть интересно посмотреть что сделаете вы, так что маленькая задачка, творческая, оформите страничку нашего сайта магазина и пришлите результат, тут важно не чтобы было красиво, а чтобы вы показали, что можете сделать сами, я могу чего-то подсказать. В любом случае через время Яя сам в комментариях пришлю свой вариант с кодом. Удачи всем!
😁1
Хмм, слушайте, я вот думаю, начало учебного года равносильно паре часов доп времени в день, есть ли у кого-то невероятные идеи, что вы хотите тут прочитать, лучше, конечно, примерно по теме)
Если что, если их не будет, я просто буду выпускать небольшие посты примерно на одну тему на пост (т.е. я не буду пытаться делать курс или что-то подобное)
Океей, говорите, вам очень хочется что-то с олимпиадной прогой. Ладно, но я все равно буду её чередовать с чем-то полезным).
Ну окей, поскольку канал про python, будем учится на нём. И я хочу как можно более полно рассказать о хеш-таблицах или словарях.
Начнем с их устройства. Хэш-таблицы - это такая структура данных, которая сопоставляет каждому ключу из списка ключей значения из некоторого другого списка. Причем она должна поддерживать несколько операций:
1) За О(1) она должна уметь добавлять, изменять или убирать любой элемент по ключу.
2) За О(1) можно получить любой элемент по ключу.
3) За О(n), где n - кол-во элементов таблицы, мы можем проитерироваться по всем парам ключ - значение.
Окей, внутри она устроена так, что есть некая функция, которая умеет превращать любой наш key в хэш, т.е. такое число, что для разных изначальных keys она должна в идеале получать разные значения. Почему в идеале? Ну, например, если мы попробуем хэшировать строки, то можем посчитать, с каким их количеством имеем дело. Чисел(это то, что мы сопоставляем строкам) у нас максимум 2^64, а вот строк в общем то сколько угодно. В разумных пределах строка может достигать любой длины, а разнообразие символов превратит это в степень, основание у которой - количество символов, которые мы можем использовать на некотором месте в строке. Как упражнение даю вам посчитать, строку из скольки русских маленьких и пробельных символов можно точно идеально закодировать(т.е. потенциально существует алгоритм, который всегда сможет сопоставить строке уникальное число).
В действительности все проще, мы просто хотим сделать вероятность случайного совпадения предельно маленькой. Поэтому мы можем, к примеру высчитывать значение какого нибудь полинома с коэффициентами из номеров символов в соответствующей таблице символов. Далее эти хэши мы используем для индексации в новом массиве и так получаем все, что нам нужно)
Теперь про код. В python все как всегда очень просто, создать словарь можно способами:
А также вот как выглядят базовые команды:
Мы можем несколькими способами итерироваться по словарям
Важно помнить, что
Теперь расскажу кое-что сложнее.
Поскольку наш любимый язык с батарейками в комплекте, то мы имеем кучу стандартных модулей, один из таких - модуль itertools. В нём есть несколько важных функций для работы в том числе со списками.
1. itertools.islice
Позволяет работать со срезами в словарях, так как обычные нет.
Ну окей, поскольку канал про python, будем учится на нём. И я хочу как можно более полно рассказать о хеш-таблицах или словарях.
Начнем с их устройства. Хэш-таблицы - это такая структура данных, которая сопоставляет каждому ключу из списка ключей значения из некоторого другого списка. Причем она должна поддерживать несколько операций:
1) За О(1) она должна уметь добавлять, изменять или убирать любой элемент по ключу.
2) За О(1) можно получить любой элемент по ключу.
3) За О(n), где n - кол-во элементов таблицы, мы можем проитерироваться по всем парам ключ - значение.
Окей, внутри она устроена так, что есть некая функция, которая умеет превращать любой наш key в хэш, т.е. такое число, что для разных изначальных keys она должна в идеале получать разные значения. Почему в идеале? Ну, например, если мы попробуем хэшировать строки, то можем посчитать, с каким их количеством имеем дело. Чисел(это то, что мы сопоставляем строкам) у нас максимум 2^64, а вот строк в общем то сколько угодно. В разумных пределах строка может достигать любой длины, а разнообразие символов превратит это в степень, основание у которой - количество символов, которые мы можем использовать на некотором месте в строке. Как упражнение даю вам посчитать, строку из скольки русских маленьких и пробельных символов можно точно идеально закодировать(т.е. потенциально существует алгоритм, который всегда сможет сопоставить строке уникальное число).
В действительности все проще, мы просто хотим сделать вероятность случайного совпадения предельно маленькой. Поэтому мы можем, к примеру высчитывать значение какого нибудь полинома с коэффициентами из номеров символов в соответствующей таблице символов. Далее эти хэши мы используем для индексации в новом массиве и так получаем все, что нам нужно)
Теперь про код. В python все как всегда очень просто, создать словарь можно способами:
python
#like this
d = dict()
#or like this
d = {}
А также вот как выглядят базовые команды:
python
#set an element by a key
d["apple"] = "fruit"
#replace an element
d["apple"] = "green"
#get an element, raises error if unable to get
print(d["apple"]) #green
#get an element or set a default value
print(d.get("banana", "yellow")) #yellow, d["banana"] → yellow
Мы можем несколькими способами итерироваться по словарям
d = {"apple": 120, "banana": 150, "orange": 100}
for fruit, mass in d.items():
print(mass)
#or you can get pairs (key, value)
for fruit in d.items():
print(fruit) #("apple", 120) ...
#if you want to have only keys
for fruit in d.keys():
print(fruit)
#and only values
for mass in d.values():
print(mass) Важно помнить, что
d.keys() и d.values() возвращают объекты-итераторы, и чтобы превратить их в список нужно отдельно воспользоваться list(). Последнее в этом блоке, это то, что не каждый объект можно захэшировать. Например, любой изменяемый тип данных как правило не хэшируется, не считая строк. Чтобы превратить, к примеру, список в хэшируемый объект, можно превратить его в кортеж, после этого он станет неизменяемым. Теперь расскажу кое-что сложнее.
Поскольку наш любимый язык с батарейками в комплекте, то мы имеем кучу стандартных модулей, один из таких - модуль itertools. В нём есть несколько важных функций для работы в том числе со списками.
1. itertools.islice
Позволяет работать со срезами в словарях, так как обычные нет.
import itertools
count_dict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
# Get the first 2 items of the dictionary
first_two = dict(itertools.islice(count_dict.items(), 2))
print(first_two)# {'one': 1, 'two': 2}
2. Можно группировать элементы в зависимости от значений в словаре
Да, тут мы использовали lambda-функцию, она отличается от обычной лишь тем, что не имеет названия и состоит из одной строки. Тут за значение группировки взяли прямо значение по ключу, но мы можем и произвести с ним вычисления, например, если бы это было число и нам нужно было бы сгруппировать их по модулю этого числа, то мы могли возводить просто его в квадрат(ну или в качестве аргумента передавать функцию модуля).
В модуле itertools есть еще много хороших инструментов, но на этом я, пожалуй, остановлюсь, если вам станет интересно, можете написать, и я напишу подробнее.
Также, если вы хотите, я могу кинуть задачку на использование хэш таблиц)
import itertools
users = [
{"name": "Alice", "role": "Admin"},
{"name": "Bob", "role": "User"},
{"name": "Charlie", "role": "Admin"}
]
# Sort by the grouping key first (required by groupby)
users.sort(key=lambda x: x["role"])
# Group by role
for role, group in itertools.groupby(users, key=lambda x: x["role"]):
print(f"Role: {role}")
for user in group:
print(f" - {user['name']}")
Да, тут мы использовали lambda-функцию, она отличается от обычной лишь тем, что не имеет названия и состоит из одной строки. Тут за значение группировки взяли прямо значение по ключу, но мы можем и произвести с ним вычисления, например, если бы это было число и нам нужно было бы сгруппировать их по модулю этого числа, то мы могли возводить просто его в квадрат(ну или в качестве аргумента передавать функцию модуля).
В модуле itertools есть еще много хороших инструментов, но на этом я, пожалуй, остановлюсь, если вам станет интересно, можете написать, и я напишу подробнее.
Также, если вы хотите, я могу кинуть задачку на использование хэш таблиц)
Ребят, у меня образовался новый кружек по ИИ, вы хотите тут видеть какую-то сжатую теорию с него?
Окей, сегодня была первая лекция, вам нужен линал? Я буду рассказывать его примерно также, как и у нас, а то расписывать все все аксиомы с 0 я в восьмой раз не хочу, наверное. Короче, если у вас есть желание это прочитать (я постараюсь сделать это легким), то пишите, лайкните или каким либо другим способом скажите...
❤9
Окей, как я и обещал.
Я расскажу ровно то, что рассказывали нам и то, что может потребоваться для ML.
Как и всегда, начнем с определение линейного пространства.
Опр Линейным пространством называют множество с заданными операциями сложения элемента и умножение на любое действительное число. Причем они(операции) должны удовлетворять некоторым свойствам.
1. Должен быть такой элемент 0, что для любого a из л.п.(линейного пространства) a + 0 = 0 + a = a.
2. Сложение должно обладать набором "хороших" свойств(типа ассоциативность, дистрибутивность и тп)
3. Умножение также должно быть "хорошим".
Про "хорошие" свойства, может быть, мы поговорим позднее, но пока, считайте, что это нормальное сложение и умножение.
Конечно, элементами л.п. являются векторы. Также, хочется привести пример л.п. с которым мы будем работать почти всегда, это пространство R^n, состоит из столбцов из n чисел с поэлементным сложением и умножением. Вы можете сами доказать, что все свойства есть.
Теперь поговорим о матрицах. Матрица - табличка вещественных чисел, сложение и умножение на число определены поэлементно(т.е. складываются соответствующие элементы матриц). Вот, а умножение матрицы на вектор сделано по-другому. Тут есть хороший пример, пусть матрица - строчки - очередной клиент магазина, а столбцы - разные товары, на пересечении строки и столбца стоит количество продукта, который купил данный покупатель. А вектор - стоимость за штучку товара. Тогда количество столбцев матрицы должно совпадать с размерностью вектора. Тогда в итоговом векторе будет сумма, которую заплатил каждый посетитель. Или как-то так.
(1 2 3) (1) (1 + 4 + 15)
(5 0 6) × (2) = (5 + 0 + 12)
(4 3 1) (5) (4 + 6 + 5)
Вот так. Последнее, это решение систем линейных уравнений.
Идея такая, систему можно записать в виде умножения матрицы коэффициентов на столбец переменных, т.е. нам нужно найти такой вектор, чтобы при умножении матрицы на него получался данный вектор. Существует метод Гаусса, который задает несколько операций с матрицей, к которой присоединила вектор ответа. Можно поменять строки местами, можно всю строку умножить на число и тп. И такими операциями по возможности можно привести матрицу к ступенчатому виду, т.е. такому, чтобы в каждой новой строке было меньше ненулевых коэффициентов, т.е. в последней строке должен быть только один ненулевой коэффициент, а значит мы можем все переменные выразить.
Вот, тут не очень много, но это ровно то, что нам рассказали...
Я расскажу ровно то, что рассказывали нам и то, что может потребоваться для ML.
Как и всегда, начнем с определение линейного пространства.
Опр Линейным пространством называют множество с заданными операциями сложения элемента и умножение на любое действительное число. Причем они(операции) должны удовлетворять некоторым свойствам.
1. Должен быть такой элемент 0, что для любого a из л.п.(линейного пространства) a + 0 = 0 + a = a.
2. Сложение должно обладать набором "хороших" свойств(типа ассоциативность, дистрибутивность и тп)
3. Умножение также должно быть "хорошим".
Про "хорошие" свойства, может быть, мы поговорим позднее, но пока, считайте, что это нормальное сложение и умножение.
Конечно, элементами л.п. являются векторы. Также, хочется привести пример л.п. с которым мы будем работать почти всегда, это пространство R^n, состоит из столбцов из n чисел с поэлементным сложением и умножением. Вы можете сами доказать, что все свойства есть.
Теперь поговорим о матрицах. Матрица - табличка вещественных чисел, сложение и умножение на число определены поэлементно(т.е. складываются соответствующие элементы матриц). Вот, а умножение матрицы на вектор сделано по-другому. Тут есть хороший пример, пусть матрица - строчки - очередной клиент магазина, а столбцы - разные товары, на пересечении строки и столбца стоит количество продукта, который купил данный покупатель. А вектор - стоимость за штучку товара. Тогда количество столбцев матрицы должно совпадать с размерностью вектора. Тогда в итоговом векторе будет сумма, которую заплатил каждый посетитель. Или как-то так.
(1 2 3) (1) (1 + 4 + 15)
(5 0 6) × (2) = (5 + 0 + 12)
(4 3 1) (5) (4 + 6 + 5)
Вот так. Последнее, это решение систем линейных уравнений.
Идея такая, систему можно записать в виде умножения матрицы коэффициентов на столбец переменных, т.е. нам нужно найти такой вектор, чтобы при умножении матрицы на него получался данный вектор. Существует метод Гаусса, который задает несколько операций с матрицей, к которой присоединила вектор ответа. Можно поменять строки местами, можно всю строку умножить на число и тп. И такими операциями по возможности можно привести матрицу к ступенчатому виду, т.е. такому, чтобы в каждой новой строке было меньше ненулевых коэффициентов, т.е. в последней строке должен быть только один ненулевой коэффициент, а значит мы можем все переменные выразить.
Вот, тут не очень много, но это ровно то, что нам рассказали...
Окей, ребятки, я разобью это на набор кусочков, а то уместить час(за который мы не успели) теории в один пост будет сложно.
Сегодня мы будем смотреть на задачу регрессии, т.е. задачу предсказания числа по набору каких-то других. При этом перед этим мы имеем n примеров, пар вида набор чисел - число. Окей, количество чисел во всех наборах одно и то же, пусть d. Тогда все наши примеры можно представить точками в многомерном пространстве, а задачу, как попытку провести поверхность через наши данные, чтобы она как-то хорошо их аппроксимировала. Ну, для простоты, давайте проводить плоскость (то, что задаётся уравнением ax + by + ... = 0). Осталось понять, а как считать, плоскость хорошая или плохая. Для этого есть разные функции ошибок, например:
MAE: самая простая, считает средний модуль ошибки, т.е. складывает модули разности предсказания модели и реального значения и делит это на их количество. Проблема её, например, в том, что модуль не везде дифференцируем.
MSE: то же самое, только вместо модуля берется квадрат.
Это две самые основные, про остальные поговорим в одной из следующих частей.
Хорошо, тогда заметим, что если все наши примеры сделать строками матрицы, то при умножении её на вектор весов, мы получим вектор предсказаний модели, а потом(советую написать это) можно вычесть вектор правильных ответов, а тогда, если найти квадрат его длины и поделить на размер - это и будет MSE. Окей, если мы хотим найти минимум этой штуки, то это можно сделать аналитически. Ищем производную, приравниваем к 0 и готово, используя вторую производную можно доказать, что это минимум, супер. Так вот, у вас есть два задания(если хочется, кидайте решения в комменты) :
1. Выведите общее решение математически.
2. Закодите его(воспользуйтесь numpy)
Не волнуйтесь, код тоже будет, но потом)
Сегодня мы будем смотреть на задачу регрессии, т.е. задачу предсказания числа по набору каких-то других. При этом перед этим мы имеем n примеров, пар вида набор чисел - число. Окей, количество чисел во всех наборах одно и то же, пусть d. Тогда все наши примеры можно представить точками в многомерном пространстве, а задачу, как попытку провести поверхность через наши данные, чтобы она как-то хорошо их аппроксимировала. Ну, для простоты, давайте проводить плоскость (то, что задаётся уравнением ax + by + ... = 0). Осталось понять, а как считать, плоскость хорошая или плохая. Для этого есть разные функции ошибок, например:
MAE: самая простая, считает средний модуль ошибки, т.е. складывает модули разности предсказания модели и реального значения и делит это на их количество. Проблема её, например, в том, что модуль не везде дифференцируем.
MSE: то же самое, только вместо модуля берется квадрат.
Это две самые основные, про остальные поговорим в одной из следующих частей.
Хорошо, тогда заметим, что если все наши примеры сделать строками матрицы, то при умножении её на вектор весов, мы получим вектор предсказаний модели, а потом(советую написать это) можно вычесть вектор правильных ответов, а тогда, если найти квадрат его длины и поделить на размер - это и будет MSE. Окей, если мы хотим найти минимум этой штуки, то это можно сделать аналитически. Ищем производную, приравниваем к 0 и готово, используя вторую производную можно доказать, что это минимум, супер. Так вот, у вас есть два задания(если хочется, кидайте решения в комменты) :
1. Выведите общее решение математически.
2. Закодите его(воспользуйтесь numpy)
Не волнуйтесь, код тоже будет, но потом)
Продолжим.
У подхода из предыдущей теории есть пара проблем
1. Все примеру нам нужно единовременно хранить в памяти, а их может быть очень много.
2. Обращение матрицы стоит дорого по операциям, поэтому слишком много обучающих примеров мы взять не можем.
А для их решения есть итеративные методы обучения, сегодня разберем градиентный спуск.
Градиентный спуск - алгоритм, который позволяет находить минимум произвольной дифференцируемой функции. Его работа заключается в вычислении производной по каждому параметру функции(вектор частных производных функции называется градиентом и направлен он в сторону наибольшего возрастания функции) и двигает точку в сторону, обратную той, что указывает градиент. Так мы двигаемся всегда вниз по функции, и если снижению придет конец, то мы нашли наш минимум. У этого алгоритма есть два параметра, которые мы задаем перед обучением(так называемых гиперпараметра):
1. lr, learning rate - параметр, показывающий, на сколько нужно умножить градиент, чтобы получить вектор смещения нашей точки, т.е. чем он больше, тем быстрее мы спускаемся, но при этом в узкий минимум можем не попасть, а если возьмем слишком маленький, то будем очень долго идти.
2. p0 - начальная точка, от неё зависит, куда мы попадем в конце, ведь наш спуск ищет локальный минимум, поэтому, если у нас их несколько, то мы можем попасть не в глобальный.
Тут снова есть две проблемы:
1. Как я уже сказал, не факт, что у нас получится найти нужный нам минимум.
2. Вычисление функции ошибки требует n операций(кол-во примеров), нахождение, например, численно производную по каждому аргументу требует отдельно пошевелить каждый из параметров. Короче, хотя и быстрее, но с учетом того, что это итеративный алгоритм, может быть долго. Для этого придумали две разновидности такого алгоритма.
1. Mini-batched. Это вид градиентного спуска, в котором мы каждую итерацию обучаемся не на конкретном наборе данных, а на неком рандомном его подмножестве, это быстрее, хотя и шумнее иногда.
2. Стохастический градиентный спуск. Это тоже самое, что и первое, только выборка состоит из одного элемента. Также часто из объединяют и просто называют mini-batched как стохастический.
Вот так)
У подхода из предыдущей теории есть пара проблем
1. Все примеру нам нужно единовременно хранить в памяти, а их может быть очень много.
2. Обращение матрицы стоит дорого по операциям, поэтому слишком много обучающих примеров мы взять не можем.
А для их решения есть итеративные методы обучения, сегодня разберем градиентный спуск.
Градиентный спуск - алгоритм, который позволяет находить минимум произвольной дифференцируемой функции. Его работа заключается в вычислении производной по каждому параметру функции(вектор частных производных функции называется градиентом и направлен он в сторону наибольшего возрастания функции) и двигает точку в сторону, обратную той, что указывает градиент. Так мы двигаемся всегда вниз по функции, и если снижению придет конец, то мы нашли наш минимум. У этого алгоритма есть два параметра, которые мы задаем перед обучением(так называемых гиперпараметра):
1. lr, learning rate - параметр, показывающий, на сколько нужно умножить градиент, чтобы получить вектор смещения нашей точки, т.е. чем он больше, тем быстрее мы спускаемся, но при этом в узкий минимум можем не попасть, а если возьмем слишком маленький, то будем очень долго идти.
2. p0 - начальная точка, от неё зависит, куда мы попадем в конце, ведь наш спуск ищет локальный минимум, поэтому, если у нас их несколько, то мы можем попасть не в глобальный.
Тут снова есть две проблемы:
1. Как я уже сказал, не факт, что у нас получится найти нужный нам минимум.
2. Вычисление функции ошибки требует n операций(кол-во примеров), нахождение, например, численно производную по каждому аргументу требует отдельно пошевелить каждый из параметров. Короче, хотя и быстрее, но с учетом того, что это итеративный алгоритм, может быть долго. Для этого придумали две разновидности такого алгоритма.
1. Mini-batched. Это вид градиентного спуска, в котором мы каждую итерацию обучаемся не на конкретном наборе данных, а на неком рандомном его подмножестве, это быстрее, хотя и шумнее иногда.
2. Стохастический градиентный спуск. Это тоже самое, что и первое, только выборка состоит из одного элемента. Также часто из объединяют и просто называют mini-batched как стохастический.
Вот так)
Я даже не знаю, так как единственное, что у меня сейчвс двигется плюс минус стабильно - это проект по информатике, иногда сюда будет чтото поститься
Interfaces.md
4 KB
тут лежат основные механики, но, очевидно, это не все, что, как думаете, стоит еще добавить?
work_process.png
12.4 KB
бездельник я, бездельник. Знаете, для чего делали ИИ, чтобы я не реализовывал этот интерфейс, а то я точно не вывезу)