摘要: H2Engine服务器引擎架构是轻量级的,与其说是引擎,个人觉得称之为平台更为合适。因为它封装的功能非常精简,但是提供了非常简洁方便的扩展机制,使得可以用C++、python、lua、js、php来开发具体的服务器功能。H2引擎的灵感来源于web服务器Apache。 H2引擎集成了websocket,也推荐大家在长连接应用中,逐渐使用websocket。 协议的封包pb、thrift已经很够用了,H2引擎支持pb、thrift、json以及传统二进制struct,但是推荐thrift,主要是效率和多语言支持都更好。 基于网游服务器的场景,H2引擎考虑到单台物理机的处理能力当前足以应付单服的需求,所以将H2的架构设计为部署在同机上,这样大大简化了服务器的架构,多gate的架构其实来源于rpg刚兴起的年代,那时候服务器的内存有限,cpu多核也还没流行,但是今非昔比,单机模式也就是伪分布式模式其实更符合实际。 脚本化:c++封装数据结构,提供接口给脚本操作,脚本无状态处理逻辑,非常像php+memcached的思路。这样既可以利用了脚本的开发高效率,运行稳定无crash,又利用了 阅读全文
posted @ 2017-09-11 08:33 知然 阅读(4534) 评论(13) 推荐(2) 编辑
摘要: ffpython is a c++ lib,which is to simplify task that embed python and extend python. For example, call python function, register c++ function to python, register c++ class to python. Only one implement c++ header file. 阅读全文
posted @ 2013-05-04 14:36 知然 阅读(2315) 评论(0) 推荐(3) 编辑
摘要: 也许你已经了解了FFLUA的设计原则,即:当在编写C++代码时,希望使用LUA就像使用C++本地的代码一样,而在lua中操作C++的数据和接口的时候,又希望C++用起来完全跟table一个样。这样可以大大减轻程序开发的工作,从而把精力更多放大设计和逻辑上。那么做到如何lua才算像C++,C++做到如何才算像lua呢?我们知道二者毕竟相差甚远,我们只需要把常见的操作封装成一直即可,不常见操作则特殊处理。常见操作有: C++ 调用lua函数,FFLUA已经封装了call函数,保障了调用lua函数就像调用本地C++函数一样方便 C++注册接口和对象到lua中,lua中操作对象就像操作table一样直接。 C++中除了自定义对象,STL是用的最多的了,C++希望lua中能够接收STL的参数,或者能够返回STL数据结构 Lua中只有table数据结构,Lua希望C++的参数的数据结构支持table,并且lua可以直接把table作为返回值。 C++的指针需要传递到lua中,同时也希望某些操作,lua可以把C++对象指针作为返回值 阅读全文
posted @ 2013-01-27 11:50 知然 阅读(8633) 评论(28) 推荐(9) 编辑

朴素贝叶斯python代码实现(西瓜书)

摘要:

朴素贝叶斯也是机器学习中一种非常常见的分类方法,对于二分类问题,并且数据集特征为离散型属性的时候,
使用起来非常的方便。原理简单,训练效率高,拟合效果好。

朴素贝叶斯

贝叶斯公式:

朴素贝叶斯之所以称这为朴素,是因为假设了各个特征是相互独立的,因此假定下公式成立:

则朴素贝叶斯算法的计算公式如下:

在实际计算中,上面的公式会做如下略微改动:

  1. 由于某些特征属性的值P(Xi|Ci)可能很小,多个特征的p值连乘后可能被约等于0。可以公式两边取log然后变乘法为加法,避免类乘问题。
  2. P(Ci) 和P(Xi|Ci) 一般不直接使用样本的频率计算出来,一般会使用拉普拉斯平滑。

上面公式中,Dc为该类别的频数,N表示所有类别的可能数。

上面公式中,Dc,xi为该特征对应属性的频数,Dc为该类别的频数,Ni表示该特征的可能的属性数。

对应的西瓜书数据集为

色泽	根蒂	敲声	纹理	脐部	触感	好瓜
青绿	蜷缩	浊响	清晰	凹陷	硬滑	是
乌黑	蜷缩	沉闷	清晰	凹陷	硬滑	是
乌黑	蜷缩	浊响	清晰	凹陷	硬滑	是
青绿	蜷缩	沉闷	清晰	凹陷	硬滑	是
浅白	蜷缩	浊响	清晰	凹陷	硬滑	是
青绿	稍蜷	浊响	清晰	稍凹	软粘	是
乌黑	稍蜷	浊响	稍糊	稍凹	软粘	是
乌黑	稍蜷	浊响	清晰	稍凹	硬滑	是
乌黑	稍蜷	沉闷	稍糊	稍凹	硬滑	否
青绿	硬挺	清脆	清晰	平坦	软粘	否
浅白	硬挺	清脆	模糊	平坦	硬滑	否
浅白	蜷缩	浊响	模糊	平坦	软粘	否
青绿	稍蜷	浊响	稍糊	凹陷	硬滑	否
浅白	稍蜷	沉闷	稍糊	凹陷	硬滑	否
乌黑	稍蜷	浊响	清晰	稍凹	软粘	否
浅白	蜷缩	浊响	模糊	平坦	硬滑	否
青绿	蜷缩	沉闷	稍糊	稍凹	硬滑	否

python实现

#encoding:utf-8

import pandas as pd
import numpy  as np

class NaiveBayes:
    def __init__(self):
        self.model = {}#key 为类别名 val 为字典PClass表示该类的该类,PFeature:{}对应对于各个特征的概率
    def calEntropy(self, y): # 计算熵
        valRate = y.value_counts().apply(lambda x : x / y.size) # 频次汇总 得到各个特征对应的概率
        valEntropy = np.inner(valRate, np.log2(valRate)) * -1
        return valEntropy

    def fit(self, xTrain, yTrain = pd.Series()):
        if not yTrain.empty:#如果不传,自动选择最后一列作为分类标签
            xTrain = pd.concat([xTrain, yTrain], axis=1)
        self.model = self.buildNaiveBayes(xTrain) 
        return self.model
    def buildNaiveBayes(self, xTrain):
        yTrain = xTrain.iloc[:,-1]
        
        yTrainCounts = yTrain.value_counts()# 频次汇总 得到各个特征对应的概率

        yTrainCounts = yTrainCounts.apply(lambda x : (x + 1) / (yTrain.size + yTrainCounts.size)) #使用了拉普拉斯平滑
        retModel = {}
        for nameClass, val in yTrainCounts.items():
            retModel[nameClass] = {'PClass': val, 'PFeature':{}}

        propNamesAll = xTrain.columns[:-1]
        allPropByFeature = {}
        for nameFeature in propNamesAll:
            allPropByFeature[nameFeature] = list(xTrain[nameFeature].value_counts().index)
        #print(allPropByFeature)
        for nameClass, group in xTrain.groupby(xTrain.columns[-1]):
            for nameFeature in propNamesAll:
                eachClassPFeature = {}
                propDatas = group[nameFeature]
                propClassSummary = propDatas.value_counts()# 频次汇总 得到各个特征对应的概率
                for propName in allPropByFeature[nameFeature]:
                    if not propClassSummary.get(propName):
                        propClassSummary[propName] = 0#如果有属性灭有,那么自动补0
                Ni = len(allPropByFeature[nameFeature])
                propClassSummary = propClassSummary.apply(lambda x : (x + 1) / (propDatas.size + Ni))#使用了拉普拉斯平滑
                for nameFeatureProp, valP in propClassSummary.items():
                    eachClassPFeature[nameFeatureProp] = valP
                retModel[nameClass]['PFeature'][nameFeature] = eachClassPFeature

        return retModel
    def predictBySeries(self, data):
        curMaxRate = None
        curClassSelect = None
        for nameClass, infoModel in self.model.items():
            rate = 0
            rate += np.log(infoModel['PClass'])
            PFeature = infoModel['PFeature']
            
            for nameFeature, val in data.items():
                propsRate = PFeature.get(nameFeature)
                if not propsRate:
                    continue
                rate += np.log(propsRate.get(val, 0))#使用log加法避免很小的小数连续乘,接近零
                #print(nameFeature, val, propsRate.get(val, 0))
            #print(nameClass, rate)
            if curMaxRate == None or rate > curMaxRate:
                curMaxRate = rate
                curClassSelect = nameClass
            
        return curClassSelect
    def predict(self, data):
        if isinstance(data, pd.Series):
            return self.predictBySeries(data)
        return data.apply(lambda d: self.predictBySeries(d), axis=1)

dataTrain = pd.read_csv("xiguadata.csv", encoding = "gbk")

naiveBayes = NaiveBayes()
treeData = naiveBayes.fit(dataTrain)

import json
print(json.dumps(treeData, ensure_ascii=False))

pd = pd.DataFrame({'预测值':naiveBayes.predict(dataTrain), '正取值':dataTrain.iloc[:,-1]})
print(pd)
print('正确率:%f%%'%(pd[pd['预测值'] == pd['正取值']].shape[0] * 100.0 / pd.shape[0]))

输出

{"否": {"PClass": 0.5263157894736842, "PFeature": {"色泽": {"浅白": 0.4166666666666667, "青绿": 0.3333333333333333, "乌 黑": 0.25}, "根蒂": {"稍蜷": 0.4166666666666667, "蜷缩": 0.3333333333333333, "硬挺": 0.25}, "敲声": {"浊响": 0.4166666666666667, "沉闷": 0.3333333333333333, "清脆": 0.25}, "纹理": {"稍糊": 0.4166666666666667, "模糊": 0.3333333333333333, "清晰": 0.25}, "脐部": {"平坦": 0.4166666666666667, "稍凹": 0.3333333333333333, "凹陷": 0.25}, "触感": {"硬滑": 0.6363636363636364, "软粘": 0.36363636363636365}}}, "是": {"PClass": 0.47368421052631576, "PFeature": {"色泽": {"乌黑": 0.45454545454545453, "青绿": 0.36363636363636365, "浅白": 0.18181818181818182}, "根蒂": {"蜷缩": 0.5454545454545454, "稍蜷": 0.36363636363636365, "硬挺": 0.09090909090909091}, "敲声": {"浊响": 0.6363636363636364, "沉闷": 0.2727272727272727, "清脆": 0.09090909090909091}, "纹理": {"清晰": 0.7272727272727273, "稍糊": 0.18181818181818182, "模糊": 0.09090909090909091}, "脐 部": {"凹陷": 0.5454545454545454, "稍凹": 0.36363636363636365, "平坦": 0.09090909090909091}, "触感": {"硬滑": 0.7, "软粘": 0.3}}}}
   预测值 正取值
0    是   是
1    是   是
2    是   是
3    是   是
4    是   是
5    是   是
6    否   是
7    是   是
8    否   否
9    否   否
10   否   否
11   否   否
12   是   否
13   否   否
14   是   否
15   否   否
16   否   否
正确率:82.352941%

总结:

  • 贝叶斯分类器是一种生成式模型,不是直接拟合分类结果,而是拟合出后验概率公式计算对应分类的概率。
  • 本文只介绍了二分类,也可以用来处理多分类问题。
  • 对于小规模数据集,表现良好。
  • 建立在特征相互独立的假设上。
  • 这是我的github主页https://github.com/fanchy,有些有意思的分享。
posted @ 2019-08-23 20:12 知然 阅读(13389) 评论(0) 推荐(2) 编辑
摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则。分类决策树是由节点和有向边组成的树形结构,节点表示特征或者属性, 而边表示的是属性值,边指向的叶节点为对应的分类。在对样本的分类过程中,由顶向下,根据特征或属性值选择分支,递归遍历直到叶节点,将实例分到叶节点对应的类别中。 决策树的学习过程就是构造出一个能正取分类(或者误差最小)训练数据集的且有较好泛化能力的树,核心是如何选择特征或属性作为节点, 通常的算法是利用启发式的算法如ID3,C4.5,CART等递归的选择最优特征。选择一个最优特征,然后按照此特征将数据集分割成多个子集,子集再选择最优特征, 直到所有训练数据都被正取分类,这就构造出了决策树。 阅读全文
posted @ 2019-08-19 15:23 知然 阅读(3797) 评论(0) 推荐(0) 编辑
摘要: 随着手机游戏、H5游戏以及微信小游戏的普及,越来越多的客户端-服务器端的通讯采用websocket协议。Websocket协议是全双工的、基于数据帧的、建立在tcp之上的长连接协议。Websocket的协议是头是字符串的兼容http的,而握手之后的数据帧则是紧凑的二进制,所以websocket是紧凑和高效的。现在主流的PC浏览器以及手机浏览器对websocket都实现了非常成熟的支持。Websocket协议有着统一的标准的,所有websocket通讯无论实现的语言如何,无论使用的终端如何,最终都是一致的。 阅读全文
posted @ 2019-04-25 15:19 知然 阅读(9153) 评论(0) 推荐(2) 编辑
摘要: H2engine的GitHub星星不知不觉已经破百了,也没有特意推广过,但是慢慢的关注的人越来越多。因为事情多,好久没有写东西了,前一段时间有了一些想法,把h2engine又更新了一下,感觉h2engine又向前迈了一大步。本文记录一下最近的心得体会,以及做出的相应修改。 阅读全文
posted @ 2019-02-21 20:33 知然 阅读(1046) 评论(3) 推荐(1) 编辑
摘要: Logistic逻辑回归也可以看成线性回归的变种,虽然名字带回归二字但实际上他主要用来二分类,区别于线性回归直接拟合目标值,Logistic逻辑回归拟合的是正类和负类的对数几率。 阅读全文
posted @ 2018-09-25 09:54 知然 阅读(9496) 评论(0) 推荐(0) 编辑
摘要: 有很多问题是一个因变量与多个自变量成线性相关,我们可以用一个多元线性回归方程来表示。 阅读全文
posted @ 2018-08-28 06:54 知然 阅读(17628) 评论(0) 推荐(0) 编辑
摘要: h2engine引擎建群以后,有热心网友向我反馈,想尝试h2engine但是没有服务器开发经验觉得无从入手,希望我能提供一个简单明了的示例。由于前一段时间工作实在忙碌,一直没有抽出时间好好写一下,后来抽空写了出来,自己从小白开发者的角度重新审视了一遍h2engine,自己也收获匪浅,也优化了部分h2engine的架构,使其更易使用。以前的例子都是c++加脚本的例子,这次写一个纯c++的例子。 阅读全文
posted @ 2018-06-13 08:20 知然 阅读(587) 评论(0) 推荐(0) 编辑
摘要: NPC系统是游戏中非常重要的系统,设计的好坏很大程度上影响游戏的体验。NPC在游戏中有如下作用: 1. 引导玩家体验游戏内容,一般游戏内有很多主线、支线任务,而任务的介绍、接取、领取奖励等操作都是通过NPC的操作,一般会有几个核心NPC,再不停的任务引导中,玩家会对核心npc印象深刻,强化了游戏代入感。 2. 核心功能的展示和操作。游戏大部分功能都会放到游戏主界面,但是全部功能都放进去是不现实的,其他功能则以NPC的方式提供,比如进入某副本的入口等。 3. 一些运营活动,比如道具秒杀,打折促销等,过年过节也可以制作一些应景的NPC形象。 阅读全文
posted @ 2018-02-22 10:08 知然 阅读(6708) 评论(8) 推荐(9) 编辑
摘要: 任务系统是游戏中最重要的系统之一,本文旨在设计一个轻量清晰的任务系统。通用易扩展是本系统关注的重点。任务系统中当角色的条件满足时,自动触发每一类型的任务,每个任务有其所需的完成条件,当角色完成了指定的操作后,则会触发任务自动完成,任务完成后一般玩家会领取对应的奖励,结束任务,此任务的生命周期结束,如果这个任务有后续任务,那么会自动触发下一个任务,从玩家角度讲,任务是一条故事线,所以经常会说主线、支线任务就是这个原因。 阅读全文
posted @ 2018-01-21 21:35 知然 阅读(5556) 评论(1) 推荐(3) 编辑
摘要: 游戏中角色拥有的属性值很多,运营多年的游戏,往往会有很多个成长线,每个属性都有可能被N个成长线模块增减数值。举例当角色戴上武器时候hp+100点,卸下武器时HP-100点,这样加减逻辑只有一处还比较好控制,如果某天有个特殊功能当被某技能攻击时,角色武器会被击落,这样就会出现减数值的操作不止一处。如果逻辑处理不当,比如击落的时候没有恰当的减数值,再次穿戴武器就导致属性值加了两边,也就是玩家经常说的刷属性。这种bug对游戏平衡性影响很大,反响很恶劣,bug又很难被测试发现。本文将介绍一种管理属性的思路,最大限度的避免此类bug,如果出现bug,也能够很好的排查。 阅读全文
posted @ 2018-01-09 19:52 知然 阅读(2328) 评论(0) 推荐(1) 编辑
点击右上角即可分享
微信分享提示