Делаем сверточную нейронную сеть в Keras | #14 нейросети на Python

  Рет қаралды 46,155

selfedu

selfedu

Күн бұрын

Пікірлер: 102
@Выживаемкакможем-в9ю
@Выживаемкакможем-в9ю Жыл бұрын
Объясняет все простым языком даже для тех, кто ничего не понимает, респект !
@aleksandrshugaev843
@aleksandrshugaev843 7 ай бұрын
Поддерживаю высокую оценку - спасибо огромное! Как в лучшем ВУЗе на лекции побывал...
@86Blind
@86Blind 3 жыл бұрын
Какая грамотная речь. Огромное спасибо !
@a-lobanov
@a-lobanov 8 ай бұрын
Огромное спасибо за Ваш курс! Все доходчиво и понятно.
@shaha2411
@shaha2411 4 жыл бұрын
Молодец! Понятно и доходчиво объясняете, огромное спасибо!
@connorkorbin4576
@connorkorbin4576 3 жыл бұрын
I know I am kind of randomly asking but do anyone know a good place to stream new series online ?
@Спец-е3п
@Спец-е3п Жыл бұрын
hdrezka@@connorkorbin4576
@kamino7_7
@kamino7_7 5 ай бұрын
Как же вы крут!
@zhongwenzhu2748
@zhongwenzhu2748 2 жыл бұрын
Очень полезный урок, спс большое - от китайца.
@Dmitrii-Zhinzhilov
@Dmitrii-Zhinzhilov Жыл бұрын
Благодарю! 💯🔥👍
@СарматПересветов
@СарматПересветов Ай бұрын
большое спасибо!
@ViktorKataev
@ViktorKataev 6 ай бұрын
Спасибо, очень понятно!
@_sort_
@_sort_ Жыл бұрын
Интересный тип сети. Даже если поставить малое количество слоев свертки, даже если убрать maxPooling. То всю сеть может спасти полносвязная часть, хоть и точность уже и не будет 99%. Возможно изображения слишком просты, и поэтому сеть устойчива к недостатку параметров. Я пытался по всякому ее развалить, но это не так то и просто. В любом случае спасибо вам за материал!
@MurzNN
@MurzNN Жыл бұрын
И ещё хотелось бы увидеть, во что визуально превращаются изображения после прогона всех комбинаций фильтра 3х3?
@osmininmaks
@osmininmaks Жыл бұрын
GraphCore на гитхабе, например, или TensorSpace. В сети можно несколько визуализаторов найти.
@СарматПересветов
@СарматПересветов Ай бұрын
вопрос, во втором слое Conv2D мы не прописываем параметр input_shape, так как он определяется автоматически?? А если бы мы прописывали его в ручную, то поидеи онбы равнялся input_shape = (14,14,32) или input_shape = (32, 14,14)?
@meltedcheese7470
@meltedcheese7470 Жыл бұрын
Хороший урок
@ПитонПайтон
@ПитонПайтон 2 жыл бұрын
мне пришла идея, как самая распознавания цифр. а что научить 10 нейросетей распознавать каждую цифру по отдельности ( с 2 выходами) . при распознавании цифры посчитать значения от каждой из нейросетей и выбрать максимально приблеженное к единице, возможно при таком способе будут выделены "образы" кадр цифры по отдельности лучше, чем при написании одной нейросети с 10 выходами
@selfedu_rus
@selfedu_rus 2 жыл бұрын
лучше одна, т.к. при множестве моделей делать их комбинацию для окончательного вывода - отдельная задача. Там есть свои подводные камни. См. занятие по многоклассовой классификации курса "Машинное обучение"
@petromukharovskyi2113
@petromukharovskyi2113 3 жыл бұрын
Спасибо большое!!!
@ludicrousprophet413
@ludicrousprophet413 Жыл бұрын
Добрый день, автор. Хочу выразить огромную благодарность за вашу титаническую работу. Невероятный мпткриал и подача. И по данному видео имею вопрос. Вы сказали, что на подачу первого свёрточного слоя необходим 4-мерный массив и для этот вы использовали строки >>> x_train = np.expand_dims(x_train, axis=3) >>> x_test = np.expand_dims(x_test, axis=3) И принимали на данный момент, что данные в x_train и тп 3-мерные а именно (batch, row, col). Но это же не так. При отладки размера x_train выдаёт (28, 28). Я объяснил себе это иначе и вроде прав: в начале мы имеем действительно (28, 28), но в строке >>> Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(28, 28, 1) >model.fit(x_train_split, y_train_split, batch_size=32, epochs=5, validation_data=(x_val_split, y_val_split))
@selfedu_rus
@selfedu_rus Жыл бұрын
Спасибо! Насколько я помню, на вход сверточных слоев подается сигнал в формате: (batch, row, col, channels) Последняя 1 - это число каналов. Если grayscale - один канал, если RGB - 3 канала и так далее.
@mormonteg4073
@mormonteg4073 Жыл бұрын
Спасибо за урок. Очень ждал, какие шаблоны получились для каждой цифры, но не судьба(
@komazmt
@komazmt 3 жыл бұрын
Здравствуйте, спасибо вам за ценные знания и приятную подачу. Вопросик: в конце построения, когда мы уже выпрямили вектор и создаём полносвязные слои, как выбирать их количество? Эксперементируем или чаще всего достаточно одного скрытого слоя?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
эксперимент + опыт, пока больше ничего особо не придумали )
@The_Dimetrius
@The_Dimetrius 2 жыл бұрын
Подскажите, что означает цифра "1500" при обучении сети (12:29 минута видео) ?
@meltedcheese7470
@meltedcheese7470 2 жыл бұрын
число итераций, говорит сколько батчей надо, чтобы завершить 1 эпоху: 48000 / 32 = 1500
@5junkmail
@5junkmail 2 жыл бұрын
Здравстуйте, спасибо больше за уроки! У меня такой вопрос. в первом слое Conv2D что делает операция активации relu, к чему она применяется? Разве у нас не просто умножение на маску 3х3 и сложение всех полученных значений? Или сумма всех значений ещё пропускается через relu?
@selfedu_rus
@selfedu_rus 2 жыл бұрын
да, результаты свертки пропускаются через функцию активации и получаем выходные значения карт признаков
@daniilk3737
@daniilk3737 6 ай бұрын
Спасибо, очень интересно и доступно но 1 вопрос остался неясным на 10:30 вы говорите про тип данных подаваемые в НС и в него нужно добавить ещё одно поле. Но сама выборка это массив с элементами 28х28. Он значения batch,rows,cols вычисляются автоматически на основе подаваемых данных ? batch - вся выборка, rows и cols - словно стандартизация размерности каждого элемента выборки? Или это требования к структуре данных и структура данных серьёзно как-то изменяется чтобы с ней можно было работать? спасибо за ответ, если кто поможет
@Илья-ф8ц4ы
@Илья-ф8ц4ы Жыл бұрын
Очень хочется поэкспериментировать с строением нейронной сети. Дополнительные слои добавить, увеличить ядро и так далее, но вот проблема: обучение у меня занимает более пяти минут😪. Очень печально, но ничего с этим не поделать. Может в будущем, когда уже поступлю в ВУЗ на направление ИИ, куплю нормальную машину, на которой приятно будет работать и учиться. На текущем устройстве даже нет полноценной видеокарты, у меня только графическое ядро у процессора есть.
@вадимсовав
@вадимсовав Жыл бұрын
Добрый вечер! Отличные подборки по видео урокам!! Но у меня возникли ьрудноати при обучении модели, выдвет ошибку : что обучающие данные содержат одну выборку, чего не достаточно для разделения на проверочные и обучаюшие наборы,как указано в validation _split=0.2
@boost_456
@boost_456 Жыл бұрын
Логично. Если в выборке 1 изображение, его невозможно поделить на обучающее и проверочное. Должно быть как минимум 2 изображения
@kotikGGG
@kotikGGG 8 ай бұрын
Почему на входе в Conv2d_1 32х10 входов? Разве MaxPooling2D((2, 2), strides=2) не сжал в 2 раза?
@YbisZX
@YbisZX 7 ай бұрын
Макспуллинг изображение сжимает. А 32*10 - это число фильтров на количество параметров (3*3+1). К размерностям карт слоев это не имеет отношение.
@ЕгорТишко́-ш9у
@ЕгорТишко́-ш9у 2 жыл бұрын
Прекрасное изложение материала. Хотел бы только уточнить один вопрос, возможно глупый, но я не нашел на него ответа нигде. Как происходит инициализация фильтров? Они есть готовые в библиотеке, или как-то случайным образом инициализируются, или их можно самостоятельно задавать?
@selfedu_rus
@selfedu_rus 2 жыл бұрын
Спасибо! Коэффициенты фильтров - это веса связей нейронов, они подбираются в процессе обучения НС.
@MurzNN
@MurzNN Жыл бұрын
Не совсем понятно почему мы уменьшаем изображение, чтобы улучшить качество распознавания. Ведь в 28х28 можно рассмотреть гораздо больше деталей и закономерностей, чем в 7х7. А тут в итоге подаётся на вход сильно урезанное изображение. Если подавать 28х28 - качество наверно будет лучше, нет?
@boost_456
@boost_456 Жыл бұрын
Я так понимаю что сначала у нас есть всё изображение 28x28, потом мы прогоняем его через фильтры и получаем какие-то наборы признаков. Из этих наборов мы отбираем главные признаки с помощью MaxPooling, в итоге размер становится 14x14. Мы снова прогоняем эти наборы через фильтры и так далее. То есть условно, сначала мы рассматривали всю цифру "2" целиком, потом поделили её на кривую и прямую палочки. Потом поделили на ещё более мелкие элементы. То есть мы учим нейронку что "2" состоит из таких-то элементов, а "5" из других. У меня, например, нейронка думала что 8 это 2, потому что у них есть общая черта (дуга сверху)
@dmitrymitrofanov3920
@dmitrymitrofanov3920 4 жыл бұрын
Разжевана каждая буква, круто, надеюсь будете продолжать ... gans, lstm, rnn. А будут bert?
@selfedu_rus
@selfedu_rus 4 жыл бұрын
gans, lstm, rnn будут )
@mormonteg4073
@mormonteg4073 2 жыл бұрын
Русскоязычнай сайт по керас не работает. Есть другой ккой-нибудь?
@tresTein
@tresTein 11 ай бұрын
Откуда брать mnist?, у меня вот есть папки с картинками как из них сделать файл подходящий как mnist.
@kotikGGG
@kotikGGG 8 ай бұрын
Ответ на 1 вопрос: from keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() Ответ на 2 (только библиотеку cv2 установи командой pip install opencv-contrib-python): from PIL import Image import numpy as np import cv2 def rec_digit(img_path): img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) gray = 255 - img gray = cv2.resize(gray, (28, 28)) cv2.imwrite('gray'+ img_path, gray) img = gray / 255.0 img = np.array(img).reshape(-1, 28, 28, 1) out = str(np.argmax(model.predict(img))) plt.subplot(121) plt.imshow(gray, cmap='gray') plt.subplot(122) # plt.imshow(img.squeeze(), cmap='gray') plt.show() return out
@Qvikkk
@Qvikkk 3 жыл бұрын
Что будет если мы укажем в макспулинг 2 на 2, а размер наше матрицы не четный, например 25 на 25?
@victortamino4998
@victortamino4998 3 жыл бұрын
Если я правильно понимаю, то к матрице добавится проинициализированная нулями 26 строка и 26 столбец.
@victortamino4998
@victortamino4998 3 жыл бұрын
Большое вам спасибо за такие подробные видео! Но не могу понять как из готовой и натренированной нейронной сети достать веса. Если мы к вашей описанной сети применим print(model.get_weights()), то получим не очень очевидный набор весов, т.к. ядро свертки у нас 3х3 (для conv2d), а веса получатся в виде 4х3, и вместо 4, 3 такие матрицы. Ко всему прочему данный вывод обрежет часть выводимых весов в последующих слоях, где этих весов больше какой-то границы для print. Подскажите, пожалуйста, как грамотно вывести веса каждого слоя, не потеряв при этом ни одного значения, с возможностью их в дальнейшем прочесть глазами?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
Во-первых, можно вывести данные с помощью метода summary() - там все будет по слоям. Во-вторых, можно создать ссылку на каждый слой (при формировании НС) и для конкретного слоя вызвать метод get_weights().
@victortamino4998
@victortamino4998 3 жыл бұрын
@@selfedu_rus Благодарю за скорый ответ! Метод summary(), если я не ошибаюсь, возвращает только общее число весов у каждого слоя. С помощью этого метода нельзя получить сами веса. Но, возможно я что-то путаю. А как создать ссылку на каждый слой? Но в любом случае, веса для слоя, например, Conv2D(4, (3,3)) должны быть вида (3*3 + 1 (bias) ) * 4, а в терминале наблюдаю матрицу 3*4. И как их правильно в таком случае соотнести с ядром свертки 3*3?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
@@victortamino4998 Да, suumary() возвращает только количество, сами веса уже через get_weights(). Биас прибавляется один ко всем каналам, а не к каждому фильтру (я об этом рассказывал в одном из уроков). Чтобы получить ссылку на слой, нужно его отдельно создать: layer1 = Conv2D(4, (3,3)), затем, добавить его в модель (как layer1) и уже через эту переменную получать веса: layer1.get_weights()
@victortamino4998
@victortamino4998 3 жыл бұрын
@@selfedu_rus Теперь понял как, Большое Спасибо! Правда, что-то не получается. Первый слой я назвал layer1 (name="layer1"). При попытке к нему обратиться (layer1.get_weights()) получаю ошибку: name 'layer1' is not defined.
@selfedu_rus
@selfedu_rus 3 жыл бұрын
@@victortamino4998 Переменную нужно создавать, а не атрибут name.
@СтепанГераскин
@СтепанГераскин Жыл бұрын
Здравствуйте, а почему на второй слой мы подаем тензор 3×3×32, а не 14×14×32?
@selfedu_rus
@selfedu_rus Жыл бұрын
3x3 - это размер ядра (фильтра), а не входного тензора (насколько я помню)
@СтепанГераскин
@СтепанГераскин Жыл бұрын
@@selfedu_rus разобрался, спасибо большое!
@dubinin_s
@dubinin_s 4 жыл бұрын
Спасибо за видео. Заранее извиняюсь за глупый вопрос, просто некоторые вещи я совершенно не понимаю. В своих видео Вы пользуетесь Mnist (так же есть и другие базы для распознания различных объектов), а как быть если мне нужно распознавать, что то для чего нет готовых баз данных? Как мне самому создать выборку для распознания нужных мне предметов на фото? Я понимаю, что нужно много фотографий для формирования обучающей и тестовой выборки, но как пиксели на этих фотографиях превратить в числа которые можно подавать на вход сети. И вообще, что из себя представляет это выборка - это список, словарь или кортеж, ведь каждой картинке должен соответствовать правильный ответ, который будет сравниваться с выходными данными нейронки. Возможно я забегаю вперед и вы об этом еще будете говорить, а возможно уже говорили. Буду крайне признателен, если подскажите где это можно посмотреть или почитать. А если вы об этом говорили, то достаточно только кивнуть головой и я пересмотрю все видео еще раз и найду сам.
@selfedu_rus
@selfedu_rus 4 жыл бұрын
Да, вы все правильно в целом сказали: для формирования своей выборки нужна своя база изображений одинаковых размеров. Далее, нужно создать тензор (это объект numpy.array, на вход которого можно передать или список или кортеж) размерностями (batch_size, x, y, channels), channels - число цветовых каналов. Сами изображения можно загрузить стандартными средствами Python, например PIL. На выходе (после загрузки) будет тензор чисел. Каждый такой тензор помещаете в коллекцию обучающей выборки и так она формируется. Вот в двух словах так. Видео отдельного вроде нет , в будущих буду это показывать, но с текстовой информацией. Где посмотреть? Честно, даже не задумывался, т.к. вроде было понятно ))
@dubinin_s
@dubinin_s 4 жыл бұрын
@@selfedu_rus Огромное спасибо за Ваш ответ. Просто распознавать циферки, кошечек, собачек интересно, но это как "Hello World" при изучении любого языка программирования, на первом занятии прошел и пошел ООП изучать.
@ИльяКоваленко-л1ф
@ИльяКоваленко-л1ф Жыл бұрын
Здравствуйте. Я попробовал сделать нейронную сеть распознающую рукописные числа а не цифры. И максимум который я смог это просто разделять их по принципу «островов». Но я точно знаю что можно как то иначе судя по примеру Photomath. Не подскажете какие нейронные сети применяются в таких случаях
@selfedu_rus
@selfedu_rus Жыл бұрын
Думаю, здесь было бы правильно сделать начальную предобработку изображения, хотя бы разбить все по цифрам, а потом распознавать. Скармливать все сразу НС далеко не всегда хорошая идея.
@sergeygetto7480
@sergeygetto7480 3 жыл бұрын
Я всю ночь провозился над преобразованием данных и в итоге ничего не получилось. Я привёл все к нужным классам и типам данных, но на этапе включения нейронной сети выдало ошибку, которая решается с помощью no.expand_dims, но данная функция попросту не работает. Я пробовал через reshape, но данных слишком много, пробовал добавлять один слой изначально, но ничего не выходит. Возможно это крайне глупо. Подскажите, где можно посмотреть хоть какую-то информацию по поводу преобразования данных в нужный вид x_train и y_train?
@sergeygetto7480
@sergeygetto7480 3 жыл бұрын
Проблема была очень быстро решена, когда я просто учился языку python, я мог потратить буквально 3-4 дня на решение, какой-либо задачи. Оказалось проблема была совсем не в переменной x_train, она таилась в переменной y_train, проблема была такова: в y_train для преобразования данных классы добавляются в формате np.unit8(), а после чего данные классы преобразуются через np.to_categorical(), единственное, чего я не учёл это того, что классы должны начинаться исключительно с 0, т.е. если у вас есть 8 классов, то они должны быть пронумерованы от(0-7), чтобы данная функция смогла превратить их в нужный тип данных. Кстати говоря пришёл я к этому всего лишь пару дней переспав с мыслью решения данной задачи, а также посмотрев, что за ошибку выдаёт функция model.fit().
@ФедорКравец-ю1е
@ФедорКравец-ю1е 5 ай бұрын
А почему у нас на втором слое стало больше признаков (64) чем на первом(32) ?
@selfedu_rus
@selfedu_rus 5 ай бұрын
это все мы сами выбираем и придумываем, в общем, не почему; попробуйте другую конфигурацию, как пример
@iuriimusagitov9865
@iuriimusagitov9865 2 жыл бұрын
для чего все-таки стандартизация в виде "x_train = x_train / 255" ?
@selfedu_rus
@selfedu_rus 2 жыл бұрын
в данном примере особой нужды в этом нет, а вообще, чтобы данные имели тот же порядок, что и на обучающей выборке, т.к. сеть в дальнейшем будет ориентироваться на обученные входные значения (по величине)
@iuriimusagitov9865
@iuriimusagitov9865 2 жыл бұрын
@@selfedu_rus Благодарю!
@norasoul
@norasoul 3 жыл бұрын
Здравствуйте, спасибо за данный урок, но возник глупый вопрос: а у сверхточных нейронов тоже же есть веса связей и самих нейронов?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
в свертках такие же нейроны (та же математика), что и в обычных полносвязных сетях
@norasoul
@norasoul 3 жыл бұрын
@@selfedu_rus большое спасибо что ответили
@norasoul
@norasoul 3 жыл бұрын
@@selfedu_rus Простите за ещё одно обращение, но есть способ давать уже готовые веса (допустим хранятся в списке) и передавать их нейронной сети?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
@@norasoul да, load_weights() и save_weights() вроде, подробнее см. в документации по Keras
@selfedu_rus
@selfedu_rus 3 жыл бұрын
@@norasoul да, те же функции, см. документацию!!!
@wordofworld6874
@wordofworld6874 Жыл бұрын
С какого курса стоит начинать обучение? С этого или с kzbin.info/www/bejne/hH_bgp-lp72Jeqc ???
@selfedu_rus
@selfedu_rus Жыл бұрын
думаю, из этих двух, лучше с этого, а вообще, лучше с курса по машинному обучению (на этом же канале)
@rpuropu
@rpuropu 3 жыл бұрын
на тестовой наколдовал accuracy: 0.9917.. SGD)
@boriswithrazor6992
@boriswithrazor6992 3 жыл бұрын
А сколько примерно у Вас сеть обучалась по времени?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
Уже не помню, но все примеры не более часа.
@борисНагибов
@борисНагибов 2 жыл бұрын
я хочу задонатить, куда?
@ПавлоКабай
@ПавлоКабай 3 жыл бұрын
неплохо
@eugeneporter3650
@eugeneporter3650 3 жыл бұрын
А почему у Вас во втором слое в конце только 32 слоя, их же 64 должно быть?
@dmitrymitrofanov3920
@dmitrymitrofanov3920 4 жыл бұрын
Когда успеваеш?
@RelaxVideosofnature
@RelaxVideosofnature Жыл бұрын
'x_tarin' ашипка нашёл и домой я пошел 10:38
@yoyooyooyygygygygyg5379
@yoyooyooyygygygygyg5379 3 жыл бұрын
Проверил выборке MNIST, да, всё Ок! асс. 99%, заменил обучающую выборку на FASHIONMNIST - результат асс. 10% не пойму в чём проблема, не та структура сети?
@selfedu_rus
@selfedu_rus 3 жыл бұрын
В приницпе, должно работать, не проверял. Возможно просто что-то не так сделано с обучающей выборкой?
@bluesnake00
@bluesnake00 4 жыл бұрын
прокрутил 100 эпох у меня accuracy вместо 0.1 стало 0.85 а val_accuracy вообще не изменилось , даже уменьшилось, стало 0.07 вообще. И ещё сеть ни черта не распознаёт вообще!!ЧТО делать?Подскажите
@glebtutik6898
@glebtutik6898 3 жыл бұрын
Вы переобучили сеть
@alexseley8633
@alexseley8633 2 жыл бұрын
Не всегда много эпох решают точность модели
@alexandernikushin9856
@alexandernikushin9856 Жыл бұрын
попробовал. Загрузил свою цифру в нужном формате, а он 7 как 3 определяет =((
@Dreamcatcher_Lvl_
@Dreamcatcher_Lvl_ 11 ай бұрын
жиза
@MoRFaiR
@MoRFaiR 3 жыл бұрын
Тоже самое и с ядрами: "Ну пусть в нашем случае будет (3,3)". Почему три на три?? Почему на 70 на 70?..
@selfedu_rus
@selfedu_rus 3 жыл бұрын
Ядрами 3x3 можно легко описать и бОльшие окна, если взять последовательно несколько слоев с ядрами 3x3 (так сделано в VGG-16 и VGG-19 см. далее). По этой причине ядра 3x3 были оптимизированы NVidia и считаются предпочтительным выбором.
@bluesnake00
@bluesnake00 4 жыл бұрын
а что делат ьесли сеть не фига не учится и выдаёт любую чушь, но только не правильный ответ
@selfedu_rus
@selfedu_rus 4 жыл бұрын
скорее всего либо сеть неверно сформирована, либо обучающая выборка, в общем, ошибка где-то )
@MoRFaiR
@MoRFaiR 3 жыл бұрын
Пусть первый сверочный слой имеет 32 фильтра... Откуда цифра взялась, с какого потолка? ...Вообще не разъясняется
@selfedu_rus
@selfedu_rus 3 жыл бұрын
На этот вопрос нет ответа. Как выбирать архитектуру НС - открытый вопрос. В основном, опираются на похожие разработки и на собственный опыт (по моему, в пред. видео я об этом говорил).
FOREVER BUNNY
00:14
Natan por Aí
Рет қаралды 30 МЛН
Do you love Blackpink?🖤🩷
00:23
Karina
Рет қаралды 19 МЛН
Твоя ПЕРВАЯ НЕЙРОСЕТЬ на Python с нуля! | За 10 минут :3
18:31
Хауди Хо™ - Просто о мире IT!
Рет қаралды 278 М.
Нейронная сеть на Python с нуля
14:40
Дмитрий Коробченко
Рет қаралды 159 М.
Свёрточные нейронные сети
14:02
Самостоятельная работа
Рет қаралды 9 М.
Обучение нейронной сети на Python
21:34
Дмитрий Коробченко
Рет қаралды 62 М.