Share This
Связаться со мной
Крути в низ
Categories
//Чат-бот на Python (Deep Learning + TensorFlow). Часть V: построение базы данных

Чат-бот на Python (Deep Learning + TensorFlow). Часть V: построение базы данных

28.04.2021Category : Python

chat bot na python deep learning tensorflow chast v postroenie bazy dannyh 3eec6be - Чат-бот на Python (Deep Learning + TensorFlow). Часть V: построение базы данных

Предыдущая статья: Чат-бот на Python (Deep Learning + TensorFlow). Часть IV: строим логику.

Добро пожаловать в пятую часть серии статей про создание чат-бота при помощи алгоритмов глубокого обучения и библиотеки TensorFlow. В предыдущих статьях мы усиленно готовили наши данные для создания из них обучающей базы. Теперь мы готовы эту базу наполнить. Наш код на настоящий момент имеет следующий вид:

import sqlite3 import json from datetime import datetime  timeframe = '2015-05' sql_transaction = []  connection = sqlite3.connect('{}.db'.format(timeframe)) c = connection.cursor()  def create_table():     c.execute("CREATE TABLE IF NOT EXISTS parent_reply(parent_id TEXT PRIMARY KEY, comment_id TEXT UNIQUE, parent TEXT, comment TEXT, subreddit TEXT, unix INT, score INT)")  def format_data(data):     data = data.replace('n',' newlinechar ').replace('r',' newlinechar ').replace('"',"'")     return data  def acceptable(data):     if len(data.split(' ')) > 50 or len(data) < 1:         return False     elif len(data) > 1000:         return False     elif data == '[deleted]':         return False     elif data == '[removed]':         return False     else:         return True  def find_parent(pid):     try:         sql = "SELECT comment FROM parent_reply WHERE comment_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False  def find_existing_score(pid):     try:         sql = "SELECT score FROM parent_reply WHERE parent_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False      if __name__ == '__main__':     create_table()     row_counter = 0     paired_rows = 0      with open('J:/chatdata/reddit_data/{}/RC_{}'.format(timeframe.split('-')[0],timeframe), buffering=1000) as f:         for row in f:             row_counter += 1             row = json.loads(row)             parent_id = row['parent_id']             body = format_data(row['body'])             created_utc = row['created_utc']             score = row['score']             comment_id = row['name']             subreddit = row['subreddit']             parent_data = find_parent(parent_id)             if score >= 2:                 existing_comment_score = find_existing_score(parent_id) 

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

if score >= 2:                 existing_comment_score = find_existing_score(parent_id)                 if existing_comment_score:                     if score > existing_comment_score:                         if acceptable(body):                             sql_insert_replace_comment(comment_id,parent_id,parent_data,body,subreddit,created_utc,score) 

Теперь нам нужно создать функцию sql_insert_replace_comment():

def sql_insert_replace_comment(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """UPDATE parent_reply SET parent_id = ?, comment_id = ?, parent = ?, comment = ?, subreddit = ?, unix = ?, score = ? WHERE parent_id =?;""".format(parentid, commentid, parent, comment, subreddit, int(time), score, parentid)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e)) 

Это касается ситуации, когда комментарий уже связан с родительским элементом, но нам также необходимо охватить комментарии, у которых нет родителей (но которые могут быть родительскими для других!), а также комментарии, у которых есть родители, но у этих родителей еще нет ответов. Мы можем дополнительно построить блок для вставки данных:

if score >= 2:                 existing_comment_score = find_existing_score(parent_id)                 if existing_comment_score:                     if score > existing_comment_score:                         if acceptable(body):                             sql_insert_replace_comment(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                  else:                     if acceptable(body):                         if parent_data:                             sql_insert_has_parent(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                             paired_rows += 1                         else:                             sql_insert_no_parent(comment_id,parent_id,body,subreddit,created_utc,score) 

Теперь нам нужно создать функции sql_insert_has_parent() и sql_insert_no_parent():

def sql_insert_has_parent(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, parent, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}","{}",{},{});""".format(parentid, commentid, parent, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))   def sql_insert_no_parent(commentid,parentid,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}",{},{});""".format(parentid, commentid, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e)) 

Чтобы ориентироваться, где мы находимся в процессе итерации, мы будем через каждые 100000 строк выводить следующую информацию:

if row_counter % 100000 == 0:                 print('Total Rows Read: {}, Paired Rows: {}, Time: {}'.format(row_counter, paired_rows, str(datetime.now()))) 

chat bot na python deep learning tensorflow chast v postroenie bazy dannyh 8f37e11 - Чат-бот на Python (Deep Learning + TensorFlow). Часть V: построение базы данных

Хотите найти работу Junior Python Developer

Подписывайтесь на наш телеграм c вакансиями по Python

Подписаться ×

Наконец, последняя нужная нам часть нашего кода — функция transaction_bldr(), которую мы сейчас создадим. Эта функция используется для создания операторов вставки и фиксации их в группах, а не по отдельности. Ее использование заметно ускорит процесс:

 def transaction_bldr(sql):     global sql_transaction     sql_transaction.append(sql)     if len(sql_transaction) > 1000:         c.execute('BEGIN TRANSACTION')         for s in sql_transaction:             try:                 c.execute(s)             except:                 pass         connection.commit()         sql_transaction = []

Да, мы здесь используем глобальную переменную.

Весь код на данный момент имеет следующий вид:

import sqlite3 import json from datetime import datetime  timeframe = '2015-05' sql_transaction = []  connection = sqlite3.connect('{}.db'.format(timeframe)) c = connection.cursor()  def create_table():     c.execute("CREATE TABLE IF NOT EXISTS parent_reply(parent_id TEXT PRIMARY KEY, comment_id TEXT UNIQUE, parent TEXT, comment TEXT, subreddit TEXT, unix INT, score INT)")  def format_data(data):     data = data.replace('n',' newlinechar ').replace('r',' newlinechar ').replace('"',"'")     return data  def transaction_bldr(sql):     global sql_transaction     sql_transaction.append(sql)     if len(sql_transaction) > 1000:         c.execute('BEGIN TRANSACTION')         for s in sql_transaction:             try:                 c.execute(s)             except:                 pass         connection.commit()         sql_transaction = []  def sql_insert_replace_comment(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """UPDATE parent_reply SET parent_id = ?, comment_id = ?, parent = ?, comment = ?, subreddit = ?, unix = ?, score = ? WHERE parent_id =?;""".format(parentid, commentid, parent, comment, subreddit, int(time), score, parentid)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def sql_insert_has_parent(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, parent, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}","{}",{},{});""".format(parentid, commentid, parent, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def sql_insert_no_parent(commentid,parentid,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}",{},{});""".format(parentid, commentid, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def acceptable(data):     if len(data.split(' ')) > 50 or len(data) < 1:         return False     elif len(data) > 1000:         return False     elif data == '[deleted]':         return False     elif data == '[removed]':         return False     else:         return True  def find_parent(pid):     try:         sql = "SELECT comment FROM parent_reply WHERE comment_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False  def find_existing_score(pid):     try:         sql = "SELECT score FROM parent_reply WHERE parent_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False      if __name__ == '__main__':     create_table()     row_counter = 0     paired_rows = 0      with open('J:/chatdata/reddit_data/{}/RC_{}'.format(timeframe.split('-')[0],timeframe), buffering=1000) as f:         for row in f:             row_counter += 1             row = json.loads(row)             parent_id = row['parent_id']             body = format_data(row['body'])             created_utc = row['created_utc']             score = row['score']             comment_id = row['name']             subreddit = row['subreddit']             parent_data = find_parent(parent_id)             if score >= 2:                 existing_comment_score = find_existing_score(parent_id)                 if existing_comment_score:                     if score > existing_comment_score:                         if acceptable(body):                             sql_insert_replace_comment(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                                              else:                     if acceptable(body):                         if parent_data:                             sql_insert_has_parent(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                             paired_rows += 1                         else:                             sql_insert_no_parent(comment_id,parent_id,body,subreddit,created_utc,score)                                          if row_counter % 100000 == 0:                 print('Total Rows Read: {}, Paired Rows: {}, Time: {}'.format(row_counter, paired_rows, str(datetime.now()))) 

Теперь мы можем запустить его. Результат должен выглядеть следующим образом:

Total Rows Read: 100000, Paired Rows: 3221, Time: 2017-11-14 15:14:33.748595 Total Rows Read: 200000, Paired Rows: 8071, Time: 2017-11-14 15:14:55.342929 Total Rows Read: 300000, Paired Rows: 13697, Time: 2017-11-14 15:15:18.035447 Total Rows Read: 400000, Paired Rows: 19723, Time: 2017-11-14 15:15:40.311376 Total Rows Read: 500000, Paired Rows: 25643, Time: 2017-11-14 15:16:02.045075

Получение всех данных будет зависеть от размера исходного файла. Чем больше становится база данных, тем медленнее будет работать операция вставки. На создание всего файла за май 2015 г., вероятно, уйдет 5–10 часов.

Обработав нужный файл (или несколько файлов), мы готовы создать обучающий датасет. Чем мы и займемся в следующей статье.

Работая с большими наборами данных, мы можем заметить, что эти самые данные сильно раздуты. Это связано с тем, что только около 10% комментариев объединяются в пары, поэтому большая часть нашей базы данных фактически не будет использоваться. Мы будем использовать следующий дополнительный код:

if row_counter % cleanup == 0:     print("Cleanin up!")     sql = "DELETE FROM parent_reply WHERE parent IS NULL"     c.execute(sql)     connection.commit()     c.execute("VACUUM")     connection.commit()

Данный код достаточно эффективно устранит раздувание нашей базы данных. Каждая «очистка» стоит около 2К пар, куда бы вы их ни положили. То есть, вычистив 100К строк, мы потеряем 2000 пар. Мы считаем, что это незначительная потеря.

Мы также добавили переменную start_row, которая позволяет нам запускать и останавливать операцию вставки в базу данных, благодаря чему мы сможем немного ускорить процесс.

с.execute(“VACUUM”) — это команда SQL для уменьшения размера базы данных до нужного для нас размера. На самом деле это не обязательно, и вы можете это сделать вообще в самом конце. Мы не проверяли, сколько времени займет эта операция. В основном мы это сделали, чтобы сразу после удаления видеть, каков размер базы данных.

Итак, полный код теперь имеет следующий вид:

 import sqlite3 import json from datetime import datetime import time  timeframe = '2017-03' sql_transaction = [] start_row = 0 cleanup = 1000000  connection = sqlite3.connect('{}.db'.format(timeframe)) c = connection.cursor()  def create_table():     c.execute("CREATE TABLE IF NOT EXISTS parent_reply(parent_id TEXT PRIMARY KEY, comment_id TEXT UNIQUE, parent TEXT, comment TEXT, subreddit TEXT, unix INT, score INT)")  def format_data(data):     data = data.replace('n',' newlinechar ').replace('r',' newlinechar ').replace('"',"'")     return data  def transaction_bldr(sql):     global sql_transaction     sql_transaction.append(sql)     if len(sql_transaction) > 1000:         c.execute('BEGIN TRANSACTION')         for s in sql_transaction:             try:                 c.execute(s)             except:                 pass         connection.commit()         sql_transaction = []  def sql_insert_replace_comment(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """UPDATE parent_reply SET parent_id = ?, comment_id = ?, parent = ?, comment = ?, subreddit = ?, unix = ?, score = ? WHERE parent_id =?;""".format(parentid, commentid, parent, comment, subreddit, int(time), score, parentid)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def sql_insert_has_parent(commentid,parentid,parent,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, parent, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}","{}",{},{});""".format(parentid, commentid, parent, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def sql_insert_no_parent(commentid,parentid,comment,subreddit,time,score):     try:         sql = """INSERT INTO parent_reply (parent_id, comment_id, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}",{},{});""".format(parentid, commentid, comment, subreddit, int(time), score)         transaction_bldr(sql)     except Exception as e:         print('s0 insertion',str(e))  def acceptable(data):     if len(data.split(' ')) > 1000 or len(data) < 1:         return False     elif len(data) > 32000:         return False     elif data == '[deleted]':         return False     elif data == '[removed]':         return False     else:         return True  def find_parent(pid):     try:         sql = "SELECT comment FROM parent_reply WHERE comment_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False  def find_existing_score(pid):     try:         sql = "SELECT score FROM parent_reply WHERE parent_id = '{}' LIMIT 1".format(pid)         c.execute(sql)         result = c.fetchone()         if result != None:             return result[0]         else: return False     except Exception as e:         #print(str(e))         return False      if __name__ == '__main__':     create_table()     row_counter = 0     paired_rows = 0      #with open('J:/chatdata/reddit_data/{}/RC_{}'.format(timeframe.split('-')[0],timeframe), buffering=1000) as f:     with open('/home/paperspace/reddit_comment_dumps/RC_{}'.format(timeframe), buffering=1000) as f:         for row in f:             #print(row)             #time.sleep(555)             row_counter += 1              if row_counter > start_row:                 try:                     row = json.loads(row)                     parent_id = row['parent_id'].split('_')[1]                     body = format_data(row['body'])                     created_utc = row['created_utc']                     score = row['score']                                          comment_id = row['id']                                          subreddit = row['subreddit']                     parent_data = find_parent(parent_id)                                          existing_comment_score = find_existing_score(parent_id)                     if existing_comment_score:                         if score > existing_comment_score:                             if acceptable(body):                                 sql_insert_replace_comment(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                                                      else:                         if acceptable(body):                             if parent_data:                                 if score >= 2:                                     sql_insert_has_parent(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)                                     paired_rows += 1                             else:                                 sql_insert_no_parent(comment_id,parent_id,body,subreddit,created_utc,score)                 except Exception as e:                     print(str(e))                                          if row_counter % 100000 == 0:                 print('Total Rows Read: {}, Paired Rows: {}, Time: {}'.format(row_counter, paired_rows, str(datetime.now())))              if row_counter > start_row:                 if row_counter % cleanup == 0:                     print("Cleanin up!")                     sql = "DELETE FROM parent_reply WHERE parent IS NULL"                     c.execute(sql)                     connection.commit()                     c.execute("VACUUM")                     connection.commit()

Следующая статья: Чат-бот на Python (Deep Learning + TensorFlow). Часть VI: обучающий набор данных.

chat bot na python deep learning tensorflow chast v postroenie bazy dannyh e6db1da - Чат-бот на Python (Deep Learning + TensorFlow). Часть V: построение базы данных

Больше материалов по машинному обучению

Подписывайтесь на нас в Телеграм

Подписаться ×

  • 0 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Свежие комментарии

    Рубрики

    About Author 01.

    Roman Spiridonov
    Roman Spiridonov

    Привет ! Мне 38 лет, я работаю в области информационных технологий более 4 лет. Тут собрано самое интересное.

    Our Instagram 04.

    Categories 05.

    © Speccy 2020 / All rights reserved

    Связаться со мной
    Close