为什么80%的码农都做不了架构师?>>>
综述:
本文主要介绍数据挖掘算法中apriori的实现,其中导入的是从中国天气网中得到的天气数据。下面从获得天气数据开始说明算法的实现。 老师经常跟我说,要站在读者的角度写文章,你看一下我的论文```````今天我也试着从读者的角度写这篇文章。
概念解析:
1、获取天气数据
天气数据的来源是从中国天气网,一开始是想通过爬虫的形似,把整个页面request下来然后进行结构化得到数据。幸好没有这样做,因为中国天气网上面有一个api可以获得里面的天气数据,具体的获取方法可以自行百度。
使用这个接口前,需要知道待查询城市在天气网中的id,例如北京的id是101010100,然后调用接口访问 http://m.weather.com.cn/data/%s.html,把%s替换成为城市的id,得到
http://m.weather.com.cn/data/101010100.html,把链接在浏览器打开,可以看到得到的json数据。
里面的数据只有一部分是我们需要的,所以先整理成为xml的格式,至于为什么是xml,其实json更好,这随便啦!
实现的代码:getWeather.py
首先通过urllib2从天气网的web接口获取信息,codeAPI.txt保存的是一些城市的id,把获得的数据流传到weatherAnalysis.py中解析
url = "http://m.weather.com.cn/data/%s.html"
path = "./conf/codeAPI.txt"
def main():
for li in open(path, "r"):
for l in re.findall(r'[\d]+', li):
try:
stream=urllib2.urlopen(url%l.strip())
weatherAnalysis.xmlBuilder(stream.read())
except Exception, e:
continue
root = etree.Element("weatherinfos")
data_xml = "data/weatherinfo%s.xml"
splitor='~'
subffixlow='L'
subffixhigh='H'
def xmlBuilder(f):
js = json.loads(f)
root.append(jsonAnalyser(js["weatherinfo"]))
out= open(data_xml%datetime.datetime.now().strftime("%Y-%m-%d-%Hh"), "w")
out.write(etree.tostring(root, pretty_print=True, encoding='utf-8'))
def jsonAnalyser(js):
element = etree.Element("weatherinfo", city=js["city"], city_en=js["city_en"]\
, date=js["date"], week=js["week"])
for x in range(1,6):
d=datetime.datetime.now()+datetime.timedelta(hours=4*(x-1))
time_range= etree.Element("time_range")
element.append(time_range)
etree.SubElement(time_range, "time").text=d.strftime("%H")
tempC=js["temp"+str(x)].split(splitor)
etree.SubElement(time_range, "tempCL").text=tempC[0]+subffixlow
etree.SubElement(time_range, "tempCH").text=tempC[1]+subffixhigh
tempC=js["tempF"+str(x)].split(splitor)
etree.SubElement(time_range, "tempFL").text=tempC[0]+subffixlow
etree.SubElement(time_range, "tempFH").text=tempC[1]+subffixhigh
etree.SubElement(time_range, "weather").text=js["weather"+str(x)]
etree.SubElement(time_range, "wind").text=js["wind"+str(x)]
return element
解析后的某个城市的数据:
16℃L
30℃H
60.8℉L
86℉H
晴
微风
17℃L
29℃H
62.6℉L
84.2℉H
多云
微风
17℃L
25℃H
62.6℉L
77℉H
多云转小雨
微风
15℃L
26℃H
59℉L
78.8℉H
小雨转阴
微风转北风3-4级
15℃L
30℃H
59℉L
86℉H
晴
微风
python操作json数据是很方便的,首先新建一个json对象,然后本节点有什么数据直接可以通过json['xxx名称']的形似获得。
2.apriori的理论及实现
理论部分:
Apriori algorithm是关联规则里一项基本算法。是由Rakesh Agrawal和Ramakrishnan Srikant两位博士在1994年提出的关联规则挖掘算法。关联规则的目的就是在一个数据集中找出项与项之间的关系,也被称为购物蓝分析 (Market Basket analysis),因为“购物蓝分析”很贴切的表达了适用该算法情景中的一个子集。关于这个算法有一个非常有名的故事:"尿布和啤酒"。故事是这样的:美国的妇女们经常会嘱咐她们的丈夫下班后为孩子买尿布,而丈夫在买完尿布后又要顺 手买回自己爱喝的啤酒,因此啤酒和尿布在一起被购买的机会很多。这个举措使尿布和啤酒的销量双双增加,并一直为众商家所津津乐道。
概念解析:
支持度(Support):定 义为 supp(X) = occur(X) / count(D) = P(X)。
置信度(Confidence/Strength): 定义为 conf(X->Y) = supp(X ∪ Y) / supp(X) = P(Y|X)。
老师经常跟我说,知识不在于你懂多少,而是在于别人能理解你知识的多少,所以你看一下我的论文`````我尽量详细的说出我对这个算法的理解,下面只是我个人的观点。
假设现在一个数据集
I1:
N1: LBN, Brooklyn, 11204
N2: MBE, WEB, 11204
I1中有两个子项N1,N2
第一步,把I1中所有的子项取出来,在把这些N1{LBN, Brooklyn, 11204},N2{MBE, WEB, 11204}子项中的元素全部取出来得到一个集合M1,M1中包括元素之外还需要包含元素的频率{LBN:1/2, Brooklyn:1/2, 11204:2/2, MBE:1/2, WEB:1/2}。
第二步,判断这些元素有哪一个符合最小support的要求,把符合的取出来组合成为一个集合P。
第三步,得到一个M2集合。M2里面每个元素都是由两个元素组成的,最简单的方法就是把M1的笛卡尔积去掉重复的部(忘记了具体的描述,离散数学老师死得早),得到
M2{
[LBN, Broollyn]: 1/2, [LBN, 11204]: 1/2, [LBN, MBN]: 0/2, [LBN, WEB]: 0/2,
[Brooklyn, 11204]: 1/2, [Brooklyn, MBN]: 0/2, [Brooklyn, WEB]: 0/2,
[11204, MBN]: 1/2, [11204, WEB]: 1/2,
[MBE, WEB]: 1/2
}
判断哪些元素符合最小support要求,把符合要求的组成一个集合P
第四步,回到第二步,第三步。但是第三步就不是生成M2,而是生成M3,也就是说生成多少阶i的Mi集合,直到生成的P集合是一个空集。
第五部:计算置信度,把P作为总集(分母),P中每个元素作为子集(分子),计算每个子集占这个总集的概率,只要子集包括在总集的的某个子集中就算一个,一个子集[Brooklyn, WEB]含义是由Brooklyn可以推出WEB,总集中首先一定会有这个子集本身,所以结果总是大于等于1的,然后如果总集中有一个[Brooklyn, WEB, 11204],这个也算是一个。如果只有这两个那么s=2,假设P中子集的数量是p=10,那么概率就是2/10,换句话说就是计算这个推测占整个推测集合的概率。如果设置的置信度小于0.2,那[Brooklyn, WEB]这个结果也是可信的(不过从上面的[Brooklyn, WEB]: 0/2 看来,这个结果连进入P集合的机会都没有 - -),如果置信度比较高,那么这个结果则是不可信的。
到此基本完成,只要把大于置信度的集合记录下来就可以了。
实现的具体代码:
def returnItemsWithMinSupport(itemSet, transactionList, minSupport, freqSet):
#把数据中大于最小支持度的项组成itemSet返回
def joinSet(itemSet,length):
#这个功能就是所谓的对一个集合笛卡尔积去掉重复的部分
def getItemSetTransactionList(data_iterator):
#把数据转换成为Set和list的形式
def runApriori(data_iter, minSupport, minConfidence):
"""
run the apriori algorithm. data_iter is a record iterator
Return both:
- items (tuple, support)
- rules ((pretuple, posttuple), confidence)
"""
itemSet, transactionList = getItemSetTransactionList(xmlAnalysis.parseWeatherXML(data_iter))
freqSet = defaultdict(int)
largeSet = dict() # Global dictionary which stores (key=n-itemSets,value=support) which satisfy minSupport
assocRules = dict() # Dictionary which stores Association Rules
oneCSet = returnItemsWithMinSupport(itemSet, transactionList, minSupport, freqSet)
currentLSet = oneCSet
k = 2
while(currentLSet != set([])):
largeSet[k-1] = currentLSet
currentLSet = joinSet(currentLSet,k)
currentCSet = returnItemsWithMinSupport(currentLSet, transactionList, minSupport, freqSet)
currentLSet = currentCSet
k = k + 1
toRetItems=[]
for key,value in largeSet.items():
toRetItems.extend([(tuple(item), getSupport(item))
for item in value])
toRetRules=[]
for key,value in largeSet.items()[1:]:
for item in value:
_subsets = map(frozenset,[x for x in subsets(item)])
for element in _subsets:
remain = item.difference(element)
if len(remain)>0:
confidence = getSupport(item)/getSupport(element)
if confidence >= minConfidence:
toRetRules.append(((tuple(element),tuple(remain)),
confidence))
return toRetItems, toRetRules
3.导入数据运行
晴 ==> 22h , 0.301
22h ==> 晴 , 0.378
02h ==> 晴 , 0.273
晴 ==> 02h , 0.217
14h ==> 晴 , 0.411
晴 ==> 14h , 0.328
22、02、14点晴天的概率还是挺大的,不过一点价值都没有- -。要想得到一些比较有意义的数据还需要把天气的xml数据进行合适的量化,例如:气温这个部分,在同一个地点出现一模一样的气温的概率不高,除非在某个特定的时间点和地段。因此可以把气温分段,例如以3度为单位,21、22、23都归结在21这个数字上,来提高21度时候的概率。这些量化的规则要按照挖掘的需要自己制定,里面需要的统计学的知识还真不少的。
如果把间隔调成5,按照5度一个区间这样子来统计得到的结果:
------------------ RULES:
小雨 ==> 20℃H , 0.639
30℃H ==> 晴 , 0.859
北风小于3级 ==> 20℃H , 0.714
晴转多云 ==> 25℃H , 0.668
10h ==> 20℃H , 0.630
置信度调成0.6 ,感觉这次结果有点科学
源码还没有整理好,稍后补上
done