Классификация наименьших квадратов с тензорным потоком
Когда дело доходит до классификации, каждый, кто знаком с линейной регрессией, может перенести знания из регрессии и сказать, почему бы нам не применить ту же простую идею и для классификации?
Ответ на этот вопрос приведет нас к классификации по методу наименьших квадратов. Основная идея состоит в том, чтобы умножить вектор признаков на матрицу весов, которая представляет собой просто комбинацию нескольких столбцов, каждый из которых отвечает за класс. Функция потерь представляет собой квадратную разницу между предсказанной меткой и золотой меткой. Этот алгоритм на самом деле прост, но для получения дополнительной информации, плюсов и минусов читатель может обратиться к главе 4 книги епископа.
В качестве моего последнего поста я реализую алгоритм на наборе данных hcr, который является популярным набором данных в анализе настроений, но с помощью тензорного потока. Подробнее об анализе настроений смотрите здесь.
Прежде всего, мы импортируем все необходимые библиотеки:
import pandas as pd import matplotlib.pyplot as plt from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score import tensorflow as tf import numpy as np
Затем нам нужно импортировать данные:
train = pd.read_csv(‘/content/drive/My Drive/Colab Notebooks/GCN/Least Square/data/hcr/train/orig/hcr-train.csv’) train[‘sentiment’] = train[‘sentiment’].str.strip() dev = pd.read_csv(‘/content/drive/My Drive/Colab Notebooks/GCN/Least Square/data/hcr/dev/orig/hcr-dev.csv’) dev[‘sentiment’] = dev[‘sentiment’].str.strip() test = pd.read_csv(‘/content/drive/My Drive/Colab Notebooks/GCN/Least Square/data/hcr/test/orig/hcr-test.csv’) test[‘sentiment’] = test[‘sentiment’].str.strip() test.head()
Поскольку я использую colab, путь, который я использую, такой. Кроме того, я просто делаю классификацию по положительному и отрицательному классу:
data = train.append(dev).append(test) ndata = data[(data[‘sentiment’].notnull())&(data[‘sentiment’] != ‘unsure’)&(data[‘sentiment’] != ‘neutral’)&(data[‘sentiment’] != ‘irrelevant’)] y = [[row[0], row[1]] for ind, row in pd.get_dummies(ndata[‘sentiment’]).iterrows()]
Нам нужно разделить данные для обучения и тестирования и векторизации нашего текста:
X_train, X_test, y_train, y_test = train_test_split( ndata['content'], y, test_size=0.2, random_state=42) vectorizer = TfidfVectorizer() vX_train = vectorizer.fit_transform(X_train) vX_test = vectorizer.transform(X_test) print(vX_train.shape)
Теперь мы определяем наши заполнители, переменные и модель, используя tensorflow. Как я уже сказал, модель представляет собой умножение вектора признаков на наши веса, добавленные по смещению:
w = tf.Variable(tf.random_normal(shape=[vX_train.shape[1], 2])) b = tf.Variable(tf.random_normal(shape=[1, 2])) data = tf.placeholder(dtype=tf.float32, shape=[None, vX_train.shape[1]]) target = tf.placeholder(dtype=tf.float32, shape=[None, 2]) logit = tf.matmul(data, w) + b
Мы должны указать некоторые гиперпараметры:
# Define the learning rate, batch_size etc. learning_rate = 0.9 batch_size = 8 numb_of_epoch = 50 num_of_iterations = int(len(train)/batch_size) iter_num = numb_of_epoch * num_of_iterations iter_num
Теперь нам нужно представить наш оптимизатор. Затем мы начинаем определять наши потери, чтобы минимизировать их. Сначала мы получаем разницу между предсказанием нашей системы и золотой меткой. На следующем шаге мы просто вычисляем норму Фробениуса результата и просто получаем среднее значение результирующего вектора. на последнем шаге мы просто определяем нашу меру, то есть точность.
opt = tf.train.GradientDescentOptimizer(learning_rate) temp = target - logit loss = tf.reduce_mean( tf.norm( temp, ord='euclidean', axis=1, )) #+ 0.01*tf.nn.l2_loss(w) goal = opt.minimize(loss) prediction = tf.math.argmax(logit, axis = 1) gold = tf.math.argmax(target, axis = 1) correct = tf.cast(tf.equal(prediction, gold), dtype=tf.float32) # Average accuracy = tf.reduce_mean(correct)
Все в порядке, и теперь мы можем приступить к обучению нашей модели. В дальнейшем мы просто обучаем нашу модель, партию за партией, а затем визуализируем результат:
init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) loss_trace = [] train_acc = [] test_acc = [] for iteration in range(iter_num): # Generate random batch index batch_index = np.random.choice(len(X_train), size=batch_size) batch_train_X = vX_train[batch_index].toarray() batch_train_y = np.matrix(np.array(y_train)[batch_index]) sess.run(goal, feed_dict={data: batch_train_X, target: batch_train_y}) temp_loss = sess.run(loss, feed_dict={data: vX_train.toarray(), target: np.matrix(y_train)}) # convert into a matrix, and the shape of the placeholder to correspond temp_train_acc = sess.run(accuracy, feed_dict={data: vX_train.toarray(), target: np.matrix(y_train)}) temp_test_acc = sess.run(accuracy, feed_dict={data: vX_test.toarray(), target: np.matrix(y_test)}) # recode the result if (iteration)%num_of_iterations == 0: loss_trace.append(temp_loss) train_acc.append(temp_train_acc) test_acc.append(temp_test_acc) # output if (iteration)%(num_of_iterations) == 0: print('epoch: {:2f} loss: {:5f} train_acc: {:5f} test_acc: {:5f}'.format((iteration)/num_of_iterations, temp_loss, temp_train_acc, temp_test_acc)) plt.figure() plt.figure(figsize=(9, 3)) plt.subplot(121) plt.plot(loss_trace, label = 'loss_trace') plt.legend() plt.subplot(122) plt.plot(train_acc, label = 'train_acc') plt.plot(test_acc, label = 'test_acc') plt.legend() plt.show()
Окончательный результат:
Наилучший результат, который мы получили, — около 71. Я очень рекомендую вам сравнить результат с результатом логистической регрессии здесь.
Если мы посмотрим на правую диаграмму, мы можем сказать, что наша модель переоснащена данными. Итак, мы видим, что после эпохи 4 разрыв между точностью обучения и теста начинает расти. Итак, давайте посмотрим, можем ли мы сделать что-нибудь интересное здесь. Итак, мы просто меняем одну строку приведенных выше кодов на:
)) + 0.01*tf.nn.l2_loss(w)
Тем самым мы добавляем регуляризацию в нашу модель. Теперь давайте снова обучим модель. Результаты:
На этот раз у нас в лучшем случае около 75.