dic演算法
Ⅰ 用python實現紅酒數據集的ID3,C4.5和CART演算法
ID3演算法介紹
ID3演算法全稱為迭代二叉樹3代演算法(Iterative Dichotomiser 3)
該演算法要先進行特徵選擇,再生成決策樹,其中特徵選擇是基於「信息增益」最大的原則進行的。
但由於決策樹完全基於訓練集生成的,有可能對訓練集過於「依賴」,即產生過擬合現象。因此在生成決策樹後,需要對決策樹進行剪枝。剪枝有兩種形式,分別為前剪枝(Pre-Pruning)和後剪枝(Post-Pruning),一般採用後剪枝。
信息熵、條件熵和信息增益
信息熵:來自於香農定理,表示信息集合所含信息的平均不確定性。信息熵越大,表示不確定性越大,所含的信息量也就越大。
設x 1 , x 2 , x 3 , . . . x n {x_1, x_2, x_3, ...x_n}x
1
,x
2
,x
3
,...x
n
為信息集合X的n個取值,則x i x_ix
i
的概率:
P ( X = i ) = p i , i = 1 , 2 , 3 , . . . , n P(X=i) = p_i, i=1,2,3,...,n
P(X=i)=p
i
,i=1,2,3,...,n
信息集合X的信息熵為:
H ( X ) = − ∑ i = 1 n p i log p i H(X) =- \sum_{i=1}^{n}{p_i}\log{p_i}
H(X)=−
i=1
∑
n
p
i
logp
i
條件熵:指已知某個隨機變數的情況下,信息集合的信息熵。
設信息集合X中有y 1 , y 2 , y 3 , . . . y m {y_1, y_2, y_3, ...y_m}y
1
,y
2
,y
3
,...y
m
組成的隨機變數集合Y,則隨機變數(X,Y)的聯合概率分布為
P ( x = i , y = j ) = p i j P(x=i,y=j) = p_{ij}
P(x=i,y=j)=p
ij
條件熵:
H ( X ∣ Y ) = ∑ j = 1 m p ( y j ) H ( X ∣ y j ) H(X|Y) = \sum_{j=1}^m{p(y_j)H(X|y_j)}
H(X∣Y)=
j=1
∑
m
p(y
j
)H(X∣y
j
)
由
H ( X ∣ y j ) = − ∑ j = 1 m p ( y j ) ∑ i = 1 n p ( x i ∣ y j ) log p ( x i ∣ y j ) H(X|y_j) = - \sum_{j=1}^m{p(y_j)}\sum_{i=1}^n{p(x_i|y_j)}\log{p(x_i|y_j)}
H(X∣y
j
)=−
j=1
∑
m
p(y
j
)
i=1
∑
n
p(x
i
∣y
j
)logp(x
i
∣y
j
)
和貝葉斯公式:
p ( x i y j ) = p ( x i ∣ y j ) p ( y j ) p(x_iy_j) = p(x_i|y_j)p(y_j)
p(x
i
y
j
)=p(x
i
∣y
j
)p(y
j
)
可以化簡條件熵的計算公式為:
H ( X ∣ Y ) = ∑ j = 1 m ∑ i = 1 n p ( x i , y j ) log p ( x i ) p ( x i , y j ) H(X|Y) = \sum_{j=1}^m \sum_{i=1}^n{p(x_i, y_j)\log\frac{p(x_i)}{p(x_i, y_j)}}
H(X∣Y)=
j=1
∑
m
i=1
∑
n
p(x
i
,y
j
)log
p(x
i
,y
j
)
p(x
i
)
信息增益:信息熵-條件熵,用於衡量在知道已知隨機變數後,信息不確定性減小越大。
d ( X , Y ) = H ( X ) − H ( X ∣ Y ) d(X,Y) = H(X) - H(X|Y)
d(X,Y)=H(X)−H(X∣Y)
python代碼實現
import numpy as np
import math
def calShannonEnt(dataSet):
""" 計算信息熵 """
labelCountDict = {}
for d in dataSet:
label = d[-1]
if label not in labelCountDict.keys():
labelCountDict[label] = 1
else:
labelCountDict[label] += 1
entropy = 0.0
for l, c in labelCountDict.items():
p = 1.0 * c / len(dataSet)
entropy -= p * math.log(p, 2)
return entropy
def filterSubDataSet(dataSet, colIndex, value):
"""返回colIndex特徵列label等於value,並且過濾掉改特徵列的數據集"""
subDataSetList = []
for r in dataSet:
if r[colIndex] == value:
newR = r[:colIndex]
newR = np.append(newR, (r[colIndex + 1:]))
subDataSetList.append(newR)
return np.array(subDataSetList)
def chooseFeature(dataSet):
""" 通過計算信息增益選擇最合適的特徵"""
featureNum = dataSet.shape[1] - 1
entropy = calShannonEnt(dataSet)
bestInfoGain = 0.0
bestFeatureIndex = -1
for i in range(featureNum):
uniqueValues = np.unique(dataSet[:, i])
condition_entropy = 0.0
for v in uniqueValues: #計算條件熵
subDataSet = filterSubDataSet(dataSet, i, v)
p = 1.0 * len(subDataSet) / len(dataSet)
condition_entropy += p * calShannonEnt(subDataSet)
infoGain = entropy - condition_entropy #計算信息增益
if infoGain >= bestInfoGain: #選擇最大信息增益
bestInfoGain = infoGain
bestFeatureIndex = i
return bestFeatureIndex
def creatDecisionTree(dataSet, featNames):
""" 通過訓練集生成決策樹 """
featureName = featNames[:] # 拷貝featNames,此處不能直接用賦值操作,否則新變數會指向舊變數的地址
classList = list(dataSet[:, -1])
if len(set(classList)) == 1: # 只有一個類別
return classList[0]
if dataSet.shape[1] == 1: #當所有特徵屬性都利用完仍然無法判斷樣本屬於哪一類,此時歸為該數據集中數量最多的那一類
return max(set(classList), key=classList.count)
bestFeatureIndex = chooseFeature(dataSet) #選擇特徵
bestFeatureName = featNames[bestFeatureIndex]
del featureName[bestFeatureIndex] #移除已選特徵列
decisionTree = {bestFeatureName: {}}
featureValueUnique = sorted(set(dataSet[:, bestFeatureIndex])) #已選特徵列所包含的類別, 通過遞歸生成決策樹
for v in featureValueUnique:
FeatureName = featureName[:]
subDataSet = filterSubDataSet(dataSet, bestFeatureIndex, v)
decisionTree[bestFeatureName][v] = creatDecisionTree(subDataSet, FeatureName)
return decisionTree
def classify(decisionTree, featnames, featList):
""" 使用訓練所得的決策樹進行分類 """
classLabel = None
root = decisionTree.keys()[0]
firstGenDict = decisionTree[root]
featIndex = featnames.index(root)
for k in firstGenDict.keys():
if featList[featIndex] == k:
if isinstance(firstGenDict[k], dict): #若子節點仍是樹,則遞歸查找
classLabel = classify(firstGenDict[k], featnames, featList)
else:
classLabel = firstGenDict[k]
return classLabel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
下面用鳶尾花數據集對該演算法進行測試。由於ID3演算法只能用於標稱型數據,因此用在對連續型的數值數據上時,還需要對數據進行離散化,離散化的方法稍後說明,此處為了簡化,先使用每一種特徵所有連續性數值的中值作為分界點,小於中值的標記為1,大於中值的標記為0。訓練1000次,統計准確率均值。
from sklearn import datasets
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
data = np.c_[iris.data, iris.target]
scoreL = []
for i in range(1000): #對該過程進行10000次
trainData, testData = train_test_split(data) #區分測試集和訓練集
featNames = iris.feature_names[:]
for i in range(trainData.shape[1] - 1): #對訓練集每個特徵,以中值為分界點進行離散化
splitPoint = np.mean(trainData[:, i])
featNames[i] = featNames[i]+'<='+'{:.3f}'.format(splitPoint)
trainData[:, i] = [1 if x <= splitPoint else 0 for x in trainData[:, i]]
testData[:, i] = [1 if x <= splitPoint else 0 for x in testData[:, i]]
decisionTree = creatDecisionTree(trainData, featNames)
classifyLable = [classify(decisionTree, featNames, td) for td in testData]
scoreL.append(1.0 * sum(classifyLable == testData[:, -1]) / len(classifyLable))
print 'score: ', np.mean(scoreL)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
輸出結果為:score: 0.7335,即准確率有73%。每次訓練和預測的准確率分布如下:
數據離散化
然而,在上例中對特徵值離散化的劃分點實際上過於「野蠻」,此處介紹一種通過信息增益最大的標准來對數據進行離散化。原理很簡單,當信息增益最大時,說明用該點劃分能最大程度降低數據集的不確定性。
具體步驟如下:
對每個特徵所包含的數值型特徵值排序
對相鄰兩個特徵值取均值,這些均值就是待選的劃分點
用每一個待選點把該特徵的特徵值劃分成兩類,小於該特徵點置為1, 大於該特徵點置為0,計算此時的條件熵,並計算出信息增益
選擇信息使信息增益最大的劃分點進行特徵離散化
實現代碼如下:
def filterRawData(dataSet, colIndex, value, tag):
""" 用於把每個特徵的連續值按照區分點分成兩類,加入tag參數,可用於標記篩選的是哪一部分數據"""
filterDataList = []
for r in dataSet:
if (tag and r[colIndex] <= value) or ((not tag) and r[colIndex] > value):
newR = r[:colIndex]
newR = np.append(newR, (r[colIndex + 1:]))
filterDataList.append(newR)
return np.array(filterDataList)
def dataDiscretization(dataSet, featName):
""" 對數據每個特徵的數值型特徵值進行離散化 """
featureNum = dataSet.shape[1] - 1
entropy = calShannonEnt(dataSet)
for featIndex in range(featureNum): #對於每一個特徵
uniqueValues = sorted(np.unique(dataSet[:, featIndex]))
meanPoint = []
for i in range(len(uniqueValues) - 1): # 求出相鄰兩個值的平均值
meanPoint.append(float(uniqueValues[i+1] + uniqueValues[i]) / 2.0)
bestInfoGain = 0.0
bestMeanPoint = -1
for mp in meanPoint: #對於每個劃分點
subEntropy = 0.0 #計算該劃分點的信息熵
for tag in range(2): #分別劃分為兩類
subDataSet = filterRawData(dataSet, featIndex, mp, tag)
p = 1.0 * len(subDataSet) / len(dataSet)
subEntropy += p * calShannonEnt(subDataSet)
## 計算信息增益
infoGain = entropy - subEntropy
## 選擇最大信息增益
if infoGain >= bestInfoGain:
bestInfoGain = infoGain
bestMeanPoint = mp
featName[featIndex] = featName[featIndex] + "<=" + "{:.3f}".format(bestMeanPoint)
dataSet[:, featIndex] = [1 if x <= bestMeanPoint else 0 for x in dataSet[:, featIndex]]
return dataSet, featName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
重新對數據進行離散化,並重復該步驟1000次,同時用sklearn中的DecisionTreeClassifier對相同數據進行分類,分別統計平均准確率。運行代碼如下:
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
scoreL = []
scoreL_sk = []
for i in range(1000): #對該過程進行1000次
featNames = iris.feature_names[:]
trainData, testData = train_test_split(data) #區分測試集和訓練集
trainData_tmp = .(trainData)
testData_tmp = .(testData)
discritizationData, discritizationFeatName= dataDiscretization(trainData, featNames) #根據信息增益離散化
for i in range(testData.shape[1]-1): #根據測試集的區分點離散化訓練集
splitPoint = float(discritizationFeatName[i].split('<=')[-1])
testData[:, i] = [1 if x<=splitPoint else 0 for x in testData[:, i]]
decisionTree = creatDecisionTree(trainData, featNames)
classifyLable = [classify(decisionTree, featNames, td) for td in testData]
scoreL.append(1.0 * sum(classifyLable == testData[:, -1]) / len(classifyLable))
clf = DecisionTreeClassifier('entropy')
clf.fit(trainData[:, :-1], trainData[:, -1])
clf.predict(testData[:, :-1])
scoreL_sk.append(clf.score(testData[:, :-1], testData[:, -1]))
print 'score: ', np.mean(scoreL)
print 'score-sk: ', np.mean(scoreL_sk)
fig = plt.figure(figsize=(10, 4))
plt.subplot(1,2,1)
pd.Series(scoreL).hist(grid=False, bins=10)
plt.subplot(1,2,2)
pd.Series(scoreL_sk).hist(grid=False, bins=10)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
兩者准確率分別為:
score: 0.7037894736842105
score-sk: 0.7044736842105263
准確率分布如下:
兩者的結果非常一樣。
(但是。。為什麼根據信息熵離散化得到的准確率比直接用均值離散化的准確率還要低啊??哇的哭出聲。。)
最後一次決策樹圖形如下:
決策樹剪枝
由於決策樹是完全依照訓練集生成的,有可能會有過擬合現象,因此一般會對生成的決策樹進行剪枝。常用的是通過決策樹損失函數剪枝,決策樹損失函數表示為:
C a ( T ) = ∑ t = 1 T N t H t ( T ) + α ∣ T ∣ C_a(T) = \sum_{t=1}^TN_tH_t(T) +\alpha|T|
C
a
(T)=
t=1
∑
T
N
t
H
t
(T)+α∣T∣
其中,H t ( T ) H_t(T)H
t
(T)表示葉子節點t的熵值,T表示決策樹的深度。前項∑ t = 1 T N t H t ( T ) \sum_{t=1}^TN_tH_t(T)∑
t=1
T
N
t
H
t
(T)是決策樹的經驗損失函數當隨著T的增加,該節點被不停的劃分的時候,熵值可以達到最小,然而T的增加會使後項的值增大。決策樹損失函數要做的就是在兩者之間進行平衡,使得該值最小。
對於決策樹損失函數的理解,如何理解決策樹的損失函數? - 陶輕松的回答 - 知乎這個回答寫得挺好,可以按照答主的思路理解一下
C4.5演算法
ID3演算法通過信息增益來進行特徵選擇會有一個比較明顯的缺點:即在選擇的過程中該演算法會優先選擇類別較多的屬性(這些屬性的不確定性小,條件熵小,因此信息增益會大),另外,ID3演算法無法解決當每個特徵屬性中每個分類都只有一個樣本的情況(此時每個屬性的條件熵都為0)。
C4.5演算法ID3演算法的改進,它不是依據信息增益進行特徵選擇,而是依據信息增益率,它添加了特徵分裂信息作為懲罰項。定義分裂信息:
S p l i t I n f o ( X , Y ) = − ∑ i n ∣ X i ∣ ∣ X ∣ log ∣ X i ∣ ∣ X ∣ SplitInfo(X, Y) =-\sum_i^n\frac{|X_i|}{|X|}\log\frac{|X_i|}{|X|}
SplitInfo(X,Y)=−
i
∑
n
∣X∣
∣X
i
∣
log
∣X∣
∣X
i
∣
則信息增益率為:
G a i n R a t i o ( X , Y ) = d ( X , Y ) S p l i t I n f o ( X , Y ) GainRatio(X,Y)=\frac{d(X,Y)}{SplitInfo(X, Y)}
GainRatio(X,Y)=
SplitInfo(X,Y)
d(X,Y)
關於ID3和C4.5演算法
在學習分類回歸決策樹演算法時,看了不少的資料和博客。關於這兩個演算法,ID3演算法是最早的分類演算法,這個演算法剛出生的時候其實帶有很多缺陷:
無法處理連續性特徵數據
特徵選取會傾向於分類較多的特徵
沒有解決過擬合的問題
沒有解決缺失值的問題
即該演算法出生時是沒有帶有連續特徵離散化、剪枝等步驟的。C4.5作為ID3的改進版本彌補列ID3演算法不少的缺陷:
通過信息最大增益的標准離散化連續的特徵數據
在選擇特徵是標准從「最大信息增益」改為「最大信息增益率」
通過加入正則項系數對決策樹進行剪枝
對缺失值的處理體現在兩個方面:特徵選擇和生成決策樹。初始條件下對每個樣本的權重置為1。
特徵選擇:在選取最優特徵時,計算出每個特徵的信息增益後,需要乘以一個**「非缺失值樣本權重占總樣本權重的比例」**作為系數來對比每個特徵信息增益的大小
生成決策樹:在生成決策樹時,對於缺失的樣本我們按照一定比例把它歸屬到每個特徵值中,比例為該特徵每一個特徵值占非缺失數據的比重
關於C4.5和CART回歸樹
作為ID3的改進版本,C4.5克服了許多缺陷,但是它自身還是存在不少問題:
C4.5的熵運算中涉及了對數運算,在數據量大的時候效率非常低。
C4.5的剪枝過於簡單
C4.5隻能用於分類運算不能用於回歸
當特徵有多個特徵值是C4.5生成多叉樹會使樹的深度加深
————————————————
版權聲明:本文為CSDN博主「Sarah Huang」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_44794704/article/details/89406612
Ⅱ C#中怎麼在字元串中查詢子串的個數
static int Count(string WithinString, string search)
{
if (string.IsNullOrEmpty(search))
throw new ArgumentNullException("search");
int counter = 0;
int index = WithinString.IndexOf(search,0);
while(index >=0 && index < WithinString.Length)
{
counter++;
index = WithinString.IndexOf(search,index+search.Length);
}
return counter;
}
//這是一個方核裂法,塵氏搏WithinString字元串,search你想查看個數的字元派祥串,counter返回個數
Ⅲ java中文分片語件word怎麼使用
參考如下
1、快速體驗
運行項目根目錄下的腳本demo-word.bat可以快速體驗分詞效果
用法: command [text] [input] [output]
命令command的可選值為:demo、text、file
demo
text 楊尚川是APDPlat應用級產品開發平台的作者
file d:/text.txt d:/word.txt
exit
2、對文本進行分詞
移除停用詞:List<Word> words = WordSegmenter.seg("楊尚川是APDPlat應用級產品開發平台的作者");
保留停用詞:List<Word> words = WordSegmenter.segWithStopWords("楊尚川是APDPlat應用級產品開發平台的作者");
System.out.println(words);
輸出:
移除停用詞:[楊尚川, apdplat, 應用級, 產品, 開發平台, 作者]
保留停用詞:[楊尚川, 是, apdplat, 應用級, 產品, 開發平台, 的, 作者]
3、對文件進行分詞
String input = "d:/text.txt";
String output = "d:/word.txt";
移除停用詞:WordSegmenter.seg(new File(input), new File(output));
保留停用詞:WordSegmenter.segWithStopWords(new File(input), new File(output));
4、自定義配置文件
默認配置文件為類路徑下的word.conf,打包在word-x.x.jar中
自定義配置文件為類路徑下的word.local.conf,需要用戶自己提供
如果自定義配置和默認配置相同,自定義配置會覆蓋默認配置
配置文件編碼為UTF-8
5、自定義用戶詞庫
自定義用戶詞庫為一個或多個文件夾或文件,可以使用絕對路徑或相對路徑
用戶詞庫由多個詞典文件組成,文件編碼為UTF-8
詞典文件的格式為文本文件,一行代表一個詞
可以通過系統屬性或配置文件的方式來指定路徑,多個路徑之間用逗號分隔開
類路徑下的詞典文件,需要在相對路徑前加入前綴classpath:
指定方式有三種:
指定方式一,編程指定(高優先順序):
WordConfTools.set("dic.path", "classpath:dic.txt,d:/custom_dic");
DictionaryFactory.reload();//更改詞典路徑之後,重新載入詞典
指定方式二,Java虛擬機啟動參數(中優先順序):
java -Ddic.path=classpath:dic.txt,d:/custom_dic
指定方式三,配置文件指定(低優先順序):
使用類路徑下的文件word.local.conf來指定配置信息
dic.path=classpath:dic.txt,d:/custom_dic
如未指定,則默認使用類路徑下的dic.txt詞典文件
6、自定義停用詞詞庫
使用方式和自定義用戶詞庫類似,配置項為:
stopwords.path=classpath:stopwords.txt,d:/custom_stopwords_dic
7、自動檢測詞庫變化
可以自動檢測自定義用戶詞庫和自定義停用詞詞庫的變化
包含類路徑下的文件和文件夾、非類路徑下的絕對路徑和相對路徑
如:
classpath:dic.txt,classpath:custom_dic_dir,
d:/dic_more.txt,d:/DIC_DIR,D:/DIC2_DIR,my_dic_dir,my_dic_file.txt
classpath:stopwords.txt,classpath:custom_stopwords_dic_dir,
d:/stopwords_more.txt,d:/STOPWORDS_DIR,d:/STOPWORDS2_DIR,stopwords_dir,remove.txt
8、顯式指定分詞演算法
對文本進行分詞時,可顯式指定特定的分詞演算法,如:
WordSegmenter.seg("APDPlat應用級產品開發平台", SegmentationAlgorithm.BidirectionalMaximumMatching);
SegmentationAlgorithm的可選類型為:
正向最大匹配演算法:MaximumMatching
逆向最大匹配演算法:ReverseMaximumMatching
正向最小匹配演算法:MinimumMatching
逆向最小匹配演算法:ReverseMinimumMatching
雙向最大匹配演算法:BidirectionalMaximumMatching
雙向最小匹配演算法:BidirectionalMinimumMatching
雙向最大最小匹配演算法:
全切分演算法:FullSegmentation
最少分詞演算法:MinimalWordCount
最大Ngram分值演算法:MaxNgramScore
9、分詞效果評估
運行項目根目錄下的腳本evaluation.bat可以對分詞效果進行評估
評估採用的測試文本有253 3709行,共2837 4490個字元
評估結果位於target/evaluation目錄下:
corpus-text.txt為分好詞的人工標注文本,詞之間以空格分隔
test-text.txt為測試文本,是把corpus-text.txt以標點符號分隔為多行的結果
standard-text.txt為測試文本對應的人工標注文本,作為分詞是否正確的標准
result-text-***.txt,***為各種分詞演算法名稱,這是word分詞結果
perfect-result-***.txt,***為各種分詞演算法名稱,這是分詞結果和人工標注標准完全一致的文本
wrong-result-***.txt,***為各種分詞演算法名稱,這是分詞結果和人工標注標准不一致的文本
Ⅳ 智能演算法有哪些
(1)人工神經網路(Artificial Neural Network)類:反向傳播(Backpropagation)、波爾茲曼機(Boltzmann Machine)、卷積神經網路(Convolutional Neural Network)、Hopfield網路(hopfield Network)、多層感知器(Multilyer Perceptron)、徑向基函數網路(Radial Basis Function Network,RBFN)、受限波爾茲曼機(Restricted Boltzmann Machine)、回歸神經網路(Recurrent Neural Network,RNN)、自組織映射(Self-organizing Map,SOM)、尖峰神經網路(Spiking Neural Network)等。
(2)貝葉斯類(Bayesin):樸素貝葉斯(Naive Bayes)、高斯貝葉斯(Gaussian Naive Bayes)、多項樸素貝葉斯(Multinomial Naive Bayes)、平均-依賴性評估(Averaged One-Dependence Estimators,AODE)
貝葉斯信念網路(Bayesian Belief Network,BBN)、貝葉斯網路(Bayesian Network,BN)等。
(3)決策樹(Decision Tree)類:分類和回歸樹(Classification and Regression Tree,CART)、迭代Dichotomiser3(Iterative Dichotomiser 3, ID3),C4.5演算法(C4.5 Algorithm)、C5.0演算法(C5.0 Algorithm)、卡方自動交互檢測(Chi-squared Automatic Interaction Detection,CHAID)、決策殘端(Decision Stump)、ID3演算法(ID3 Algorithm)、隨機森林(Random Forest)、SLIQ(Supervised Learning in Quest)等。
(4)線性分類器(Linear Classifier)類:Fisher的線性判別(Fisher』s Linear Discriminant)
線性回歸(Linear Regression)、邏輯回歸(Logistic Regression)、多項邏輯回歸(Multionmial Logistic Regression)、樸素貝葉斯分類器(Naive Bayes Classifier)、感知(Perception)、支持向量機(Support Vector Machine)等。
常見的無監督學習類演算法包括:
(1) 人工神經網路(Artificial Neural Network)類:生成對抗網路(Generative Adversarial Networks,GAN),前饋神經網路(Feedforward Neural Network)、邏輯學習機(Logic Learning Machine)、自組織映射(Self-organizing Map)等。
(2) 關聯規則學習(Association Rule Learning)類:先驗演算法(Apriori Algorithm)、Eclat演算法(Eclat Algorithm)、FP-Growth演算法等。
(3)分層聚類演算法(Hierarchical Clustering):單連鎖聚類(Single-linkage Clustering),概念聚類(Conceptual Clustering)等。
(4)聚類分析(Cluster analysis):BIRCH演算法、DBSCAN演算法,期望最大化(Expectation-maximization,EM)、模糊聚類(Fuzzy Clustering)、K-means演算法、K均值聚類(K-means Clustering)、K-medians聚類、均值漂移演算法(Mean-shift)、OPTICS演算法等。
Ⅳ 如何對excel表格里的詞結巴分詞python
#-*-coding:utf-8-*-
importjieba
'''''
Createdon2015-11-23
'''
defword_split(text):
"""
Splitatextinwords.
(word,location).
"""
word_list=[]
windex=0
word_primitive=jieba.cut(text,cut_all=True)
forwordinword_primitive:
iflen(word)>0:
word_list.append((windex,word))
windex+=1
returnword_list
definverted_index(text):
"""
CreateanInverted-.
{word:[locations]}
"""
inverted={}
forindex,wordinword_split(text):
locations=inverted.setdefault(word,[])
locations.append(index)
returninverted
definverted_index_add(inverted,doc_id,doc_index):
"""
AddInvertd-Indexdoc_indexofthedocumentdoc_idtothe
Multi-DocumentInverted-Index(inverted),
usingdoc_idasdocumentidentifier.
{word:{doc_id:[locations]}}
"""
forword,locationsindoc_index.iteritems():
indices=inverted.setdefault(word,{})
indices[doc_id]=locations
returninverted
defsearch_a_word(inverted,word):
"""
searchoneword
"""
word=word.decode('utf-8')
ifwordnotininverted:
returnNone
else:
word_index=inverted[word]
returnword_index
defsearch_words(inverted,wordList):
"""
searchmorethanoneword
"""
wordDic=[]
docRight=[]
forwordinwordList:
ifisinstance(word,str):
word=word.decode('utf-8')
ifwordnotininverted:
returnNone
else:
element=inverted[word].keys()
element.sort()
wordDic.append(element)
numbers=len(wordDic)
inerIndex=[0foriinrange(numbers)]
docIndex=[wordDic[i][0]foriinrange(numbers)]
flag=True
whileflag:
ifmin(docIndex)==max(docIndex):
docRight.append(min(docIndex))
inerIndex=[inerIndex[i]+1foriinrange(numbers)]
foriinrange(numbers):
ifinerIndex[i]>=len(wordDic[i]):
flag=False
returndocRight
docIndex=[wordDic[i][inerIndex[i]]foriinrange(numbers)]
else:
minIndex=min(docIndex)
minPosition=docIndex.index(minIndex)
inerIndex[minPosition]+=1
ifinerIndex[minPosition]>=len(wordDic[minPosition]):
flag=False
returndocRight
docIndex=[wordDic[i][inerIndex[i]]foriinrange(numbers)]
defsearch_phrase(inverted,phrase):
"""
searchphrase
"""
docRight={}
temp=word_split(phrase)
wordList=[temp[i][1]foriinrange(len(temp))]
docPossible=search_words(inverted,wordList)
fordocindocPossible:
wordIndex=[]
indexRight=[]
forwordinwordList:
wordIndex.append(inverted[word][doc])
numbers=len(wordList)
inerIndex=[0foriinrange(numbers)]
words=[wordIndex[i][0]foriinrange(numbers)]
flag=True
whileflag:
ifwords[-1]-words[0]==numbers-1:
indexRight.append(words[0])
inerIndex=[inerIndex[i]+1foriinrange(numbers)]
foriinrange(numbers):
ifinerIndex[i]>=len(wordIndex[i]):
flag=False
docRight[doc]=indexRight
break
ifflag:
words=[wordIndex[i][inerIndex[i]]foriinrange(numbers)]
else:
minIndex=min(words)
minPosition=words.index(minIndex)
inerIndex[minPosition]+=1
ifinerIndex[minPosition]>=len(wordIndex[minPosition]):
flag=False
break
ifflag:
words=[wordIndex[i][inerIndex[i]]foriinrange(numbers)]
returndocRight
if__name__=='__main__':
doc1="""
中文分詞指的是將一個漢字序列切分成一個一個單獨的詞。分詞就是將連續的字序列按照一定的規范
重新組合成詞序列的過程。我們知道,在英文的行文中,單詞之間是以空格作為自然分界符的,而中文
只是字、句和段能通過明顯的分界符來簡單劃界,唯獨詞沒有一個形式上的分界符,雖然英文也同樣
存在短語的劃分問題,不過在詞這一層上,中文比之英文要復雜的多、困難的多。
"""
doc2="""
存在中文分詞技術,是由於中文在基本文法上有其特殊性,具體表現在:
與英文為代表的拉丁語系語言相比,英文以空格作為天然的分隔符,而中文由於繼承自古代漢語的傳統,
詞語之間沒有分隔。古代漢語中除了連綿詞和人名地名等,詞通常就是單個漢字,所以當時沒有分詞
書寫的必要。而現代漢語中雙字或多字詞居多,一個字不再等同於一個詞。
在中文裡,「詞」和「片語」邊界模糊
現代漢語的基本表達單元雖然為「詞」,且以雙字或者多字詞居多,但由於人們認識水平的不同,對詞和
短語的邊界很難去區分。
例如:「對隨地吐痰者給予處罰」,「隨地吐痰者」本身是一個詞還是一個短語,不同的人會有不同的標准,
同樣的「海上」「酒廠」等等,即使是同一個人也可能做出不同判斷,如果漢語真的要分詞書寫,必然會出現
混亂,難度很大。
中文分詞的方法其實不局限於中文應用,也被應用到英文處理,如手寫識別,單詞之間的空格就不很清楚,
中文分詞方法可以幫助判別英文單詞的邊界。
"""
doc3="""
作用
中文分詞是文本挖掘的基礎,對於輸入的一段中文,成功的進行中文分詞,可以達到電腦自動識別語句含義的效果。
中文分詞技術屬於自然語言處理技術范疇,對於一句話,人可以通過自己的知識來明白哪些是詞,哪些不是詞,
但如何讓計算機也能理解?其處理過程就是分詞演算法。
影響
中文分詞對於搜索引擎來說,最重要的並不是找到所有結果,因為在上百億的網頁中找到所有結果沒有太多的意義,
沒有人能看得完,最重要的是把最相關的結果排在最前面,這也稱為相關度排序。中文分詞的准確與否,常常直接
影響到對搜索結果的相關度排序。從定性分析來說,搜索引擎的分詞演算法不同,詞庫的不同都會影響頁面的返回結果
"""
doc4="""
這種方法又叫做機械分詞方法,它是按照一定的策略將待分析的漢字串與一個「充分大的」機器詞典中的詞條進行配,
若在詞典中找到某個字元串,則匹配成功(識別出一個詞)。按照掃描方向的不同,串匹配分詞方法可以分為正向
匹配和逆向匹配;按照不同長度優先匹配的情況,可以分為最大(最長)匹配和最小(最短)匹配;常用的幾種
機械分詞方法如下:
正向最大匹配法(由左到右的方向);
逆向最大匹配法(由右到左的方向);
最少切分(使每一句中切出的詞數最小);
雙向最大匹配法(進行由左到右、由右到左兩次掃描)
還可以將上述各種方法相互組合,例如,可以將正向最大匹配方法和逆向最大匹配方法結合起來構成雙向匹配法。
由於漢語單字成詞的特點,正向最小匹配和逆向最小匹配一般很少使用。一般說來,逆向匹配的切分精度略高於
正向匹配,遇到的歧義現象也較少。統計結果表明,單純使用正向最大匹配的錯誤率為,單純使用逆向
最大匹配的錯誤率為。但這種精度還遠遠不能滿足實際的需要。實際使用的分詞系統,都是把機械分詞
作為一種初分手段,還需通過利用各種其它的語言信息來進一步提高切分的准確率。
一種方法是改進掃描方式,稱為特徵掃描或標志切分,優先在待分析字元串中識別和切分出一些帶有明顯特徵
的詞,以這些詞作為斷點,可將原字元串分為較小的串再來進機械分詞,從而減少匹配的錯誤率。另一種方法
是將分詞和詞類標注結合起來,利用豐富的詞類信息對分詞決策提供幫助,並且在標注過程中又反過來對分詞
結果進行檢驗、調整,從而極大地提高切分的准確率。
對於機械分詞方法,可以建立一個一般的模型,在這方面有專業的學術論文,這里不做詳細論述。
"""
doc5="""
從形式上看,詞是穩定的字的組合,因此在上下文中,相鄰的字同時出現的次數越多,就越有可能構成一個詞。
因此字與字相鄰共現的頻率或概率能夠較好的反映成詞的可信度。可以對語料中相鄰共現的各個字的組合的頻度
進行統計,計算它們的互現信息。定義兩個字的互現信息,計算兩個漢字的相鄰共現概率。互現信息體現了
漢字之間結合關系的緊密程度。當緊密程度高於某一個閾值時,便可認為此字組可能構成了一個詞。這種方法
只需對語料中的字組頻度進行統計,不需要切分詞典,因而又叫做無詞典分詞法或統計取詞方法。但這種方法
也有一定的局限性,會經常抽出一些共現頻度高、但並不是詞的常用字組,例如「這一」、「之一」、「有的」、
「我的」、「許多的」等,並且對常用詞的識別精度差,時空開銷大。實際應用的統計分詞系統都要使用一部基本
的分詞詞典(常用詞詞典)進行串匹配分詞,同時使用統計方法識別一些新的詞,即將串頻統計和串匹配結合起來,
既發揮匹配分詞切分速度快、效率高的特點,又利用了無詞典分詞結合上下文識別生詞、自動消除歧義的優點。
另外一類是基於統計機器學習的方法。首先給出大量已經分詞的文本,利用統計機器學習模型學習詞語切分的規律
(稱為訓練),從而實現對未知文本的切分。我們知道,漢語中各個字單獨作詞語的能力是不同的,此外有的字常
常作為前綴出現,有的字卻常常作為後綴(「者」「性」),結合兩個字相臨時是否成詞的信息,這樣就得到了許多
與分詞有關的知識。這種方法就是充分利用漢語組詞的規律來分詞。這種方法的最大缺點是需要有大量預先分好詞
的語料作支撐,而且訓練過程中時空開銷極大。
到底哪種分詞演算法的准確度更高,目前並無定論。對於任何一個成熟的分詞系統來說,不可能單獨依靠某一種演算法
來實現,都需要綜合不同的演算法。例如,海量科技的分詞演算法就採用「復方分詞法」,所謂復方,就是像中西醫結合
般綜合運用機械方法和知識方法。對於成熟的中文分詞系統,需要多種演算法綜合處理問題。
"""
#BuildInverted-Indexfordocuments
inverted={}
documents={'doc1':doc1,'doc2':doc2,'doc3':doc3,'doc4':doc4,'doc5':doc5}
fordoc_id,textindocuments.iteritems():
doc_index=inverted_index(text)
inverted_index_add(inverted,doc_id,doc_index)
#Searchoneword
aWord="分詞"
result_a_word=search_a_word(inverted,aWord)
ifresult_a_word:
result_a_word_docs=result_a_word.keys()
print"'%s'isappearedat"%(aWord)
forresult_a_word_docinresult_a_word_docs:
result_a_word_index=result_a_word[result_a_word_doc]
forindexinresult_a_word_index:
print(str(index)+''),
print"of"+result_a_word_doc
print""
else:
print"Nomatches! "
#Searchmorethanoneword
words=["漢語","切分"]
result_words=search_words(inverted,words)
ifresult_words:
print("["),
foriinrange(len(words)):
print("%s"%(words[i])),
print("]areappearedatthe"),
forresult_words_docinresult_words:
print(result_words_doc+''),
print" "
else:
print"Nomatches! "
#Searchphrase
phrase="中文分詞"
result_phrase=search_phrase(inverted,phrase)
ifresult_phrase:
result_phrase_docs=result_phrase.keys()
print"'%s'isappearedatthe"%(phrase)
forresult_phrase_docinresult_phrase_docs:
result_phrase_index=result_phrase[result_phrase_doc]
forindexinresult_phrase_index:
print(str(index)+''),
print"of"+result_phrase_doc
print""
else:
print"Nomatches! "
Ⅵ 簽名演算法怎麼來的
數字簽名演算法分析與Hash簽名
序:這篇文章我用了近一周的時間完成,其中涉及到的RSA演算法已經在上一篇《公鑰密碼體系》中詳細的介紹過,目前數字簽名中人們使用很多的還是512位與1024位的RSA演算法。
摘要: 數字簽字和認證機構是電子商務的核心技術。數字簽名作為目前Internet中電子商務重要的技術,不斷地進行改進,標准化。本文從數字簽名的意義出發,詳細介紹了數字簽名中涉及到的內容與演算法,並自行結合進行改進。
關鍵詞:Internet公鑰加密 Hash函數 電子商務加密數字簽名
數字簽名簡介
我們對加解密演算法已經有了一定理解,可以進一步討論"數字簽名"(注意不要與數字認證混淆)的問題了,即如何給一個計算機文件進行簽字。數字簽字可以用對稱演算法實現,也可以用公鑰演算法實現。但前者除了文件簽字者和文件接受者雙方,還需要第三方認證,較麻煩;通過公鑰加密演算法的實現方法,由於用秘密密鑰加密的文件,需要靠公開密鑰來解密,因此這可以作為數字簽名,簽名者用秘密密鑰加密一個簽名(可以包括姓名、證件號碼、簡訊息等信息),接收人可以用公開的、自己的公開密鑰來解密,如果成功,就能確保信息來自該公開密鑰的所有人。
公鑰密碼體制實現數字簽名的基本原理很簡單,假設A要發送一個電子文件給B,A、B雙方只需經過下面三個步驟即可:
1. A用其私鑰加密文件,這便是簽字過程
2. A將加密的文件送到B
3. B用A的公鑰解開A送來的文件
這樣的簽名方法是符合可靠性原則的。即:
簽字是可以被確認的,
簽字是無法被偽造的,
簽字是無法重復使用的,
文件被簽字以後是無法被篡改的,
簽字具有無可否認性,
數字簽名就是通過一個單向函數對要傳送的報文進行處理得到的用以認證報文來源並核實報文是否發生變化的一個字母數字串。用這幾個字元串來代替書寫簽名或印章,起到與書寫簽名或印章同樣的法律效用。國際社會已開始制定相應的法律、法規,把數字簽名作為執法的依據。
數字簽名的實現方法
實現數字簽名有很多方法,目前數字簽名採用較多的是公鑰加密技術,如基於RSA Data Security公司的PKCS(Public Key Cryptography Standards)、DSA(Digital Signature Algorithm)、x.509、PGP(Pretty Good Privacy)。1994年美國標准與技術協會公布了數字簽名標准(DSS)而使公鑰加密技術廣泛應用。同時應用散列演算法(Hash)也是實現數字簽名的一種方法。
非對稱密鑰密碼演算法進行數字簽名
演算法的含義:
非對稱密鑰密碼演算法使用兩個密鑰:公開密鑰和私有密鑰,分別用於對數據的加密和解密,即如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能進行解密;如果用私有密鑰對數據進行加密,則只有用對應的公開密鑰才能解密。
使用公鑰密碼演算法進行數字簽名通用的加密標准有: RSA,DSA,Diffie-Hellman等。
簽名和驗證過程:
發送方(甲)首先用公開的單向函數對報文進行一次變換,得到數字簽名,然後利用私有密鑰對數字簽名進行加密後附在報文之後一同發出。
接收方(乙)用發送方的公開密鑰對數字簽名進行解密交換,得到一個數字簽名的明文。發送方的公鑰可以由一個可信賴的技術管理機構即認證中心(CA)發布的。
接收方將得到的明文通過單向函數進行計算,同樣得到一個數字簽名,再將兩個數字簽名進行對比,如果相同,則證明簽名有效,否則無效。
這種方法使任何擁有發送方公開密鑰的人都可以驗證數字簽名的正確性。由於發送方私有密鑰的保密性,使得接受方既可以根據結果來拒收該報文,也能使其無法偽造報文簽名及對報文進行修改,原因是數字簽名是對整個報文進行的,是一組代表報文特徵的定長代碼,同一個人對不同的報文將產生不同的數字簽名。這就解決了銀行通過網路傳送一張支票,而接收方可能對支票數額進行改動的問題,也避免了發送方逃避責任的可能性。
對稱密鑰密碼演算法進行數字簽名
演算法含義
對稱密鑰密碼演算法所用的加密密鑰和解密密鑰通常是相同的,即使不同也可以很容易地由其中的任意一個推導出另一個。在此演算法中,加、解密雙方所用的密鑰都要保守秘密。由於計算機速度而廣泛應用於大量數據如文件的加密過程中,如RD4和DES,用IDEA作數字簽名是不提倡的。
使用分組密碼演算法數字簽名通用的加密標准有:DES,Tripl-DES,RC2,RC4,CAST等。
簽名和驗證過程
Lamport發明了稱為Lamport-Diffle的對稱演算法:利用一組長度是報文的比特數(n)兩倍的密鑰A,來產生對簽名的驗證信息,即隨機選擇2n個數B,由簽名密鑰對這2n個數B進行一次加密交換,得到另一組2n個數C。
發送方從報文分組M的第一位開始,依次檢查M的第I位,若為0時,取密鑰A的第i位,若為1則取密鑰A的第i+1位;直至報文全部檢查完畢。所選取的n個密鑰位形成了最後的簽名。
接受方對簽名進行驗證時,也是首先從第一位開始依次檢查報文M,如果M的第i位為0時,它就認為簽名中的第i組信息是密鑰A的第i位,若為1則為密鑰A的第i+1位;直至報文全部驗證完畢後,就得到了n個密鑰,由於接受方具有發送方的驗證信息C,所以可以利用得到的n個密鑰檢驗驗證信息,從而確認報文是否是由發送方所發送。
這種方法由於它是逐位進行簽名的,只有有一位被改動過,接受方就得不到正確的數字簽名,因此其安全性較好,其缺點是:簽名太長(對報文先進行壓縮再簽名,可以減少簽名的長度);簽名密鑰及相應的驗證信息不能重復使用,否則極不安全。
結合對稱與非對稱演算法的改進
對稱演算法與非對稱演算法各有利弊,所以結合各自的優缺點進行改進,可以用下面的模塊進行說明:
Hash演算法進行數字簽名
Hash演算法也稱作散列演算法或報文摘要,Hash演算法將在數字簽名演算法中詳細說明。
Hash演算法數字簽字通用的加密標准有: SHA-1,MD5等。
數字簽名演算法
數字簽名的演算法很多,應用最為廣泛的三種是: Hash簽名、DSS簽名、RSA簽名。這三種演算法可單獨使用,也可綜合在一起使用。數字簽名是通過密碼演算法對數據進行加、解密變換實現的,常用的HASH演算法有MD2、MD5、SHA-1,用DES演算法、RSA演算法都可實現數字簽名。但或多或少都有缺陷,或者沒有成熟的標准。
Hash簽名
Hash簽名是最主要的數字簽名方法,也稱之為數字摘要法(digital digest)、數字指紋法(digital finger print)。它與RSA數字簽名是單獨的簽名不同,該數字簽名方法是將數字簽名與要發送的信息緊密聯系在一起,它更適合於電子商務活動。將一個商務合同的個體內容與簽名結合在一起,比合同和簽名分開傳遞,更增加了可信度和安全性。下面我們將詳細介紹Hash簽名中的函數與演算法。
Ⅶ python對數據進行聚類怎麼顯示數據分類
將其整理成數據集為:
[ [1,0,"yes"],[1,1,"yes"],[0,1,"yes"],[0,0,"no"],[1,0,"no"] ]
演算法過程:
1、計算原始的信息熵。
2、依次計算數據集中每個樣本的每個特徵的信息熵。
3、比較不同特徵信息熵的大小,選出信息熵最大的特徵值並輸出。
運行結果:
col : 0 curInfoGain : 2.37744375108 baseInfoGain : 0.0
col : 1 curInfoGain : 1.37744375108 baseInfoGain : 2.37744375108
bestInfoGain : 2.37744375108 bestFeature: 0
結果分析:
說明按照第一列,即有無喉結這個特徵來進行分類的效果更好。
思考:
1、能否利用決策樹演算法,將樣本最終的分類結果進行輸出?如樣本1,2,3屬於男性,4屬於女性。
2、示常式序生成的決策樹只有一層,當特徵量增多的時候,如何生成具有多層結構的決策樹?
3、如何評判分類結果的好壞?
在下一篇文章中,我將主要對以上三個問題進行分析和解答。如果您也感興趣,歡迎您訂閱我的文章,也可以在下方進行評論,如果有疑問或認為不對的地方,您也可以留言,我將積極與您進行解答。
完整代碼如下:
from math import log
"""
計算信息熵
"""
def calcEntropy(dataset):
diclabel = {} ## 標簽字典,用於記錄每個分類標簽出現的次數
for record in dataset:
label = record[-1]
if label not in diclabel.keys():
diclabel[label] = 0
diclabel[label] += 1
### 計算熵
entropy = 0.0
cnt = len(dataset)
for label in diclabel.keys():
prob = float(1.0 * diclabel[label]/cnt)
entropy -= prob * log(prob,2)
return entropy
def initDataSet():
dataset = [[1,0,"yes"],[1,1,"yes"],[0,1,"yes"],[0,0,"no"],[1,0,"no"]]
label = ["male","female"]
return dataset,label
#### 拆分dataset ,根據指定的過濾選項值,去掉指定的列形成一個新的數據集
def splitDataset(dataset , col, value):
retset = [] ## 拆分後的數據集
for record in dataset:
if record[col] == value :
recedFeatVec = record[:col]
recedFeatVec.extend(record[col+1:]) ### 將指定的列剔除
retset.append(recedFeatVec) ### 將新形成的特徵值列表追加到返回的列表中
return retset
### 找出信息熵增益最大的特徵值
### 參數:
### dataset : 原始的數據集
def findBestFeature(dataset):
numFeatures = len(dataset[0]) - 1 ### 特徵值的個數
baseEntropy = calcEntropy(dataset) ### 計算原始數據集的熵
baseInfoGain = 0.0 ### 初始信息增益
bestFeature = -1 ### 初始的最優分類特徵值索引
### 計算每個特徵值的熵
for col in range(numFeatures):
features = [record[col] for record in dataset] ### 提取每一列的特徵向量 如此處col= 0 ,則features = [1,1,0,0]
uniqueFeat = set(features)
curInfoGain = 0 ### 根據每一列進行拆分,所獲得的信息增益
for featVal in uniqueFeat:
subDataset = splitDataset(dataset,col,featVal) ### 根據col列的featVal特徵值來對數據集進行劃分
prob = 1.0 * len(subDataset)/numFeatures ### 計運算元特徵數據集所佔比例
curInfoGain += prob * calcEntropy(subDataset) ### 計算col列的特徵值featVal所產生的信息增益
# print "col : " ,col , " featVal : " , featVal , " curInfoGain :" ,curInfoGain ," baseInfoGain : " ,baseInfoGain
print "col : " ,col , " curInfoGain :" ,curInfoGain ," baseInfoGain : " ,baseInfoGain
if curInfoGain > baseInfoGain:
baseInfoGain = curInfoGain
bestFeature = col
return baseInfoGain,bestFeature ### 輸出最大的信息增益,以獲得該增益的列
dataset,label = initDataSet()
infogain , bestFeature = findBestFeature(dataset)
print "bestInfoGain :" , infogain, " bestFeature:",bestFeature
Ⅷ 〔C++演算法分析〕迷宮問題
在還沒學習bfs的情況下做到一個迷宮問題,於是的大概了解了一下DFS和BFS,就以本題為例子講一下我初識的bfs
/*
試題 : 迷宮
本題總分:15 分
【問題描述】
下圖給出了一個迷宮的平面圖,其中標記為 1 的為障礙旁握纖,標記為 0 的為可 以通行的地方。
010000
000100
001001
110000
迷宮皮滲的入口為左上角,出口為右下角,在迷宮中,只能從一個位置走到這個它的上、下、左、右四個方向之一。
對於上面的迷宮,從入口開始,可以按DRRURRDDDR 的順序通過迷宮,一運仿共10步。其中 D、U、L、R 分別表示向下、向上、向左、向右走。
對於下面這個更復雜的迷宮(30 行50 列),請找出一種通過迷宮的方式, 其使用的步數最少,在步數最少的前提下,請找出字典序最小的一個作為答案。
請注意在字典序中D<L<R<U。(如果你把以下文字復制到文本文件中,請務必檢查復制的內容是否與文檔中的一致。
在試題目錄下有一個文件 maze.txt, 內容與下面的文本相同)
【答案提交】
這是一道結果填空的題,你只需要算出結果後提交即可。
本題的結果為一個字元串,包含四種字母 D、U、L、R,
在提交答案時只填寫這個字元串,填寫多餘的內容將無法得分。
*/
#include
#include
#include
using namespace std;
const int N = 30;
const int M =50; //數據范圍
const int fx[4][2] = { 1, 0, 0, -1, 0, 1, -1, 0 }; //方向向量,直接按字典序排列
const char dic[5] = "DLRU"; //字典序
char maze[N+5][M+5]; //地圖
char path[N+5][M+5]; //上一步的方向
void bfs()
{
queue > q;
q.push(make_pair(1,1));
maze[1][1]= '1';
while(!q.empty())
{
intx = q.front().first;
inty = q.front().second;
q.pop();
for(int i = 0; i < 4; i++)
{
intxx = x + fx[i][0];
intyy = y + fx[i][1];
if(maze[xx][yy] == '0')
{
maze[xx][yy]= '1';
q.push(make_pair(xx,yy));
path[xx][yy]= i;
}
}
}
}
void print(int x, int y)
{
if(x != 1 || y != 1)
{
intt = path[x][y];
print(x- fx[t][0], y - fx[t][1]);
maze[x][y]= 1; //將走過的地方置1
cout<< dic[t];
}
}
int main()
{
freopen("text.ini","r", stdin);
memset(maze,'1', sizeof maze); //加圍牆
for(int i = 1; i <= N; i++)
cin>> maze[i]+1;
bfs();
memset(maze,0, sizeof maze); //初始化,0為牆,1為路徑
maze[1][1]= 1;
print(N,M); //輸出最短路徑字元,同時標記路徑為1
//輸出迷宮圖
cout<< endl;
for(int i = 0; i <= N + 1; i++)
{
for(int j = 0; j <= M + 1; j++)
{
if(i == 0 || i == N + 1 || j == 0 || j == M + 1) cout << "※"; //畫圍牆
elseif (maze[i][j] == 0) cout << "■"; //迷宮里的牆
elsecout << "□"; //最短路的路徑
}
cout<< endl;
}
cout<< "\nover" << endl;
while(1);
return0;
}
事例中,我們先將整個maze數組鋪滿全部范圍,來建立牆,然後再對maze數組賦值,來建立迷宮,從而達到,牆裹著迷宮的效果。
然後我們建立一個名為q的queue來保存我們現在所在的位置。
數組fx代表方向,dic代表方向的字元。
數組path記錄上一步的方向
尋路部分
首先將起點放入queue中,取得點之後,讓起點出隊,在吧起點堵死成牆。
然後從起點獲得的值去同時向外延伸,遇到牆不延伸,死路表示這條線終結,沒次延伸後,都把原來的點設置成牆。
在延伸的過程中,沒到一個點便堵死成牆,並且出隊,這樣防止一個點多重賦值。
因為是對目前隊列里所有的點同時延伸(雖然有先後順序,但是總會延伸完這一階段的點才會延伸下一階段的點),所以不必擔心走那條路會早一點到某一點,因為完到的,已經被堵死了。
在將所有起點能到達的點延伸完畢之後,隊列為空,進行結算。
如果起點能達到終點的話,終點的path必定有值,只需要在終點倒推即可得到答案。
畫圖部分
先把全體設置成牆,再按照path倒推,結果是路程全被篩選出來。
by:有我wa
Ⅸ dic應變測量常用的行業有哪些
XTDIC主要應用在:汽車製造、航空航天、3C電子、岩煤土木、生物醫學、材料研究
Ⅹ C#List中相同元素合並演算法問題
List<int>list=newList<int>(){2,3,4,5,3,5,4,2,2,4,3};
varresult1渣嫌=fromiinlistgroupibyi;
varresult2=fromj洞磨inresult1納梁斗selectj.Key*j.Count();
list=result2.ToList();
附加一個連接
http://www.cnblogs.com/zwq194/archive/2010/08/17/1801411.html