Описание проекта
Сетевой супермаркет «Хлеб-Соль» внедряет систему компьютерного зрения для обработки фотографий покупателей. Фотофиксация в прикассовой зоне поможет определять возраст клиентов, чтобы:
- Анализировать покупки и предлагать товары, которые могут заинтересовать покупателей этой возрастной группы;
- Контролировать добросовестность кассиров при продаже алкоголя.
Постройте модель, которая по фотографии определит приблизительный возраст человека. В вашем распоряжении набор фотографий людей с указанием возраста.
Инструкция по выполнению проекта
- Проведите исследовательский анализ набора фотографий. Сделайте выводы о том, как результаты исследования повлияют на обучение модели. Этапы анализа:
- Посмотрите на размер выборки.
- Постройте график распределения возраста в выборке.
- Напечатайте на экране 10–15 фотографий и посмотрите, как устроен датасет.
- Подготовьте данные к обучению.
- Обучите нейронную сеть и рассчитайте её качество.
Описание данных
Данные взяты с сайта ChaLearn Looking at People. Они находятся в папке /datasets/faces/
.
В вашем распоряжении одна папка со всеми изображениями (/final_files
) и CSV-файл labels.csv
с двумя колонками: file_name
и real_age
.
Извлечь данные из папки вам поможет новый метод ImageDataGenerator —flow_from_dataframe(dataframe, directory, ...)
.
Содержание
Исследовательский анализ данных¶
Подготовка тетради¶
Загрузка библиотек¶
# Базовые библиотеки
import pandas as pd
import numpy as np
# Нейросеть
from tensorflow.keras.layers import Conv2D, Flatten, GlobalAveragePooling2D, Dense, AvgPool2D
from tensorflow.keras.applications.resnet import ResNet50
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import Adam
# Графика
from PIL import Image # Просмотр изображений
import matplotlib.pyplot as plt
Создание глобальных переменных¶
# Загрузка и проверка датафрейма
FACES_DIR = '/datasets/faces/'
Загрузка и предварительный анализ данных¶
Анализ датафрейма с данными¶
# Загрузка датафрейма
data = pd.read_csv(FACES_DIR + 'labels.csv')
# Анализ датафрейма
data.head(10)
file_name | real_age | |
---|---|---|
0 | 000000.jpg | 4 |
1 | 000001.jpg | 18 |
2 | 000002.jpg | 80 |
3 | 000003.jpg | 50 |
4 | 000004.jpg | 17 |
5 | 000005.jpg | 27 |
6 | 000006.jpg | 24 |
7 | 000007.jpg | 43 |
8 | 000008.jpg | 26 |
9 | 000009.jpg | 39 |
# Анализ данных датафрейма
data.info()
data.hist(bins=100)
plt.title('Распределение количества объектов по возрастам')
plt.xlabel('Возраст')
plt.ylabel('Количество объектов')
data.describe()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 7591 entries, 0 to 7590 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 file_name 7591 non-null object 1 real_age 7591 non-null int64 dtypes: int64(1), object(1) memory usage: 118.7+ KB
real_age | |
---|---|
count | 7591.000000 |
mean | 31.201159 |
std | 17.145060 |
min | 1.000000 |
25% | 20.000000 |
50% | 29.000000 |
75% | 41.000000 |
max | 100.000000 |
Выводы из анализа датафрейма
- В датафрейме всего 7591 объект, каждый из которых должен соответствовать файлу датасета. Подобного количества объектов должно быть достаточно для обучения нейросети, ранее обученной на большей выбоке.
- В датафрейме 2 признака:
file_name
с именами файлов и целевой признакreal_age
с возрастами людей, изображенных в файлах. Целевой признак имеет целочисленные значения, где каждое число означает год. - Датафрейм не содержит пропусков.
- Данные распределены нормально от 1 до 100 лет с большим всплеском ближе к нулю. При этом, вершина «колокола» нормального распределения смещена влево. Пик расположен на значении возраста в 25-30 лет. К этому возрасту относится более 1100 объектов. Медиана приходится на возраст 29 лет. Требуется выравнить распределение количества объектов между разными возрастами для равной вероятности их предсказания.
- Наблюдаются отдельные всплески в значениях возрастов кратных 5. Это может свидетельствовать о возможном округлении целевых значений возрастов при их разметке. Это будет создавать помехи для предсказания точного возраста.
Анализ изображений¶
# Анализ информации о первом изображении датасета
file_dir = FACES_DIR + 'final_files/000000.jpg'
image = Image.open(file_dir)
array = np.array(image)
print('Файл :', data.loc[0, 'file_name'])
print('Возраст :', data.loc[0, 'real_age'])
print('Размерность:', array.shape)
print()
print(array)
Файл : 000000.jpg Возраст : 4 Размерность: (114, 114, 3) [[[129 70 36] [168 112 77] [169 115 77] ... [150 103 83] [157 110 94] [158 111 95]] [[133 77 42] [162 106 71] [165 111 73] ... [171 123 103] [169 124 105] [169 124 105]] [[118 62 29] [129 73 40] [131 77 41] ... [187 134 116] [180 135 112] [180 135 112]] ... [[112 65 19] [115 68 22] [119 72 26] ... [211 155 70] [191 140 57] [191 140 57]] [[115 74 30] [102 61 17] [ 96 55 9] ... [202 142 56] [192 135 56] [199 142 63]] [[113 72 28] [ 99 58 14] [ 94 53 7] ... [195 135 49] [192 135 56] [199 142 63]]]
# Анализ 15 изображений
# и информации о них из датафрейма
for i in range(0, 15, 1):
print()
print('Файл :', data.loc[i, 'file_name'])
print('Возраст :', data.loc[i, 'real_age'])
if i < 10:
file_dir = FACES_DIR + 'final_files/00000'+ str(i) + '.jpg'
elif i < 100:
file_dir = FACES_DIR + 'final_files/0000'+ str(i) + '.jpg'
image = Image.open(file_dir)
array = np.array(image)
print('Размерность:', array.shape)
plt.imshow(array, cmap='gray')
#plt.colorbar()
plt.axis('off')
plt.show()
Файл : 000000.jpg Возраст : 4 Размерность: (114, 114, 3)
Файл : 000001.jpg Возраст : 18 Размерность: (784, 784, 3)
Файл : 000002.jpg Возраст : 80 Размерность: (133, 133, 3)
Файл : 000003.jpg Возраст : 50 Размерность: (370, 370, 3)
Файл : 000004.jpg Возраст : 17 Размерность: (212, 212, 3)
Файл : 000005.jpg Возраст : 27 Размерность: (636, 637, 3)
Файл : 000006.jpg Возраст : 24 Размерность: (412, 412, 3)
Файл : 000007.jpg Возраст : 43 Размерность: (311, 311, 3)
Файл : 000008.jpg Возраст : 26 Размерность: (898, 897, 3)
Файл : 000009.jpg Возраст : 39 Размерность: (724, 724, 3)
Файл : 000010.jpg Возраст : 17 Размерность: (636, 636, 3)
Файл : 000011.jpg Возраст : 51 Размерность: (803, 803, 3)
Файл : 000012.jpg Возраст : 2 Размерность: (155, 155, 3)
Файл : 000013.jpg Возраст : 1 Размерность: (321, 321, 3)
Файл : 000014.jpg Возраст : 6 Размерность: (203, 204, 3)
Выводы из анализа изображений
- Датасет содержит файлы фотографий множества людей разного возраста и пола выполненных в разных условиях осещения и с разным фоном.
- Все изображения содержаться в файлах формата
jpg
, имеют три цветовых каналаRGB
, квадратную форму и разные размеры. Для предсказания потребуется предобученной сверточная нейросеть типаResNet
. - Изображения расположены в отдельных файлах собранных в одну директорию. Для работы с ними требуется использовать метод
ImageDataGenerator
—flow_from_dataframe
. - Фотографии ранее обработаны таким образом, что лица расположены практически вертикально и занимают большую часть изображения. Это означает, что не требуется дополнительная обработка изображений. Достаточно использовать аугментацию в процессе подготовки треннировочных данных.
- Часть фотографий содержат артефакты в виде черного и белого фона, оставшегося после поворота и обрезки фотографий. Также, на некоторых изображениях имеются «растянутые» пиксели.
- Проанализированные фотографии из датасета размечены верно и приблизительно соответствуют возрасту, указнному в соовтетствующих им объектах датафрейма.
Выводы из анализа¶
На основе анализа датасета с изображениями и датафрейма с данными об изображениях сделаны выводы о том, что ребуется:
- Перед обучением выравнить распределение количества объектов между разными возрастами для равной вероятности их предсказания.
- В процессе обучения использовать метод
ImageDataGenerator
—flow_from_dataframe
и предобученную сверточную нейросеть типаResNet
.
Обучение модели¶
В этом разделе расположен код обучения модели и её результат вывода на экран.
(Код в этом разделе запускается в отдельном GPU-тренажёре, поэтому оформлен не как ячейка с кодом, а как код в текстовой ячейке)
# Базовые библиотеки
import pandas as pd
import numpy as np
# Нейросеть
from tensorflow.keras.layers import Conv2D, Flatten, GlobalAveragePooling2D, Dense, AvgPool2D
from tensorflow.keras.applications.resnet import ResNet50
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import Adam
# Графика
from PIL import Image # Просмотр изображений
import matplotlib.pyplot as plt
# Функция подготовки тренировочных данных
def load_train(path):
datagen = ImageDataGenerator(
rotation_range = 40,
width_shift_range = 30,
height_shift_range = 30,
zoom_range = [.8, .8],
horizontal_flip = True,
rescale=1./255,
validation_split=.25
)
datagen_flow = datagen.flow_from_dataframe(
dataframe=pd.read_csv(path + 'labels.csv'),
#labels='inferred',
directory=path + 'final_files/',
x_col='file_name',
y_col='real_age',
target_size=(224, 224),
#batch_size=16,
class_mode='raw',
subset='training',
seed=12345
)
return datagen_flow
# Функция подготовки тестовых данных
def load_test(path):
datagen = ImageDataGenerator(
rescale=1./255,
validation_split=.25)
datagen_flow = datagen.flow_from_dataframe(
dataframe=pd.read_csv(path + 'labels.csv') ,
directory=path + 'final_files/',
x_col='file_name',
y_col='real_age',
target_size=(224, 224),
#sbatch_size=16,
class_mode='raw',
subset='validation',
seed=12345
)
return datagen_flow
# Функция создания модели нейросети
def create_model(input_shape):
backbone = ResNet50(input_shape=input_shape,
weights='/datasets/keras_models/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5',
#weights='imagenet',
include_top=False)
model = Sequential()
model.add(backbone)
model.add(GlobalAveragePooling2D())
model.add(Dense(1, activation='relu'))
optimizer_adam = Adam(lr=.00001)
model.compile(optimizer=optimizer_adam,
loss='mean_squared_error',
metrics=['mean_absolute_error'])
model.summary()
return model
# Функция обучения модели нейросети
def train_model(model,train_datagen_flow,
test_datagen_flow,
batch_size=None, epochs=15,
steps_per_epoch=None,
validation_steps=None):
model.fit(train_datagen_flow,
validation_data=test_datagen_flow,
batch_size=batch_size,
epochs=epochs,
steps_per_epoch=steps_per_epoch,
validation_steps=validation_steps,
verbose=2, shuffle=True)
return model
2023-10-13 13:28:56.783580: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6
2023-10-13 13:28:56.785276: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer_plugin.so.6
2023-10-13 13:28:57.646984: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2023-10-13 13:28:57.655853: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1555] Found device 0 with properties:
pciBusID: 0000:8b:00.0 name: Tesla V100-SXM2-32GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 31.75GiB deviceMemoryBandwidth: 836.37GiB/s
2023-10-13 13:28:57.655915: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:57.655946: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:28:57.657733: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10
2023-10-13 13:28:57.658079: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10
2023-10-13 13:28:57.660069: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10
2023-10-13 13:28:57.661169: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10
2023-10-13 13:28:57.661225: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2023-10-13 13:28:57.663558: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1697] Adding visible gpu devices: 0
Using TensorFlow backend.
Found 5694 validated image filenames.
Found 1897 validated image filenames.
2023-10-13 13:28:59.126883: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
2023-10-13 13:28:59.133741: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2100000000 Hz
2023-10-13 13:28:59.134193: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x4f699e0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2023-10-13 13:28:59.134217: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
2023-10-13 13:28:59.314905: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x4f84900 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
2023-10-13 13:28:59.314948: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Tesla V100-SXM2-32GB, Compute Capability 7.0
2023-10-13 13:28:59.316292: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1555] Found device 0 with properties:
pciBusID: 0000:8b:00.0 name: Tesla V100-SXM2-32GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 31.75GiB deviceMemoryBandwidth: 836.37GiB/s
2023-10-13 13:28:59.316348: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:59.316359: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:28:59.316388: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10
2023-10-13 13:28:59.316400: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10
2023-10-13 13:28:59.316413: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10
2023-10-13 13:28:59.316425: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10
2023-10-13 13:28:59.316433: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2023-10-13 13:28:59.318671: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1697] Adding visible gpu devices: 0
2023-10-13 13:28:59.318720: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:59.945897: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1096] Device interconnect StreamExecutor with strength 1 edge matrix:
2023-10-13 13:28:59.945956: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1102] 0
2023-10-13 13:28:59.945967: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] 0: N
2023-10-13 13:28:59.949552: W tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:39] Overriding allow_growth setting because the TF_FORCE_GPU_ALLOW_GROWTH environment variable is set. Original config value was 0.
2023-10-13 13:28:59.949616: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 10240 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-32GB, pci bus id: 0000:8b:00.0, compute capability: 7.0)
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
resnet50 (Model) (None, 7, 7, 2048) 23587712
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048) 0
_________________________________________________________________
dense (Dense) (None, 1) 2049
=================================================================
Total params: 23,589,761
Trainable params: 23,536,641
Non-trainable params: 53,120
_________________________________________________________________
<class 'tensorflow.python.keras.engine.sequential.Sequential'>
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
Train for 178 steps, validate for 60 steps
Epoch 1/15
2023-10-13 13:29:13.419813: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:29:14.008287: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
178/178 - 115s - loss: 912.0856 - mean_absolute_error: 25.2353 - val_loss: 1132.8731 - val_mean_absolute_error: 29.1857
Epoch 2/15
178/178 - 104s - loss: 300.1206 - mean_absolute_error: 13.1046 - val_loss: 1154.0420 - val_mean_absolute_error: 29.5457
Epoch 3/15
178/178 - 104s - loss: 162.3667 - mean_absolute_error: 9.3622 - val_loss: 1100.6221 - val_mean_absolute_error: 28.7697
Epoch 4/15
178/178 - 100s - loss: 121.4088 - mean_absolute_error: 8.1426 - val_loss: 299.2196 - val_mean_absolute_error: 13.3489
Epoch 5/15
178/178 - 95s - loss: 103.6374 - mean_absolute_error: 7.6085 - val_loss: 105.8444 - val_mean_absolute_error: 7.7642
Epoch 6/15
178/178 - 96s - loss: 91.2088 - mean_absolute_error: 7.2005 - val_loss: 93.7318 - val_mean_absolute_error: 7.2731
Epoch 7/15
178/178 - 95s - loss: 82.4739 - mean_absolute_error: 6.9012 - val_loss: 88.5470 - val_mean_absolute_error: 7.1817
Epoch 8/15
178/178 - 97s - loss: 73.3976 - mean_absolute_error: 6.5202 - val_loss: 83.8626 - val_mean_absolute_error: 6.9451
Epoch 9/15
178/178 - 95s - loss: 68.3407 - mean_absolute_error: 6.2948 - val_loss: 87.0837 - val_mean_absolute_error: 7.1503
Epoch 10/15
178/178 - 95s - loss: 65.1655 - mean_absolute_error: 6.1743 - val_loss: 89.9151 - val_mean_absolute_error: 7.0716
Epoch 11/15
178/178 - 94s - loss: 61.2360 - mean_absolute_error: 6.0194 - val_loss: 94.0438 - val_mean_absolute_error: 7.2199
Epoch 12/15
178/178 - 100s - loss: 57.8289 - mean_absolute_error: 5.8463 - val_loss: 91.6314 - val_mean_absolute_error: 7.1323
Epoch 13/15
178/178 - 96s - loss: 54.3197 - mean_absolute_error: 5.6740 - val_loss: 84.1345 - val_mean_absolute_error: 6.8958
Epoch 14/15
178/178 - 95s - loss: 52.1032 - mean_absolute_error: 5.5688 - val_loss: 98.3294 - val_mean_absolute_error: 7.3483
Epoch 15/15
178/178 - 92s - loss: 48.7260 - mean_absolute_error: 5.4116 - val_loss: 85.0145 - val_mean_absolute_error: 6.9589
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
60/60 - 10s - loss: 85.0145 - mean_absolute_error: 6.9589
Test MAE: 6.9589
2023-10-13 13:28:56.783580: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6
2023-10-13 13:28:56.785276: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer_plugin.so.6
2023-10-13 13:28:57.646984: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2023-10-13 13:28:57.655853: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1555] Found device 0 with properties:
pciBusID: 0000:8b:00.0 name: Tesla V100-SXM2-32GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 31.75GiB deviceMemoryBandwidth: 836.37GiB/s
2023-10-13 13:28:57.655915: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:57.655946: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:28:57.657733: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10
2023-10-13 13:28:57.658079: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10
2023-10-13 13:28:57.660069: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10
2023-10-13 13:28:57.661169: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10
2023-10-13 13:28:57.661225: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2023-10-13 13:28:57.663558: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1697] Adding visible gpu devices: 0
Using TensorFlow backend.
Found 5694 validated image filenames.
Found 1897 validated image filenames.
2023-10-13 13:28:59.126883: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
2023-10-13 13:28:59.133741: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2100000000 Hz
2023-10-13 13:28:59.134193: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x4f699e0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2023-10-13 13:28:59.134217: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
2023-10-13 13:28:59.314905: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x4f84900 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
2023-10-13 13:28:59.314948: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Tesla V100-SXM2-32GB, Compute Capability 7.0
2023-10-13 13:28:59.316292: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1555] Found device 0 with properties:
pciBusID: 0000:8b:00.0 name: Tesla V100-SXM2-32GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 31.75GiB deviceMemoryBandwidth: 836.37GiB/s
2023-10-13 13:28:59.316348: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:59.316359: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:28:59.316388: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10
2023-10-13 13:28:59.316400: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10
2023-10-13 13:28:59.316413: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10
2023-10-13 13:28:59.316425: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10
2023-10-13 13:28:59.316433: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2023-10-13 13:28:59.318671: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1697] Adding visible gpu devices: 0
2023-10-13 13:28:59.318720: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.1
2023-10-13 13:28:59.945897: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1096] Device interconnect StreamExecutor with strength 1 edge matrix:
2023-10-13 13:28:59.945956: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1102] 0
2023-10-13 13:28:59.945967: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] 0: N
2023-10-13 13:28:59.949552: W tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:39] Overriding allow_growth setting because the TF_FORCE_GPU_ALLOW_GROWTH environment variable is set. Original config value was 0.
2023-10-13 13:28:59.949616: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 10240 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-32GB, pci bus id: 0000:8b:00.0, compute capability: 7.0)
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
resnet50 (Model) (None, 7, 7, 2048) 23587712
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048) 0
_________________________________________________________________
dense (Dense) (None, 1) 2049
=================================================================
Total params: 23,589,761
Trainable params: 23,536,641
Non-trainable params: 53,120
_________________________________________________________________
<class 'tensorflow.python.keras.engine.sequential.Sequential'>
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
Train for 178 steps, validate for 60 steps
Epoch 1/15
2023-10-13 13:29:13.419813: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
2023-10-13 13:29:14.008287: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
178/178 - 115s - loss: 912.0856 - mean_absolute_error: 25.2353 - val_loss: 1132.8731 - val_mean_absolute_error: 29.1857
Epoch 2/15
178/178 - 104s - loss: 300.1206 - mean_absolute_error: 13.1046 - val_loss: 1154.0420 - val_mean_absolute_error: 29.5457
Epoch 3/15
178/178 - 104s - loss: 162.3667 - mean_absolute_error: 9.3622 - val_loss: 1100.6221 - val_mean_absolute_error: 28.7697
Epoch 4/15
178/178 - 100s - loss: 121.4088 - mean_absolute_error: 8.1426 - val_loss: 299.2196 - val_mean_absolute_error: 13.3489
Epoch 5/15
178/178 - 95s - loss: 103.6374 - mean_absolute_error: 7.6085 - val_loss: 105.8444 - val_mean_absolute_error: 7.7642
Epoch 6/15
178/178 - 96s - loss: 91.2088 - mean_absolute_error: 7.2005 - val_loss: 93.7318 - val_mean_absolute_error: 7.2731
Epoch 7/15
178/178 - 95s - loss: 82.4739 - mean_absolute_error: 6.9012 - val_loss: 88.5470 - val_mean_absolute_error: 7.1817
Epoch 8/15
178/178 - 97s - loss: 73.3976 - mean_absolute_error: 6.5202 - val_loss: 83.8626 - val_mean_absolute_error: 6.9451
Epoch 9/15
178/178 - 95s - loss: 68.3407 - mean_absolute_error: 6.2948 - val_loss: 87.0837 - val_mean_absolute_error: 7.1503
Epoch 10/15
178/178 - 95s - loss: 65.1655 - mean_absolute_error: 6.1743 - val_loss: 89.9151 - val_mean_absolute_error: 7.0716
Epoch 11/15
178/178 - 94s - loss: 61.2360 - mean_absolute_error: 6.0194 - val_loss: 94.0438 - val_mean_absolute_error: 7.2199
Epoch 12/15
178/178 - 100s - loss: 57.8289 - mean_absolute_error: 5.8463 - val_loss: 91.6314 - val_mean_absolute_error: 7.1323
Epoch 13/15
178/178 - 96s - loss: 54.3197 - mean_absolute_error: 5.6740 - val_loss: 84.1345 - val_mean_absolute_error: 6.8958
Epoch 14/15
178/178 - 95s - loss: 52.1032 - mean_absolute_error: 5.5688 - val_loss: 98.3294 - val_mean_absolute_error: 7.3483
Epoch 15/15
178/178 - 92s - loss: 48.7260 - mean_absolute_error: 5.4116 - val_loss: 85.0145 - val_mean_absolute_error: 6.9589
WARNING:tensorflow:sample_weight modes were coerced from
...
to
['...']
60/60 - 10s - loss: 85.0145 - mean_absolute_error: 6.9589
Test MAE: 6.9589
Анализ обученной модели¶
Цель обучения нейросети достигнута. В результате выполнения кода, созданной нейросети на GPU с валидационными данными, получено значение показателя «MAE» равного 6.9589. Это меньше целевого значания 8. Так как «MAE» измеряется в абсолютных величинах, то полученый результат означает, что созданная модель ошибается в предсказании возраста человека по его фотографиии не более чем 6.9589 лет.
С точки зрения использования данной модели в реальном бизнесе получен не самый точный результат. Причина в использованном датасете. В нем фотографии людей в основном среднего возраста. Фотографий детей, особенно среднего школьного возраста, и людей приклонного возраста не достаточно для полноценного обучения модели. Если датасет с фотографиями дополнить объектами в тех возрастных категориях, где количества изображений относительно мало, то качество модели будет лучше. Также на качестве обучения сказалось возможное округление до 5 целевых значений в ряде случаем. Это возможно исправить только более качественной разметкой целевых признаков.
Данная модель рекоммендуется для использования в сервисе, анализирующем покупки и предлагающем товары, которые могут заинтересовать покупателей возрастной группы анализ. Модель не рекоммендуется длля контроля добросовестности кассиров при продаже алкоголя.
Чек-лист¶
- [x] Jupyter Notebook открыт
- [x] Весь код выполняется без ошибок
- [x] Ячейки с кодом расположены в порядке исполнения
- [x] Исследовательский анализ данных выполнен
- [x] Результаты исследовательского анализа данных перенесены в финальную тетрадь
- [x] MAE модели не больше 8
- [x] Код обучения модели скопирован в финальную тетрадь
- [x] Результат вывода модели на экран перенесён в финальную тетрадь
- [x] По итогам обучения модели сделаны выводы