内容回顾
逻辑回归是在线性模型的基础上,再增加一个Sigmoid函数来实现的。
输入样本特征,经过线性组合之后,得到的是一个连续值,经过Sigmoid函数,把它转化为一个0-1之间的概率,再通过设置一个合理的阈值,就可以实现二分类问题。
; Sigmoid 函数:
在实现逻辑回归时,需要计算
如何编程来实现这个函数表达式:
import numpy as np
import tensorflow as tf
# 在TensorFlow中, 使用 exp 来实现 e^x 的运算,
# 需要注意这个函数的参数要求是浮点数。
x = np.array([1., 2., 3., 4.])
w = tf.Variable(1.)
b = tf.Variable(1.)
print(1/(1+tf.exp(-(w*x+b))))
"""
tf.Tensor([0.880797 0.95257413 0.98201376 0.9933072 ], shape=(4,), dtype=float32)
"""
准确率:
import numpy as np
import tensorflow as tf
# 假设 y 是样本标签
y = np.array([0, 0, 1, 1])
# pred 是对应的预测概率
pred = np.array([0.1, 0.2, 0.8, 0.49])
# 如果将阈值设置为 0.5 ,就可以使用四舍五入函数 round, 把它转换为 0 和 1
print(tf.round(pred))
"""
tf.Tensor([0. 0. 1. 0.], shape=(4,), dtype=float64)
"""
# 然后使用 equal 函数逐个元素的去比较预测值和标签值
print(tf.equal(tf.round(pred), y))
"""
tf.Tensor([ True True True False], shape=(4,), dtype=bool)
"""
# 使用 cast 函数将上面得到的结果转换为整数
print(tf.cast(tf.equal(tf.round(pred), y), tf.int8))
"""
tf.Tensor([1 1 1 0], shape=(4,), dtype=int8)
"""
# 得到预测正确的样本数在所有样本数中的比例
print(tf.reduce_mean(tf.cast(tf.equal(tf.round(pred), y), tf.float32)))
"""
tf.Tensor(0.75, shape=(), dtype=float32)
"""
# 需要注意的是, 使用 round 函数时, 如果参数恰好是0.5, 那么返回的结果是0.0
print(tf.round(0.5))
"""
tf.Tensor(0.0, shape=(), dtype=float32)
"""
# 当参数的值大于0.5时, 返回的结果才是是1.0
print(tf.round(0.5000001))
"""
tf.Tensor(1.0, shape=(), dtype=float32)
"""
在上面例子中,阈值被设置为0.5,如果想要设置为其他值,应该怎么处理呢?
可以使用 TensorFlow 中的 where 函数。
where (condition, a, b)
# 它根据condition返回a或者b的值,参数condition是一个布尔型的张量或者数组。
# 如果condition中的某个元素为真,那么对应位置就返回 a ,否则返回 b 。
例子如下:
import numpy as np
import tensorflow as tf
# pred 是预测概率
pred = np.array([0.1, 0.2, 0.8, 0.49])
print(pred < 0.5)
# [ True True False True]
print(tf.where(pred < 0.5, 0, 1))
# tf.Tensor([0 0 1 0], shape=(4,), dtype=int32)
print(pred < 0.4)
# [ True True False False]
print(tf.where(pred < 0.4, 0, 1))
# tf.Tensor([0 0 1 1], shape=(4,), dtype=int32)
参数 a 和 b还可以是张量或者数组,这时a和b必须有相同的形状。并且它们的第一维必须和condition形状一致。
import numpy as np
import tensorflow as tf
# pred 是预测概率
pred = np.array([0.1, 0.2, 0.8, 0.59])
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(tf.where(pred < 0.5, a, b))
# tf.Tensor([ 1 2 30 40], shape=(4,), dtype=int32)
print(tf.where(pred >= 0.5))
# 当参数 a 和 b 省略时, 就返回数组 pred 中大小等于0.5的元素的索引
# 这个返回值以一个二维张量的形式给出
"""
tf.Tensor(
[[2]
[3]], shape=(2, 1), dtype=int64)
"""
# 这在我们需要获取某种条件的掩码时非常有用
# 在计算分类准确率时, 使用 where 函数可以更加灵活地设置阈值
# 然后将预测概率转化为类别
y = np.array([0, 0, 1, 1])
y_pred = np.array([0.1, 0.2, 0.8, 0.49])
print(tf.reduce_mean(tf.cast(tf.equal(tf.where(y_pred < 0.5, 0, 1), y), tf.float32)))
"""
tf.Tensor(0.75, shape=(), dtype=float32)
"""
交差熵损失函数:
; 平均交差熵损失函数:
import numpy as np
import tensorflow as tf
# 假设 y 是样本标签
y = np.array([0, 0, 1, 1])
# pred 是对应的预测概率
pred = np.array([0.1, 0.2, 0.8, 0.49])
# 计算交差熵损失函数值
# tf.math.log实现以 e 为底的对数运算
print(-tf.reduce_sum(y*tf.math.log(pred)+(1-y)*tf.math.log(1-pred)))
# tf.Tensor(1.2649975061637104, shape=(), dtype=float64)
# 计算平均交差熵损失函数值
print(-tf.reduce_mean(y*tf.math.log(pred)+(1-y)*tf.math.log(1-pred)))
# tf.Tensor(0.3162493765409276, shape=(), dtype=float64)
实例:实现一元逻辑回归
(这个图中的数据比前面的不一样,修改了两个数据,目的是为了和其他相邻的点重合。其中,0代表普通住宅,1代表高档住宅。)
注意,在训练模型时,是没有房价这个标签的,而是直接使用面积和所属的类别来训练模型。
此外,在模型的训练过程中产生的线性模型 wx + b 的值,我们可以把它理解为类似于房价的一个指标,它是一个中间结果,我们并不需要把它读取出来。
第一步:加载数据
代码如下:
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "SimHei", "sans-serif"
plt.rcParams['axes.unicode_minus'] = False # 设置正常显示符号
# 第一步:数据加载
# 面积都是大于40的正数
x = np.array([137.97, 104.50, 100.00, 126.32, 79.20, 99.00, 124.00, 114.00,
106.69, 140.05, 53.75, 46.91, 68.00, 63.02, 81.26, 86.21])
y = np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0])
plt.figure()
plt.scatter(x, y)
plt.show()
运行下代码:
(注:面积都是大于40的正数)
第二步:数据处理
因为 Sigmoid 函数是以零点为中心的,因此在数据处理阶段, 我们对这些点进行中心化,每个样本点都减去它们的平均值,这样整个数据集的均值就等于0。
x_train = x - np.mean(x)
y_train = y
plt.figure()
plt.scatter(x_train, y_train)
plt.suptitle("数据处理后的商品房分类图", fontsize=20)
plt.show()
在运行下代码:
可以发现,数据整体向左平移了,但是它们之间的想对位置并没有改变。
第三步:设置超参数
learn_rate = 0.005
itar = 5
display_step = 1
第四步:训练模型
cross_train = [] # 用来存放训练集的交叉熵损失
acc_train = [] # 用来存放训练集的分类准确率
for i in range(0, itar+1):
with tf.GradientTape() as tape:
# Sigmoid 函数
pred_train = 1/(1+tf.exp(-(w*x_train+b)))
# 平均交叉熵损失函数
Loss_train = -tf.reduce_mean(y_train * tf.math.log(pred_train) + (1 - y_train) * tf.math.log(1 - pred_train))
# 计算准确率函数 -- 因为不需要对其进行求导运算, 因此也可以把这条语句写在 with 语句的外面
Accuarcy_train = tf.reduce_mean(tf.cast(tf.equal(tf.where(pred_train < 0.5, 0, 1), y_train), tf.float32))
# 记录每一次迭代的交叉熵损失和准确率
cross_train.append(Loss_train)
acc_train.append(Accuarcy_train)
# 对交叉熵损失函数分别对 w 和 b 求偏导
dL_dw, dL_db = tape.gradient(Loss_train, [w, b])
# 更新模型参数
w.assign_sub(learn_rate * dL_dw)
b.assign_sub(learn_rate * dL_db)
if i % display_step == 0:
print("i: %i, Train Loss: %f, Accuracy: %f" % (i, Loss_train, Accuarcy_train))
运行结果如下:
第六步:数据可视化
1、绘制 Sigmoid 函数 曲线图
# 在设置模型初始值后, 给出一组连续的x坐标
x_ = range(-80, 80)
# 并使用 w 和 b 的初始值,计算Sigmoid 函数作为 y 坐标
y_ = 1/(1+tf.exp(-(w*x_+b)))
这个曲线看起来和S型曲线相差很大,是因为这个随机的w和b正好得到了一个中间变化部分范围很大的曲线。
如果将 x 取值扩大一些,比如扩大到
# 在设置模型初始值后, 给出一组连续的x坐标
x_ = range(-600, 600)
# 并使用 w 和 b 的初始值,计算Sigmoid 函数作为 y 坐标
y_ = 1/(1+tf.exp(-(w*x_+b)))
此时,再来看看输出图像
接下来,在训练模型的过程中增加绘制 Sigmoid 函数曲线图。
# 第四步:设置模型变量的初始值
......
# 在设置模型初始值后, 给出一组连续的x坐标
x_ = range(-80, 80)
# 并使用 w 和 b 的初始值,计算Sigmoid 函数作为 y 坐标
y_ = 1/(1+tf.exp(-(w*x_+b)))
plt.figure()
# 绘制房子实际分类的散点图
plt.scatter(x_train, y_train)
plt.plot(x_, y_, color="red", linewidth=3)
# 第五步:训练模型
......
for i in range(0, itar+1):
with tf.GradientTape() as tape:
......
......
if i % display_step == 0:
print("i: %i, Train Loss: %f, Accuracy: %f" % (i, Loss_train, Accuarcy_train))
y_ = 1/(1+tf.exp(-(w*x_+b)))
plt.plot(x_, y_)
plt.suptitle("不断更新 w 和 b 后得到的 Sigmoid 函数曲线图", fontsize=20)
plt.show()
运行结果如下:
上图红色的粗线是随机设置模型参数 w 、b的初始值后绘制出来的曲线,可以看出刚好有10个点属于普通住宅,这只能说是运气蒙对了。
上图蓝色的(曲))线是第一次迭代后的结果,随着迭代次数增加,输出概率越来越能够反映出样本的真实分类了。
那怎么根据曲线来判断出分类的呢?
是根据每个样本点在曲线上对应的取值,再与0.5进行比较,低于0.5时,被分类为普通住房,而高于0.5时,则被分类为高档住宅。
因为下图框中的圈起来的这几个样本(横坐标为0附近)),该位置的曲线斜率较大,更新后的 w 和 b 对该曲线的斜率的影响也是最大的,比较难预测。
所以这个区域中的点可能会出现分类错误,导致准确率无法达到100%。
第一次训练的模型分类的准确率虽然更高,但是从整体上来看,还是经过更多次迭代之后概率的预测更加合理。
第七步:模型预测
# 第七步:模型预测
x_test = np.array([128.15, 45.00, 141.43, 106.27, 99.00, 53.84, 85.36, 70.00, 162.00, 114.60])
# 这里使用训练数据的平均值对新的数据进行中心化处理
pred_test = 1 / (1 + tf.exp(-(w * (x_test-np.mean(x)) + b)))
# 根据概率进行分类
y_test = tf.where(pred_test < 0.5, 0, 1)
for i in range(len(x_test)):
print(x_test[i], "\t", pred_test[i].numpy(), "\t", y_test[i].numpy())
输出结果如下:
"""
128.15 0.8610252 1
45.0 0.0029561974 0
141.43 0.9545566 1
106.27 0.45318928 0
99.0 0.2981362 0
53.84 0.00663888 0
85.36 0.108105935 0
70.0 0.028681064 0
162.0 0.9928677 1
114.6 0.6406205 1
"""
要注意的是,这里虽然使用 x_test 来表示这些数据,但是它并不是测试集,因为真正的测试集是有标签的数据,例如波士顿房价数据集中的测试集。在训练的过程中,通过模型在测试集上表现来评价模型的性能。在机器学习中,要求测试集和训练集是独立同分布的。也就是说,它们有着相同的均值和方差。这样的测试才有意义。
而这里的 x_test,实际上是模型训练好之后,在真实场景下的应用情况,是没有标签的。真实场景中的数据,可能是各种各样的,而且通常来说,每次应用可能只是给出一个数据,或者一部分数据,所以这里采用训练集中的均值来中心化数据。
下面来将数据可视化。首先,根据分类结果绘制散点图,可以看到这四套商品房被划分为高档住宅,剩下的被划分为普通住宅。通过散点图,可以更加直观地得到商品房类型和面积的关系,然后绘制概率曲线。
plt.subplot(122)
plt.title("Test Outcome", fontsize=12)
plt.scatter(x_test, y_test)
x_ = np.array(range(-80, 80))
y_ = 1/(1 + tf.exp(-(w * x_ + b)))
plt.plot(x_+np.mean(x), y_)
plt.show()
运行结果如下:
因为散点图的 x 坐标使用的是真实的面积,没有平移,所以在这里加上训练集的均值。
Original: https://blog.csdn.net/xuechanba/article/details/124530357
Author: xuechanba
Title: 使用TensorFlow编程实现一元逻辑回归
相关阅读
Title: dbpedia知识图谱java_一种基于DBpedia的水务领域概念知识图谱构建方法与流程
本发明涉及的是领域知识图谱构建技术领域,涉及到一种基于DBpedia的水务领域概念知识图谱构建方法,特别涉及到一种基于Jaccard相似度算法与随机游走相似度算法结合的协同过滤模型框架,用于补全概念模型的一套水务领域概念知识图谱构建方法。
背景技术:
目前调研领域知识图谱构建技术主要包括:1)知识融合:很多领域知识图谱的应用的方案都是建立在通用知识图谱的基础之上的,通用知识图谱可以为很多的领域知识图谱提供种子事实,目前有很多的通用知识图谱,比如复旦大学的通用百科知识图谱CN-DBpedia和概念图谱CN-Probase,基于维基百科页面结构化知识的DBpedia、YAGO。国内外对与从通用实体、概念的获取研究技术一般采用迭代的原理进行循环获取,即远程监督的方式,通过API端口,获取通用知识图谱中的领域种子实体,通过这些种子从语料中获取更多的实体,再以此实体作为种子,从通用知识图谱中获取相关的实体。概念合并,概念上下位关系合并,概念的属性合并,国内外研究学者在这些方面做出了很多贡献。国内知识图谱映射技术主要包括词典wordnet、结构和基于实例的方法,以及使用背景知识和以前的知识找到匹配结果输出。2)数据处理:数据来源通常是来自于领域百科爬取、通用百科导出、业务系统导出等,对与词汇挖掘、实体发现、关系发现的研究,国内外学者做出了很多贡献。比如对与实体关系的抽取,目前国内外主要具有成果性的技术有:基于Rule的关系抽取、基于bootstrapping的关系抽取等。
目前针对水务领域的概念知识图谱研究较少,关于这些技术还没有真正的得到落实,有些也不适用与水务领域,因此本发明构建水务概念知识图谱的方法对与其它领域可以提供一些指导。
技术实现要素:
有鉴于上述现有技术的不足,本发明的目的在于提供一种基于DBpedia的水务领域概念知识图谱构建方法,旨在解决水务领域概念知识图谱构建的知识补全的问题。
本发明解决其技术问题所采取的技术方案是:一种基于DBpedia的水务领域知识图谱构建方法,该方法主要包括如下步骤:
步骤1:在java系统中构建水务概念词库,将构建好的水务概念词库放入word中。
步骤2:以概念词库作为种子,获取DBpedia中获取与水务相关的实体、概念及其之间的关系,构建水务概念知识图谱。
步骤3:构建好的概念知识图谱在protégé系统中实现可视化,修改现有的概念知识图谱,得到最终的水务领域概念知识图谱。
进一步的,本发明步骤1所述的构建水务概念词库的方法,其步骤具体包括:
步骤1-1:借助水务专家知识、相关水务分类标准、Wordnet词典初步获取概念词。
步骤1-2:使用python从贴吧、博客以及水务文档中爬取一些水务文本。
步骤1-3:用python中的jieba工具对抽取的水务文本进行文本分词。
步骤1-4:用python中的stopwords工具对分词后的文本进行停用词去除,组成水务相关实体、概念词。
步骤1-5:用TF-IDF方法对水务相关实体、概念词分别进行权重计算,设置一个权重阈值,保留权重大于阈值的实体、概念词。
进一步的,本发明步骤2所述的获取DBpedia中与水务相关的实体与概念的方法,其步骤具体包括:
步骤2-1:输出的实体词,通过DBpedia的接口,分别找到其上位概念、下位概念的集合,通过Jaccard相似度算法,两个集合重叠度越高,实体越相似,若相似度高于一个设定的阈值,最后的实体作为我们的最终的候选实体。
步骤2-2:利用随机游走相似度的方法,以输出的实体为起点,在DBpedia知识库中先得到上位/下位方向随机游走后落到每一个节点的概率向量,然后计算两个向量的Cosine相似度。我们设定步数为2步,最后得到两个实体的相似度值。
步骤2-3:综合考虑以上两种方法,我们采用一种合并相似度算法,找到实体的前5个最相似的实体,确定实体集。
步骤2-4:通过DBpedia,找到实体集相关的上/下位概念,及其他们之间的等级关系,并将相似的实体进行归类,将其存储到Mysql数据库中。根据从DBpedia中筛选的实体、概念词和专家知识对概念等级结构进行修改。
步骤2-5:用jena工具将保存到数据库中的概念信息表写成owl文件。
进一步的,本发明步骤3所述的在protégé中实现可视化并挂接水务信息的方法,其步骤具体包括:
步骤3-1:将owl文件导入到protégé软件中,实现水务领域知识图谱的可视化。
进一步的,本发明步骤2所述的用相似度算法寻找水务相关实体方法,其算法步骤具体包括:
步骤2-1:Jaccard相似度通用公式为首先分别计算两个实体/概念c1和c2的上/下位概念集合的Jaccard相似度je和jo,je(c1,c2)=Jacc(hype(c1),hype(c2)),jo(c1,c2)=Jacc(hype(c1),hype(c2)),其中hype(c1)、hype(c2)分别为两个实体/概念c1和c2对应的概念集合。最后使用noisy-or合并je、jo,得到最终的两个实体/概念的相似度值为jacc(c1,c2)=1-(1-je(c1,c2))·(1-jo(c1,c2))。
步骤2-2:首先计算实体/概念c的随机游走向量其中i为结束的节点数,M为权重值,一般的情况设置i值为2。其次计算两个实体c1和c2随机游走向量的Cosine相似度与分别代表实体c1和c2的随机游走向量。
步骤2-3:计算合并相似度β为可调参数。
本发明能够应用于水务领域概念知识图谱的构建。
与现有技术相比较,本发明具有如下有益效果:
1.本发明在水务实体、概念词抽取阶段,从大量的非结构文本中,能够抽取大量特定的水务实体、概念词,为水务知识图谱的构建打下坚实的基础。
2.本发明通过一定的技术方法,从DBpedia知识库中归类出水务领域的实体与概念,并将初步抽取的词汇进行了精确的筛选及关系的合并,并将获取的实体、概念关系作为现有知识图谱的补充,提供了一种知识图谱补全的方法。
附图说明
图1为本发明一种基于DBpedia的水务领域知识图谱构建方法的流程图。
图2为步骤2的具体流程图。
图3为水务领域概念知识图谱部分展开图。
具体实施方式
本发明提供一种基于DBpedia的水务领域概念知识图谱构建方法,为使本发明的目的、技术方案及效果更加清楚、明确,以下对本发明进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。
请参阅图1。图1为本发明一种一种基于DBpedia的水务领域概念知识图谱构建方法较佳实施例的流程图,如图所示,其实施步骤,包括如下:
步骤1:在java系统中构建水务概念词库,将构建好的水务概念词库放入word中。
步骤2:以概念词库作为种子,获取DBpedia中获取与水务相关的实体、概念及其之间的关系,构建水务概念知识图谱。
步骤3:构建好的概念知识图谱在protégé系统中实现可视化,修改现有的概念知识图谱,得到最终的水务领域概念知识图谱。
图2中本发明所采用的相似度计算方法都有各自的优势,在实验中依据实体数据量的大小进行搭配使用,其中Jaccard算法在实验中较为简单,但准确率相对较低,适合概念集相对较少的时候使用,合并相似度算法较为复杂,但是准确率会相对较高,适合概念集合相对较多的时候使用。
图3是构建的水务领域概念知识图谱部分图。
应当理解的是,本发明的应用不限于上述的举例,对本领域普通技术人员来说,可以根据上述说明加以改进或变换,所有这些改进和变换都应属于本发明所附权利要求的保护范围。
Original: https://blog.csdn.net/weixin_39677203/article/details/114493090
Author: weixin_39677203
Title: dbpedia知识图谱java_一种基于DBpedia的水务领域概念知识图谱构建方法与流程