Menu
快讀
  • 旅遊
  • 生活
    • 美食
    • 寵物
    • 養生
    • 親子
  • 娛樂
    • 動漫
  • 時尚
  • 社會
  • 探索
  • 故事
  • 科技
  • 軍事
  • 国际
快讀

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

2020 年 4 月 16 日 IT可达鸭

朋友圈很多人都想學python,有一個很重要的原因是它非常適合入門。對于人工智能算法的開發,python有其他編程語言所沒有的獨特優勢,代碼量少,開發者只需把精力集中在算法研究上面。

本文介紹一個用python開發的,自動與美女尬聊的小軟件。以下都是滿滿的幹貨,是我工作之余時寫的,經過不斷優化,現在分享給大家。那現在就讓我們抓緊時間開始吧!

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

准備:

編程工具IDE:pycharm

python版本: 3.6.0

首先新建一個py文件,命名爲:ai_chat.py

PS: 以下五步的代碼直接複制到單個py文件裏面就可以直接運行。爲了讓讀者方便寫代碼,我把代碼都貼出來了,但是排版存在問題,我又把在pycharm的代碼排版給截圖出來。

第一步: 引入關鍵包

# encoding:utf-8
import json
import jieba
import pickle
from gensim import corpora, models, similarities
from os.path import exists
from warnings import filterwarnings
filterwarnings('ignore')  # 不打印警告

簡單介紹一下上面幾個包的作用: pickle 包是用來對數據序列化存文件、反序列化讀取文件,是人類不可讀的,但是計算機去讀取時速度超快。(就是用記事本打開是亂碼)。 而json包是一種文本序列化,是人類可讀的,方便你對其進行修改(記事本打開,可以看到裏面所有內容,而且都認識。) gensim 包是自然語言處理的其中一個python包,簡單容易使用,是入門NLP算法必用的一個python包。jieba包是用來分詞,對于算法大咖來說效果一般般,但是它的速度非常快,適合入門使用。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

關鍵包代碼的排版

以上這些包,不是關鍵,學習的時候,可以先跳過。等理解整個程序流程後,可以一個一個包有針對性地去看文檔。

第二步:靜態配置

這裏path指的是對話語料(訓練數據)存放的位置,model_path是模型存儲的路徑。

class CONF:
    path = '對話語料.json'          # 語料路徑
    model_path = '對話模型.pk'      # 模型路徑

這裏是個人編程的習慣,我習慣把一些配置,例如:文件路徑、模型存放路徑、模型參數統一放在一個類中。當然,實際項目開發的時候,是用config 文件存放,不會直接寫在代碼裏,這裏爲了演示方便,就寫在一起,也方便運行。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

配置類排版

第三步: 編寫一個類,實現導數據、模型訓練、對話預測一體化

首次運行的時候,會從靜態配置中讀取訓練數據的路徑,讀取數據,進行訓練,並把訓練好的模型存儲到指定的模型路徑。後續運行,是直接導入模型,就不用再次訓練了。

class Model:
    def __init__(self, question, answer, dictionary, tfidf, index):
        self.dictionary = dictionary    # 字典
        self.tfidf = tfidf              # 詞袋模型轉tfidf
        self.index = index              # 稀疏矩陣建立索引
        self.question = question        # 語料--問題數組
        self.answer = answer            # 語料--答案數組(與問題一一對應)

    """模型初始化"""
    @classmethod
    def initialize(cls, config):
        if exists(config.model_path):
            # 模型讀取
            question, answer, dictionary, tfidf, index = cls.__load_model(config.model_path)
        else:
            # 語料讀取
            if exists(config.path):
                data = load_json(config.path)
            else:
                data = get_data(config.path)
            # 模型訓練
            question, answer, dictionary, tfidf, index = cls.__train_model(data)
            # 模型保存
            cls.__save_model(config.model_path, question, answer, dictionary, tfidf, index)

        return cls(question, answer, dictionary, tfidf, index)

    @staticmethod
    def __train_model(data):
        """訓練模型"""
        # 劃分問題和答案
        question_list = []
        answer_list = []
        for line in data:
            question_list.append(line['question'])
            answer_list.append(line['answer'])

        # 對問題進行分詞
        qcut = []
        for i in question_list:
            data1 = ""
            this_data = jieba.cut(i)
            for item in this_data:
                data1 += item + " "
            qcut.append(data1)
        docs = qcut

        # 將二維數組轉爲字典
        tall = [[w1 for w1 in doc.split()] for doc in docs]
        dictionary = corpora.Dictionary(tall)
        # # gensim的doc2bow實現詞袋模型
        corpus = [dictionary.doc2bow(text) for text in tall]
        # corpus是一個返回bow向量的叠代器。下面代碼將完成對corpus中出現的每一個特征的IDF值的統計工作
        tfidf = models.TfidfModel(corpus)
        # 通過token2id得到特征數
        num = len(dictionary.token2id.keys())
        # 稀疏矩陣相似度,從而建立索引
        index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=num)
        return question_list, answer_list, dictionary, tfidf, index

    @staticmethod
    def __save_model(model_path, question, answer, dictionary, tfidf, index):
        """模型的保存"""
        model = {}
        model['question'] = question
        model['answer'] = answer
        model['dictionary'] = dictionary
        model['tfidf'] = tfidf
        model['index'] = index
        with open(model_path, "wb") as fh:
            pickle.dump(model, fh)

    @staticmethod
    def __load_model(model_path):
        """模型的保存"""
        with open(model_path, "rb") as fh:
            model = pickle.load(fh)
        question = model['question']
        answer = model['answer']
        dictionary = model['dictionary']
        tfidf = model['tfidf']
        index = model['index']

        return question, answer, dictionary, tfidf, index

    def get_answer(self, question, digalog_id = 1):
        """獲取問題的答案"""
        # 對輸入的問題進行分詞
        data3 = jieba.cut(question)
        data31 = ""
        for item in data3:
            data31 += item + " "
        new_doc = data31

        # 計算該問題的答案
        new_vec = self.dictionary.doc2bow(new_doc.split())
        sim = self.index[self.tfidf[new_vec]]
        position = sim.argsort()[-1]
        answer = self.answer[position]

        return answer, digalog_id

對于model類,我們一個一個來介紹。

initialize() 函數和 __init__() 函數 是對象初始化和實例化,其中包括基本參數的賦值、模型的導入、模型的訓練、模型的保存、最後返回用戶一個對象。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

initialize() 函數和 __init__() 函數 排版

__train_model() 函數,對問題進行分詞,使用gesim實現詞袋模型,統計每個特征的tf-idf, 建立稀疏矩陣,進而建立索引。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

__train_model() 函數 排版

__save_model() 函數 和 __load_model() 函數 是成對出現的,很多項目都會有這兩個函數,用于保存模型和導入模型。不同的是,本項目用的是文件存儲的方式,實際上線用的是數據庫

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

__save_model() 函數 和 __load_model() 函數 排版

get_answer() 函數使用訓練好的模型,對問題進行分析,最終把預測的回答內容反饋給用戶。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

get_answer() 函數排版

第四步:寫三個工具類型的函數,作爲讀寫文件。

其中,獲取對話材料,可以自主修改對話內容,作爲機器的訓練的數據。我這裏只是給了幾個簡單的對話語料,實際上線的項目,需要大量的語料來訓練,這樣對話內容才飽滿。

def load_json(filename, encoding='utf-8'):
    """ 讀取json數據"""
    filename = filename
    with open(filename, encoding=encoding) as file_obj:
        rnt = json.load(file_obj)
    return rnt['data']

def save_json(filename, data, encoding='utf-8'):
    """保存json"""
    with open(filename, 'w', encoding=encoding) as file_obj:
        json.dump({"data": data}, file_obj, ensure_ascii=False)

def get_data(filename):
    """獲取對話材"""
    # question_list 與 answer_list 一一對應
    question_list = ["在嗎?", "在幹嘛?", "我餓了", "我想看電影。"]
    answer_list = ["親,在的。", "在想你呀!", "來我家,做飯給你吃~", "來我家,我家有30寸大電視。"]
    data = []
    for question, answer in zip(question_list, answer_list):
        data.append({'question': question, "answer":answer})
    save_json(filename, data)
    return data

這三個工具函數,相對比較簡單一些。其中 get_data() 函數,裏面的數據是我自己編的,大家可以根據自己的習慣,添加自己的對話數據,這樣最終訓練的模型,對話方式會更貼近自己的說話方式。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

三個工具類的排版

第五步: 調用模型,進行對話預測

if __name__ == '__main__':
    model = Model.initialize(config=CONF)
    question_list = ["在嗎?", "在幹嘛?", "我餓了", "我肚子餓了", "我肚子好餓", "有好看電影介紹嗎?我想看"]
    for line in question_list:
        rnt, digalog_id = model.get_answer(line)
        print("\033[031m女神:%s\033[0m" % line)
        print("\033[036m尬聊:%s\033[0m" % rnt)

主函數main(), 就是你整個程序運行的起點,它控制著所有步驟。

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

主函數排版

運行結果:

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)

程序後台運行結果:

我用了100行Python代碼,實現了與女神尬聊微信(附代碼)


如果有疑問想獲取源碼(其實代碼都在上面),可以後台私信我,回複:python智能對話。 我把源碼發你。最後,感謝大家的閱讀,祝大家工作生活愉快!

相關文章:

  • CentOS 7 上安裝 Node.js + PM2 + NGINX + Redis
  • 跟我一起自學python語言 第9章 類(9.3.4 重寫父類的方法)
  • 面試必過史上最全面試題---分享
  • 基于Go的馬蜂窩旅遊網分布式IM系統技術實踐
  • Tendermint Core Golang應用開發教程「含源代碼」
  • 每日一技:巧用 Telnet 調試 Dubbo 服務
科技

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

快讀 > 科技 > 我用了100行Python代碼,實現了與女神尬聊微信(附代碼)
©2021 快讀 | 服務協議 | DMCA | 聯繫我們