import os
os.environ["TF_ENABLE_ONEDNN_OPTS"]="0" # 数字必须变成字符串

# from tensorflow.keras.preprocessing.text import Tokenizer   # 词汇映射器
from keras.src.legacy.preprocessing.text import Tokenizer   # 词汇映射器。上下的效果完全一样
import joblib

"""
    one-hot总结：
        优点：非常简单，容易理解
        缺点：
            1- one-hot词向量中大量的0，只有一个地方是1，是一个稀疏向量，会浪费存储和计算资源
            2- 对于一次多义的情况，无法解决。小龙女 想 过过 过过 过过 的生活
"""
def demo01():
    # 1- 准备数据
    vocabs = {"周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"}

    # 2- 训练词汇映射器
    # 2.1- 创建词汇映射器
    my_tokenizer = Tokenizer()
    # 2.2- 训练词汇映射器
    my_tokenizer.fit_on_texts(vocabs)
    # 2.3- 得到训练后的结果数据：也就是词与索引的映射关系。注意：索引从1开始的
    word_dict = my_tokenizer.word_index
    # print(type(word_dict))  # 类型是dict。{'王力宏': 1, '周杰伦': 2, '吴亦凡': 3, '鹿晗': 4, '陈奕迅': 5, '李宗盛': 6}
    # print(word_dict)

    # 2.4- 保存训练好的词汇映射器
    joblib.dump(my_tokenizer,"../model/my_tokenizer.pkl")

    # 3- 获得每个词的one-hot词向量
    for word in vocabs:
        # 3.1- 创建一个全0的列表
        # [0,0,0,0,0,0]
        word_one_hot = [0] * len(vocabs)

        # 3.2- 获得词的索引
        index = word_dict[word] - 1

        # 3.3- 将指定位置的值设置为1
        word_one_hot[index] = 1

        print(f"{word} one-hot词向量 {word_one_hot}")

def demo02():
    # 1- 准备数据
    star_name = "王力宏"

    # 2- 加载训练好的词汇映射器
    my_tokenizer = joblib.load("../model/my_tokenizer.pkl")
    word_dict = my_tokenizer.word_index

    # 3- 获得词的one-hot词向量
    # 3.1- 创建一个全0的列表
    word_one_hot = [0] * len(word_dict)

    # 3.2- 获得词的索引
    index = word_dict[star_name] - 1

    # 3.3- 将指定位置的值设置为1
    word_one_hot[index] = 1

    print(f"{star_name} one-hot词向量 {word_one_hot}")

def demo03():
    # 1- 准备数据
    vocabs = ["周杰伦", "陈奕迅", "王力宏", "李宗盛", "吴亦凡", "鹿晗"]

    # 2- 获得每个词的one-hot词向量
    for word in vocabs:
        # 2.1- 初始化一个全0的列表
        word_one_hot = [0]*len(vocabs)
        # 2.2- 获得词的索引，注意该索引从0开始
        index = vocabs.index(word)
        # 2.3- 将指定位置的值设置为1即可
        word_one_hot[index] = 1

        print(f"{word} one-hot词向量 {word_one_hot}")


if __name__ == '__main__':
    # 1- 训练词汇映射器，得到每个词的词向量
    demo01()

    # 2- 加载训练好的词汇映射器，得到某个词的词向量
    demo02()

    # 3- 【掌握】使用纯Python的方式实现
    demo03()