一、手寫數字識別
一個手寫數字,通過電腦程序做判斷,這個數字是什麼。
技術點:numpy、KNN
問題
問題1
爲什麼同一個數字要有多個樣本?
原因:手寫數字存在不確定性,每次寫的同一個數字都不完全一樣,所以需要更多的樣本,才能使匹配的結果更準確。
問題2
文件名的解讀?
_
前爲該樣本代表的數字,_
後爲代表相同數字的樣本序號。
問題3
假如每個文件生成一個32*32的矩陣,那麼將生成很多個矩陣,後續x將分別跟這些矩陣進行運算,導致計算量增大。
解決:因爲矩陣能夠進行簡化計算,現在將多個文件生成唯一一個樣本集矩陣(這個矩陣,一個文件對應一行,有多少個文件就有多少行)。
實現
from os import listdir
import numpy as np
import random
# 從文件中讀取數據到矩陣
# 一行
def img2vector(file_path):
# 根據文件內容生成矩陣
# 創建向量
vect = np.zeros((1,1024))
with open(file_path,'r') as fp:
for i in range(32): # 32行
line_str = fp.readline()
for j in range(32): # 每行32個字符
vect[0,(i*32)+j] = line_str[j]
return vect
# KNN算法實現步驟
# 第一步:構建數據
file_list = listdir('digits/trainingDigits')
# 行:有多少個文件就有多少行
# 列:32*32
BigMat = np.zeros((len(file_list),1024))
for i,file in enumerate(file_list):
vect = img2vector('digits/trainingDigits/'+file)
BigMat[i,:] = vect
# print(BigMat)
# print(BigMat.shape) # (1934, 1024)
# 第二步:計算相似度
test_list = listdir('digits/testDigits')
test = random.choice(test_list)
print(test)
x = img2vector('digits/testDigits/' + test)
# x = img2vector('digits/testDigits/9_16.txt')
diff = BigMat - x
# 按行求和
# !!!矩陣中A*A != A**2
# 一個是矩陣相乘,一個是數乘
d = np.sum(diff**2,axis=1)**0.5 # 得到一個行矩陣
# print(d)
# 第三步:排序,並取前k個樣本
sorted_ = np.argsort(d)
sorted_ = sorted_[:11]
# 第四步:投票
result = {}
for i in sorted_:
re = file_list[i].split('_')[0]
result[re] = result.get(re,0) + 1
result = sorted(result.items(),key=lambda item:item[1],reverse=True)
print(result)
print('該數字爲:',result[0][0])
二、pandas
numpy–數
pandas–表
pandas是基於numpy實現的。
統計分析是數據分析重要的組成部分,它幾乎貫穿了整個數據分析的流程。應用統計方法,將定量與定性相結合。
(一)讀取文件
1.讀excel文件
detail = pd.read_excel('data/meal_order_detail.xlsx')
print(detail)
2.讀csv文件
order = pd.read_csv('data/meal_order_info.csv',encoding='gbk')
print(order)
3.讀表文件
order = pd.read_table('data/meal_order_info.csv',sep=',',encoding='gbk')
print(order)
(二)常見屬性
print(detail.shape)
print(detail.ndim)
print(detail.size)
print(detail.columns)
print(detail.dtypes)
(三)統計分析–分析訂單詳情表
dishes_name = detail['dishes_name']
print(dishes_name)
1.loc()
可以獲取指定行或列的數據。
取出訂單詳情表中的counts和dishes_name兩列的數據。
格式:表對象.loc[行,列]
result = detail.loc[:,:] # 此時result等同於detail
result = detail.loc[:,('counts','dishes_name')]
print(result)
result = detail.loc[:5,('counts','dishes_name')]
print(result)
2.describe()
描述函數。
print(result.describe())
3.head()和tail()
取前幾行或後幾行的數據,默認爲5行。
print(detail.head())
print(detail.head(2))
4.相對不太常用的獲取數據的方法
(1)0-4行的dishes_name數據
print(detail['dishes_name'][:5])
(2)0-4行所有數據
print(detail[:][:5])
(四)類型
print(type(detail)) # <class 'pandas.core.frame.DataFrame'>
# DataFrame--數據結構--傾向於字典
# 凡是DataFrame類型的對象,都可以使用列名獲取數據
# 如:detail['dishes_name']
print(type(detail['dishes_name'])) # <class 'pandas.core.series.Series'>
# Series--序列--相當於一個一維數組--傾向於列表
問題
print(type(detail[:])) # <class 'pandas.core.frame.DataFrame'>
print(type(detail[:][:5])) # <class 'pandas.core.frame.DataFrame'>
爲什麼它們不是Series類型??
原因:它們不是一維!
print(type(detail.columns)) # <class 'pandas.core.indexes.base.Index'>