Yazar | Toffee Cat
Kaynak | CSDN blogu, sorumlu editör | Xi Yan
Baş resmi | Visual China'dan CSDN indirmesi
Üretildi | CSDN (ID: CSDNnews)
El yazısıyla yazılan rakam tanıma, KNN algoritmasının özellikle klasik bir örneğidir. Veri kaynaklarını elde etmenin iki yolu vardır, biri MNIST veri setinden ve diğeri UCI Irvine Üniversitesi Makine Öğrenimi Deposundan indirilir. misal.
Temel fikir, aşağıda gösterildiği gibi 32x32'lik bir ikili matriste hangi sayının 0-9 arasında olduğunu anlamak için KNN algoritmasını kullanmaktır.
Veri seti, biri toplam 1934 veri içeren eğitim veri seti, diğeri ise toplam 946 veri içeren test veri seti olmak üzere iki bölümden oluşmaktadır. 5. 55_56.txt numaralı 56. örnek gibi tüm veri isimlendirme formatları tek tiptir Bu, örneğin gerçek etiketinin çıkarılmasını kolaylaştırmak için yapılır.
Ayrıca iki veri formatı vardır, biri yukarıdaki resimdeki gibi 0 ve 1'den oluşan bir metin dosyasıdır; diğeri ise görüntüyü yukarıdaki resimle aynı formata dönüştürmek için biraz işlem gerektiren el yazısı dijital bir resimdir ve aşağıdakilerin tümü Giriş.
Veri toplayın: veri kaynaklarını açın
Verileri analiz edin ve nasıl işleneceğini öğrenin
Eğitim verilerini içe aktarın ve yapılandırılmış bir veri biçimine dönüştürün
Mesafeyi hesapla (Öklid mesafesi)
Test verilerini içe aktarın ve model doğruluğunu hesaplayın
El yazısı sayılar, pratik uygulama modeli
Tüm veriler 0 ve 1'den oluştuğu için veri standardizasyonuna ve normalleştirmeye gerek yoktur.
İki örnek arasındaki mesafeyi hesaplarken, her özniteliğin bire bir karşılığı vardır, bu nedenle burada 32x32 dijital matris, örnekler arasındaki mesafenin hesaplanmasını kolaylaştırmak için 1x1024 dijital matrise dönüştürülür.
1 # Metin dosyalarını işleme 2def img_deal (dosya): 3 # 1 * 1024 tek boyutlu sıfır matrisi oluşturun 4 the_matrix = np.zeros ((1,1024)) 5 fb = açık (dosya) Aralıktaki i için 6 (32): 7 # satır satır okumak 8 lineStr = fb.readline (32) aralığında j için 9: 10 # 32 * 32 = 1024 öğeyi tek boyutlu sıfır matrisine atayın 11 the_matrix = int (lineStr) 12 matrisi döndürNumpy, tek boyutlu bir matrisi birkaç kez yatay ve birkaç kez dikey olarak kopyalayabilen bir karo yöntemine sahiptir; bu nedenle, bir test verisi karo yöntemiyle işlendikten sonra, yeni bir matris elde etmek için eğitim verileri çıkarılır ve ardından matrisin her biri Veri (yatay) kareler eklendikten ve kök açıldıktan sonra, test verileri ile her bir eğitim verisi arasındaki mesafe elde edilebilir.
Bir sonraki adım, tüm mesafeleri artan sırada sıralamak, en üstteki K'yi ve bu aralıkta her sayı kategorisinin numarasını almak ve daha sık görünen numara kategorisinin etiketini döndürmektir.
1def sınıflandırması (test_data, train_data, etiket, k): 2 Boyut = train_data.shape 3 # Her bir test verisi satırını kopyalayın Zamanları eksi egzersiz verilerini boyutlandırın, Boyutları yatay olarak kopyalayın ve dikey olarak 1 kez kopyalayın 4 the_matrix = np.tile (test_data, (Size, 1)) - train_data 5 # çıkarma sonucunun karesi 6 sq_the_matrix = the_matrix ** 27 # karelerin toplamı, eksen = 1 yatay temsil eder 8 all_the_matrix = sq_the_matrix.sum (axis = 1) 9 # Sonuç son mesafeyi elde etmek için kök numarasını açın 10 mesafe = all_the_matrix ** 0.511 # Mesafeyi küçükten büyüğe sıralayın ve sonucu dizin olarak verin 12 sort_distance = distance.argsort 13 dis_Dict = {} 14 # İlk k'yi alın (K) aralığında i için 15: 16 # İlk K etiketlerini alın 17 the_label = etiket 18 # Etiketin anahtarını ve değerini sözlüğe aktarın 19 dis_Dict = dis_Dict.get (the_label, 0) +120 # Sözlüğü değerin boyutuna göre, büyükten küçüğe, yani K aralığında sıralayın, en sık kullanılan etiketleri filtreleyin 21 sort_Count = sıralanmış (dis_Dict.items, key = operator.itemgetter (1), reverse = True) 22 # En sık kullanılan etikete geri dönün 23 return sort_CountÖncelikle eğitim veri setinin işlenmesi gerekir. Listdir yöntemi, bir klasördeki tüm dosyaları döndürmek ve ardından satır ve 1024 sütun sayısı ile eğitim veri setindeki her verinin gerçek etiketini içeren bir eğitim veri matrisi oluşturmaktır. Kesme ekstraksiyonu etiketler listesinde saklanır, yani sınıflandırma fonksiyonunda geçirilen etiket mesafeden hesaplanır.
1 etiket = 2 # listdir yöntemi, bir klasörde bulunan dosyaları döndürmektir 3 train_data = listdir ('trainingDigits') 4 # Klasördeki dosya sayısını alın 5 m_train = len (train_data) 6 # Sütun numarası train_matrix ve satır 1024 olan bir sıfır matrisi oluşturun 7 tren_matrix = np.zeros ((m_train, 1024)) Aralıktaki i için 8 (m_train): 9 file_name_str = train_data 10 file_str = dosya_adı_str.split ('.') 11 # eğitim setindeki her verinin gerçek etiketini kesin 12 dosya_num = int (dosya_dizi.split ('_')) 13 labels.append (dosya_numarası) 14 # Eğitim veri kümesindeki tüm verileri train_matrix'e aktarın 15 train_matrix = img_deal ('trainingDigits /% s'% file_name_str)Daha sonra test eğitim veri seti yukarıdaki ile aynı şekilde işlenir ve test veri matrisi TestClassify, eğitim veri matrisi train_matrix, eğitim verileri gerçek etiket etiketleri ve K hesaplama mesafe sınıflandırma fonksiyonuna geçirilir ve son olarak model doğruluk oranı hesaplanır. Ve tahmin edilen hata verilerini çıktı olarak alın.
1hata = 2 test_matrix = listdir ('testDigits') 3 doğru = 0.04 m_test = len (test_matrix) Aralıktaki i için 5 (m_test): 6 file_name_str = test_matrix 7 file_str = dosya_adı_str.split ('.') 8 # Test veri setindeki her verinin gerçek sonucu 9 dosya_num = int (dosya_dizi.split ('_')) 10 TestClassify = img_deal ('testDigits /% s'% file_name_str) 11 classify_result = sınıflandır (TestClassify, train_matrix, etiketler, 3) 12 baskı ('Öngörülen sonuç:% s \ tGerçek sonuç:% s'% (classify_result, file_num)) 13 classify_result == file_num: 14 doğru + = 1.015 başka: 16 error.append ((file_name_str, classify_result)) 17 baskı ("Doğru oran: {:. 2f}%". Format (doğru / float (m_test) * 100)) 18 baskı (hata) 19 baskı (len (hata))Kod çalıştırma kısmının ekran görüntüsü aşağıdaki gibidir
K = 3 olduğunda, doğruluk oranı% 98.94'e ulaşır Bu model için doğruluk oranı çok etkileyicidir, ancak işletim verimliliği nispeten düşüktür ve 30 saniyeye yaklaşır. Her bir test verisinin yaklaşık 2000 eğitim verisinden mesafeyi hesaplaması gerektiğinden ve her hesaplama 1024 boyutlu kayan nokta işlemi içerdiğinden, yüksek frekanslı çok boyutlu hesaplamalar modelin düşük verimliliğinin ana nedenidir.
Aşağıdaki şekil K değeri ile model doğruluğu arasındaki ilişkiyi göstermektedir: K = 3 olduğunda, modelin doğruluğu zirveye ulaşır K arttıkça doğruluk küçülür ve küçülür, bu nedenle bu verilerin gürültüsü hala nispeten küçüktür.
Modelleme tamamlandıktan sonra modelin doğruluğu da iyidir El yazısı sayıları neden kendiniz test ediyorsunuz? Bu yüzden birkaç numarayı elle yazdım.
Normal olarak çekilen resimler RGB renkli resimlerdir ve pikseller de farklıdır, bu nedenle resim üzerinde iki işlem yapmanız gerekir: yukarıdaki algoritmamızın gereksinimlerini karşılamak için resmi siyah beyaz bir resme dönüştürmek ve pikseli 32x32'ye dönüştürmek; pikseller için , Değer genellikle 0-255 arasındadır; 255 beyazı, 0 siyahı temsil eder, ancak el yazısı dijital piksellerin rengi standartlaştırılmadığından, siyah ve beyaz arasındaki farkı değerlendirmek için bir eşik belirledik.
Metin koduna resim aşağıdaki gibidir:
1def pic_txt: Aralıktaki i için 2 (0,10): 3 img = Image.open ('. \ El yazısı \% s.png'% i) 4 # Resim pikselini 32X32 olarak değiştirin 5 img = resim yeniden boyut ((32,32)) 6 # Renkli resimleri siyah beyaz resimlere dönüştürün 7 img = img.convert ('L') 8 #Kaydet 9 yol = '. \ El yazısı \% s_new.jpg'% i 10 img. Kaydet (yol) 11 (0,10) aralığında i için: 12 fb = open ('. \ Hand_written \% s_handwritten.txt'% i, 'w') 13 new_img = Image.open ('. \ El yazısı \% s_new.jpg'% i) 14 # Resmin genişliğini ve yüksekliğini okuyun 15 genişlik, yükseklik = new_img.size Aralıktaki i için 16 (yükseklik): Aralıktaki j için 17 (genişlik): 18 # Piksel alın 19 renk = new_img.getpixel ((j, i)) 20 # Yüksek piksel resimdeki beyazdır 21 renk ise > 170: 22 fb.write ('0') 23 başka: 24 fb.write ('1') 25 fb.write ('\ n') 26 fb. YakınGenel kod çalıştıran ekran görüntüsü aşağıdaki gibidir:
Doğruluk oranı% 70. Sonuçta çok az test verisi var 10 sayı arasında 4, 7 ve 8'in tahminleri yanlış, bu oldukça etkileyici.Işık probleminden dolayı bazı numaraların sol alt köşesinde doğru olacak şekilde bazı koyu gölgeler olacak. Test sonuçlarının belirli bir etkisi vardır. Benzer durumlardan kaçınırsanız ve daha fazla test verisi eklerseniz, doğruluk oranı kesinlikle artacaktır.