Классификация наименьших квадратов с тензорным потоком

Когда дело доходит до классификации, каждый, кто знаком с линейной регрессией, может перенести знания из регрессии и сказать, почему бы нам не применить ту же простую идею и для классификации?

Ответ на этот вопрос приведет нас к классификации по методу наименьших квадратов. Основная идея состоит в том, чтобы умножить вектор признаков на матрицу весов, которая представляет собой просто комбинацию нескольких столбцов, каждый из которых отвечает за класс. Функция потерь представляет собой квадратную разницу между предсказанной меткой и золотой меткой. Этот алгоритм на самом деле прост, но для получения дополнительной информации, плюсов и минусов читатель может обратиться к главе 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.