# загрузка из файла
reviews_test = pd.read_csv('data/reviews_test.csv', header=0, encoding='utf-8')
reviews_train = pd.read_csv('data/reviews_train.csv', header=0, encoding='utf-8')
reviews_internet = pd.read_csv('data/internet_reviews.csv', header=0, encoding='utf-8')

# обучающая выборка
X_train_raw = reviews_train.comment
y_train_raw = reviews_train.reting

# проверочная выборка
X_test_raw = reviews_test.comment
y_test_raw = reviews_test.reting

# дополнительная обучающая выборка
X_internet = reviews_internet.comment
y_internet = reviews_internet.rating

"""
Explanation: Модель № 1
Вход
Данные: Данные предоставленные МВидео (80% обучающая выборка/ 20% тестовая выборка)
Представление: word2vec на основе обученной модели gensim, размерность пространства: 500
Описание модели: 4 параллельные 1D свертки с разым размером окна по компоненте word2vec, с L2 регулиризацией, далее объединение результатов, GlobalVaxPooling, и один полносвязный слой с дропаутом, далее выход регрессии.
Параметры обучения: Оптимизатор: стохастический градиентный спуск, learning rate опредлялся как: 2 эпохи с 0.01, далее ~5 эпох с 0.001, далее ~5 эпох с 0.0001, далее ~5 эпох с 0.00005
Целевая метрика: MSE
Результат (целевые переменные не нормировались!): MSE(train)=0.8403, MSE(test)=0.9136
Загрузка данных
Для начала загружаем данные из *.csv файлов, данные были предварительно разбиты на обучающую и проверочную выборки (см. файл "data preprocessing.ipynb"). Кроме того, были загружены дополнительные данные для увеличения обучающей выборки(отзывы об интернет провайдерах).
End of explanation
"""


DIR = 'data/w2v_models/'
MODEL_NAME = 'tenth.norm-sz500-w7-cb0-it5-min5.w2v'
#MODEL_NAME = 'all.norm-sz100-w10-cb0-it1-min100.w2v'

# initialazing comment preprocessor
sp = SentenceProcessor(DIR + MODEL_NAME)
sp.stop_list = stop_words
sp.sample_len = 100

WORD_VECTOR_LENGTH = sp.w2v.vector_size # 500 each word
SENTENCE_LENGTH = sp.sample_len # 100 words

print ('Размерность коментария: {}x{}'.format(SENTENCE_LENGTH, WORD_VECTOR_LENGTH))

"""
Explanation: Загрузка обработчика комментариев
Загружаем предобученную модель word to vec в обработчик комментариев (модель можно найти здесь, мы использовали модель размерностью 500 со словарем более 1 млн. слов).
<br /><br />В обработчике:
 - переводим текст в нижний регистр
 - разбиваем по словам, удаляя всё, кроме букв
 - исправляем орфографию, где это возможно, с помощью Яндекс.спеллер
 - нормализуем слова, приводя их к единственному числу, именительному падежу и т.д. и т.п.
 - еще раз иcправляем орфографию :)
 - переводим полученный массив слов с помощью обученной w2v модели в матрицу размерностью количество_слов х размер_вектора_слова - 100x500 (размер комментария выбран изходя из анализа данных в  "data preprocessing.ipynb")
End of explanation
"""


# приводим оба датафрема к одному формату
del reviews_internet['Unnamed: 0']
reviews_internet = reviews_internet.rename(columns={'rating':'reting'})

# склеиваем данные
new_reviews = reviews_train.append(reviews_internet, ignore_index=True)

# добавляем новый столбец
new_reviews['bag_of_words'] = ' '

# первичная предобработка данных(токенизация, нормализация, исправление орфографических ошибок)
bag_of_bags = []
for i in tqdm_notebook(range(len(new_reviews.comment))):
    bag_of_bags.append(' '.join(sp.process(new_reviews.comment[i])))

# добавляем обработанные комментарии в новый столбец
new_reviews['bag_of_words'] = bag_of_bags

# сохраняем наши данные в .csv формате
new_reviews.to_csv('data/new_reviews.csv')

# на всякий случай сохраняем обработанные комментарии в .pkl
with open('bag_{}.pkl'.format(len(bag_of_bags)), 'wb') as f:
    pickle.dump(bag_of_bags, f)

# читаем из файла если предыдущие шаги уже выполнены
new_reviews = pd.read_csv('data/new_reviews.csv', encoding='cp1251')

# полная обучающая выборка
X_train_all = new_reviews.bag_of_words
y_train_all = new_reviews.reting

# обучающая выборка от МВидео (без дополнительных отзывов об интернет провайдерах)
X_train = new_reviews.bag_of_words[:12410]
y_train = new_reviews.reting[:12410]

# тестовая выборка
X_val = reviews_test.comment
y_val = reviews_test.reting

"""
Explanation: Обработка данных
End of explanation
"""


from utils.generators import train_generator, test_generator
from keras.regularizers import l2 as L2
l2 = L2(0.01)

MODELS_DIR = 'saved_models/'

# создаем модель нейросети
input = keras.layers.Input(shape=(SENTENCE_LENGTH, WORD_VECTOR_LENGTH))
l_0 = keras.layers.Dense(256)(input)
l_1 = keras.layers.Conv1D(nb_filter=256, filter_length=2, activation='relu', W_regularizer=l2)(input)
l_2 = keras.layers.Conv1D(nb_filter=256, filter_length=3, activation='relu', W_regularizer=l2)(input)
l_3 = keras.layers.Conv1D(nb_filter=256, filter_length=4, activation='relu', W_regularizer=l2)(input)
merge = keras.layers.Merge(mode='concat', concat_axis=1) ([l_0, l_1, l_2, l_3])
l_5 = keras.layers.GlobalMaxPooling1D()(merge)
l_6 = keras.layers.Dropout(0.5)(l_5)
output = keras.layers.Dense(1, activation=None, W_regularizer=l2)(l_6)
model = keras.models.Model(input, output, name='model_5')
model.summary()

# загрузка обученной модели
model = keras.models.load_model('saved_models/model_5_mse_0.9056_extra')

# обучение
optimizer = keras.optimizers.SGD(lr=0.01)
model.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['mse'])

model.fit_generator(
    train_generator(X_train, y_train, sp, shuffle=True), 
    nb_epoch=10,
    samples_per_epoch=len(y_train),
    validation_data=train_generator(X_val, y_val, sp, shuffle=False),
    nb_val_samples=len(y_val),
    verbose=2,
)

# сохранение обчунной модели
model.save('saved_models/trained_model_1(keras==1.2.2)')

"""
Explanation: Обучение модели
End of explanation
"""


# метрики
errors = get_score(model, X_val_vec, y_val.values, sparse=40)

"""
Explanation: Результаты
целевые переменные не нормировались!
End of explanation
"""


from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.metrics import accuracy_score

def to_bool(y):
    y_bool = []
    for a in y:
        if a == 5.0:
            y_bool.append(1)
        else:
            y_bool.append(0)
    return y_bool

y_train_bool = to_bool(y_train)
y_test_bool = to_bool(y_test)  

"""
Explanation: Классификатор 5 / не 5
End of explanation
"""


p = PCA(n_components=100)

p.fit(X_train.reshape((X_train.shape[0], -1)))

X_train_transformed = p.transform(X_train.reshape((X_train.shape[0], -1)))

X_test_transformed = p.transform(X_test.reshape((X_test.shape[0], -1)))

"""
Explanation: Cнизижаем размерность
End of explanation
"""


clf = SVC(C=100.0)
clf.fit(X_train_transformed, y_train_bool)

y_pred = clf.predict(X_test_transformed)

accuracy_score(y_test_bool, y_pred)

"""
Explanation: Обучаем классификатор
End of explanation
"""


