Каково это иметь небольшой набор данных в глубоком обучении?

искусственный интеллект глубокое обучение

предисловие

Сегодня я подниму относительно простую тему и кратко расскажу о влиянии размера набора данных на обучение глубокому обучению. Не знаю, читали ли вы эту статью:Don't use deep learning your data isn't that big QQ20180605-002523@2x

Да, кто-то предоставил доказательство ограничений глубокого обучения: то есть, когда у вас меньше данных, эффект глубокого обучения не имеет преимуществ перед другими традиционными методами, наоборот, эффект не так хорош, как у традиционных методов.

Автор, сделавший это утверждение, провел тестирование с использованием двух методов: тестовый набор данных был MNIST, и тестовый компьютер мог правильно идентифицировать 0 и 1. Использовались следующие методы:

  • 5-слойная глубокая нейронная сеть, живой функцией является функция гиперболического тангенса;
  • Другой метод использует метод выбора переменной Ликассо, Идея этого метода состоит в том, чтобы выбрать 10 пикселей с наименьшим предельным значением p для выполнения (используйте эти значения для регрессии);

Тогда сделайте вывод:unnamed-chunk-7-1

То есть использование метода Ликассо превосходит нейронную сеть. какие?

текст

Итак, вернемся к теме: верно ли приведенное выше утверждение?Можем ли мы правильно выполнять обучение глубокому обучению, когда данных относительно мало, чтобы достичь удовлетворительных результатов?

Все мы знаем, что нейронные сети эквивалентны неограниченной универсальной функции, мы вводим переменныеxзатем получить результатy, испытал много сложных вычислительных процессов в середине. Теоретически проблемы, которые можно решить с помощью традиционных алгоритмов, можно решить с помощью глубокого обучения, но если нейронная сеть достаточно глубокая, хотя функция этой сети очень мощная, если данных недостаточно, этого легко добиться. явление переоснащения, чтобы добиться желаемого эффекта.

Итак, можно ли определить, является ли набор данных слишком маленьким, с помощью глубокого обучения, давайте проверим его.

одномерный сигнал

Наши тестовые данные очень просты, это не трехканальное изображение RGB, которое мы обычно используем (3 x 256 x 256), а обычный одноканальный одномерный сигнал (1 x 168).

signal

Выше показан наш одномерный сигнал, 532нм и 1064мн соответствуют двум разным сигналам соответственно, нам нужен только один сигнальный процессор. Формат сигнала - файл .mat, который является файлом Matlab.

В приведенном выше файле набор данных поезда имеет размер 161 x 168, первая строка — это координаты по оси X, нам не нужно заботиться о данных по оси Y, а затем каждые 40 наборов данных представляют собой класс 2-41, 42-81, 82-121, 122-161, всего четыре категории. Тестовый набор данных 81х168, а первая строка тоже x-координата, нам все равно, каждые 20 наборов данных — это класс (такой же, как набор данных поезда в заказе). Другими словами, у нас есть всего четыре типа сигналов, которые нужно классифицировать.

Этикетки:0、1、2、3.

Наш объем тренировочных данных составляет всего 160 наборов, а объем тестовых данных - всего 80 наборов.

чтение данных

Используемая нами библиотека глубокого обученияPytorch, с использованиемpythonВверхscipyБиблиотекаscipyЭто библиотека обработки линейных функций, конечно, мы просто используем ее функцию чтения для матовых файлов.

Создайте файл для чтения.py, импортируйте следующие файлы заголовков.

import torch
import torch.utils.data as data
import scipy.io
import os
import os.path as osp

Затем пишем класс чтения файла.py:

# 将原始数据转化为训练需要的数据格式
def to_tensor(data):
    data = torch.from_numpy(data).type(torch.float32)
    data = data.unsqueeze(0)
    return data


# 读取数据类
class LineData(data.Dataset):

    def __init__(self, root, name=532, train=True, transform=to_tensor):
        self.root = os.path.expanduser(root)
        self.name = name
        self.train = train
        self.transform = transform
        self.classes = [0, 1, 2, 3]

        if not osp.exists('datasets'):
            raise FileExistsError('Missing Datasets')

        if self.train:
            self.train_datas = []
            self.train_labels = []

            dataset_dir = osp.join(self.root, 'train_{}nm.mat'.format(self.name))
            train_data = scipy.io.loadmat(dataset_dir)['lineIntensity']
            data_length = len(train_data) - 1              # 161 - 1 = 160

            if self.transform:

                for i in range(data_length):                   # 0 - 159
                    self.train_datas.append(transform(train_data[i+1]))        # i+1 => 1 - 160
                    self.train_labels.append(self.classes[int(i / 40)])
            else:
                raise ValueError('We need tranform function!')

        if not self.train:
            self.test_datas = []
            self.test_labels = []

            dataset_dir = osp.join(self.root, 'test_{}nm.mat'.format(self.name))
            test_data = scipy.io.loadmat(dataset_dir)['lineIntensity']
            data_length = len(test_data) - 1              # 81 - 1 = 80

            if self.transform:

                for i in range(data_length):                   # 0 - 79
                    self.test_datas.append(transform(test_data[i+1]))         # i+1 => 1 - 80
                    self.test_labels.append(self.classes[int(i / 20)])
            else:
                raise ValueError('We need tranform function!')

    def __getitem__(self, index):
        """
        Args:
            index (int): Index

        Returns:
            tuple: (image, target) where target is index of the target class.
        """
        if self.train:
            data, target = self.train_datas[index], self.train_labels[index]
        else:
            data, target = self.test_datas[index], self.test_labels[index]

        return data, target

    def __len__(self):
        if self.train:
            return len(self.train_datas)
        else:
            return len(self.test_datas)

Написать нейронную сеть

Написав код чтения файла, давайте спроектируем нейронную сеть, поскольку объем данных небольшой, количество слоев нашей нейронной сети также должно уменьшаться. В противном случае легко может произойти переобучение.

Сначала мы проектируем 5-слойную нейронную сеть, два сверточных слоя, один объединяющий слой, два линейных слоя, а функция активации использует Relu:

每个数据的长度为168
模型:两个个卷积层、两个线性层
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv1d(1, 10, 3)    # (168 - 3)/1 + 1 = 166 (* 10)
        self.pool = nn.MaxPool1d(2, 2)      # (166 - 2)/2 + 1= 83 (* 10)
        self.conv2 = nn.Conv1d(10, 20, 3)   # (83 - 3)/1 + 1 = 81 (* 20)
        self.fc1 = nn.Linear(81*20, 100)
        self.fc2 = nn.Linear(100, 4)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = F.relu(self.conv2(x))
        x = x.view(-1, 81*20)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

тренируйся и тестируй

После проектирования нейронной сети давайте обучим ее!

Сначала напишите код для тренировочного блока, используемой нами стратегии оптимизации является метод стохастического спуска SGD (с кинетической энергией), а скорость обучения по умолчанию установлена ​​на0.001, метод проверки принимает классическую классификацию, обычно используемый метод проверкиCrossEntropyLoss.

Сначала мы тренируем, а затем проверяем точность, которая представляет собой отношение правильного количества раз к общему количеству раз для каждого из этих четырех сигналов в каждом тесте.

# 主程序页面

import torch
import torch.nn as nn
import torch.utils.data
import torch.optim as optim
from model import Net
from data_utils import LineData

root = 'datasets'    # 数据所在目录,相对目录地址
train_name = '532'   # 或者 '1064'

# device = torch.device('cuda:0')

# 读取文件类
trainset = LineData(root, name=train_name)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True)

testset = LineData(root, name=train_name, train=False)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=True)

net = Net()
# net = net.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# 下面的epoch改成 2 可以达到100%的准确率
epoch_sum = 1
# 训练
for epoch in range(epoch_sum):

    loss_sum = 0.0
    for i, data in enumerate(trainloader, 0):

        inputs, labels = data
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        loss_sum += loss.item()
        if i % 10 == 9:
            print('[epoch:{} num:{}] loss:{}'.format(epoch, i, loss_sum / 20))
            loss_sum = 0.0

print('Finished Training')

# 验证
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        inputs, labels = data
        outputs = net(inputs)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 80 test images: %d %%' % (
    100 * correct / total))

pass

Ок, приступаем к обучению, потому что объемов данных немного, поэтому обучение на CPU.

Первое обучение, эпоха 1, lr 0,001:

[epoch:0 num:9] loss:1.693671927541118e+16
[epoch:0 num:19] loss:53694975.30745087
[epoch:0 num:29] loss:6.2672371854667905e+28
[epoch:0 num:39] loss:51403236.52956776
Finished Training
Accuracy of the network on the 80 test images: 25 %

Результат выглядит очень плохо... Точность 25%, вроде угадывает, проигрыш сильно колеблется, должно быть, у нас слишком высокая скорость обучения настроена, а потом регулировать скорость обучения.

Второе обучение, эпоха 1, lr 0,0001:

[epoch:0 num:9] loss:133432.54784755706
[epoch:0 num:19] loss:67940.00796541572
[epoch:0 num:29] loss:109.18773172795773
[epoch:0 num:39] loss:1.1358043849468231
Finished Training
Accuracy of the network on the 80 test images: 25 %

Потеря падает очень плавно, но эпохи кажется недостаточно, поэтому потеря не падает полностью, и показатель точности все еще очень низок Давайте настроим эпоху.

Третье обучение, эпоха 5, lr 0,0001:

[epoch:0 num:9] loss:3024598166.2773805
[epoch:0 num:19] loss:3117157163.829549
[epoch:0 num:29] loss:258.4028107881546
[epoch:0 num:39] loss:0.6990358293056488
[epoch:1 num:9] loss:0.6830220401287079
[epoch:1 num:19] loss:66.56461009383202
[epoch:1 num:29] loss:0.7117315053939819
[epoch:1 num:39] loss:0.6977931916713714
[epoch:2 num:9] loss:0.6974189281463623
[epoch:2 num:19] loss:0.6898959457874299
[epoch:2 num:29] loss:0.7101178288459777
[epoch:2 num:39] loss:0.6914324820041656
[epoch:3 num:9] loss:0.686737447977066
[epoch:3 num:19] loss:0.6972651600837707
[epoch:3 num:29] loss:0.7028001189231873
[epoch:3 num:39] loss:0.6998239696025849
[epoch:4 num:9] loss:0.6997098863124848
[epoch:4 num:19] loss:0.6969940900802613
[epoch:4 num:29] loss:0.696108078956604
[epoch:4 num:39] loss:0.6910847663879395
Finished Training
Accuracy of the network on the 80 test images: 25 %

Потеря падает до определенного уровня и больше не падает, а уровень точности все еще очень сбивает с толку.Возможно, потеря застряла в диапазоне и не может быть полностью уменьшена, потому что скорость обучения слишком высока.Попробуем снова снизить скорость обучения.

Четвертое обучение, эпоха 2, lr 0,00001:

[epoch:0 num:9] loss:200.58453428081702
[epoch:0 num:19] loss:5.724525341391564
[epoch:0 num:29] loss:0.2976263818090047
[epoch:0 num:39] loss:0.05558242934057489
[epoch:1 num:9] loss:0.0004892532759185996
[epoch:1 num:19] loss:0.00012833428763769916
[epoch:1 num:29] loss:9.479262493137242e-05
[epoch:1 num:39] loss:3.948449189010717e-05
Finished Training
Accuracy of the network on the 80 test images: 100 %

Отлично, похоже, мы вычислили правильную скорость обучения (0.00001), после 10 тестов показатели точности составляют: 100 %, 100 %, 100 %, 100 %, 100 %, 100 %, 100 %, 100 %, 100 %, 98 %.

Если я изменю эпоху с 2 на 1, это будет 100%, 77%, 100%, 100%, 100%, 86%, 100%, 100%, 100%, 100%.

Эпоха меняется от 1 до 3: 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%.

Если мы изменим слой нейронной сети, чтобы он был трехслойным полностью связанным слоем, lr равен0.00001Эффект будет плохой, даже тренировка больше 10 эпох не достигнет 100% точности, но если сбросить лр до0.000001, точность достигнет 100%:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(168, 1000)
        self.fc2 = nn.Linear(1000, 100)
        self.fc3 = nn.Linear(100,4)

    def forward(self, x):
        x = x.view(-1, 168)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

в заключении

С помощью приведенного выше теста кажется, что набор данных в пределах числа 200, если уровень проектирования является разумным и скорость обучения является соответствующей, уровень точности также может достичь лучших результатов.

На самом деле переобучение часто происходит из-за того, что количество слоев спроектированной нами нейросети слишком глубокое, а данных не так много, нейросеть будет полностью «выжимать» обучающие данные и впитывать информацию обучающей выборки чрезмерно, что приводит к тесту Время не так точно.Говорят, что если набор данных слишком мал, ошибку можно уменьшить, уменьшив количество слоев.

Однако, если данные содержат богатую информацию, но объем данных невелик, в настоящее время недостаточно настроить количество слоев Нам нужны некоторые методы улучшения данных, чтобы расширить набор данных, чтобы «кормить» нейронную сеть. и предотвратить появление нейронной сети ненормальной. Конечно, расширение набора данных реализовано для информации, которая содержит много информации.Если информация похожа на одномерный сигнал, который мы использовали ранее, расширение обычно не требуется.

дразни меня

  • Если вы со мной единомышленники, Лао Пан очень хочет с вами общаться;
  • Если вам нравится контент Лао Пана, подпишитесь и поддержите его.
  • Если вам понравилась моя статья, надеюсь, она вам понравится? Избранное ? Комментарии ? Три в ряд~

Я хочу знать, как Лао Пан научился наступать на яму, и я хочу обменяться со мной вопросами ~ Пожалуйста, обратите внимание на публичный аккаунт "старый блог". Лао Пан также организует некоторые из своих частных коллекций, надеясь помочь всем, нажмитеТаинственный порталПолучать.