mrgloom 242 Жалоба Опубликовано June 6, 2012 ну с учителем как то прозаично, тем более что внутри класса цифра сильно варьируется и можно некоторые примеры посчитать за неправильные. именно хочется найти какие то взаимосвязи. кстати если я вектор длины N проецирую на пространство размерности N, то я вроде как получаю результат отличный от того если бы я не проецировал, т.е. у PCA видимо есть какое то еще свойство кроме уменьшения размерности. потом интересно посмотреть на центр кластеров, это как я понимаю усредненное изображение по кластеру, наверно можно ввести еще такое понятие как дисперсия внутри кластера, чтобы посмотреть сильно ли различаются сэмплы в кластере. вот такой результат получился если взять максимальный размер пространсва 28*28. это уже спроецированные векторы, слева видно что всё в таких шумных точках, это видимо важные данные, а если смещаться в право, то всё одно и то же, видимо не важные, единственное меня смущает что полоски получились какого то разного цвета, возможно это не верно, т.к. я нормировал для вывода каждую полоску, а может быть надо было нормировать всё изображение. кстати можно найти базис размерности n, а проецировать на размерность k (k<n), т.е. на k первых максимальных? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 6, 2012 вообще если выбрать не целевое кол-во кластеров, а большее, то получается что то более осмысленное, как бы подкластеры. на самом деле ведь по такому подходу можно наглядно оценивать хорошо ли выбран вектор признаков. единственное пока не очень понятно как сливать подкластеры в целевые кластеры и как можно скажем так отфильтровать шумные сэмплы? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 6, 2012 Что касается проецирования, то Вы же всегда находите все собственные числа и векторы. Смысл PCA именно в том и есть, чтобы делать репроекцию на векторы с максимальными собственными числами, это и есть уменьшение размерности. По поводу k-means и тому подобного: http://charlotte.ucsd.edu/users/elkan/cikm02.pdf Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 8, 2012 попробовал на 10к данных knn, потом решил на тех же данных проверить как работает и мне выдало все лишь 963 правильных ответа из 10к. это нормально? void do_knn() { //первая часть тренировка //читаем данные vector<Mat> db; read_data("C:/MNIST/10k_images.bin",db); int rows=db[0].rows; int cols=db[0].cols; //читаем лэйблы vector<unsigned char> vec_labels; read_labels("C:/MNIST/10k_labels.bin",vec_labels); //приводим исходные данные к нужным матрицам int total = rows*cols; Mat trainData(total, db.size(), CV_32FC1); for(int i = 0; i < db.size(); i++) { Mat X = trainData.col(i); db[i].reshape(1, total).col(0).convertTo(X, CV_32FC1, 1/255.); } Mat trainClasses(vec_labels); trainClasses.convertTo(trainClasses,CV_32FC1, 1/255.); int k=32;//можно варьировать Mat t= trainData.t(); CvMat trainData_= t; CvMat trainClasses_= trainClasses; CvKNearest knn(&trainData_,&trainClasses_, 0, false, k); int c_tottal=0; int c_good=0; for(int i = 0; i < db.size(); ++i) { Mat t=db[i].reshape(1,1); t.convertTo(t,CV_32FC1, 1/255.); CvMat sample= t; CvMat* currentLabel= cvCreateMat( 1, 1, CV_32FC1); knn.find_nearest(&sample, k, currentLabel); if(255*currentLabel->data.fl[0]==vec_labels[i]) c_good++; c_tottal++; int g=0; } cout<<c_good; cout<<c_tottal; } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 8, 2012 Такой же результат был бы если просто вслепую выбирать ответ. (вероятность 1/10) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 8, 2012 дело было в параметре k в find_nearest, почему то если его поставить таким же как при обучении =32, то получается плохой результат, попробовал =5 и норм ~97%(правда на той же самой выборке).Если выбрать =1 то на той же самой выборке получим 100%. какое k оптимально для обучения и поиска опять же непонятно. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 13, 2012 кстати я тут подумал вот о чём приминительно к нахождению лиц. если мы находим лица с помощью хаара, то нам надо иметь примеры положительные и отрицательные. что если мы имеем довольно много фотографий людей(один вариант простой как на паспорт или другой вариант сложнее в "натуральной среде обитания") и пытаемся найти какую либо зависимость в данных, выделяя из изображения какие либо высоуровневые или низкоуровневые признаки. т.е. алгоритм нам как бы сам найдет "примеры" через похожести в данных, а мы уже на последней стадии сможем проверить эти данные на адекватность. имеет ли такой подход право на существование? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 13, 2012 Я думаю тут что то близкое к проблеме обнаружения аномалий. (Anomaly Detection). Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 21, 2012 как можно отобразить это на 2д? (т.е. чтобы похожие элементы были близко, а не похожие не близко) я попробовал спроецировать через PCA на 2 компоненты, но это получилось что то не то. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 21, 2012 Вообще PCA должен работать, и его для таких вещей часто применяют. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 22, 2012 ну у меня получилось нечто такое http://forum.vingrad.ru/act-Attach/type/post/id-2497082.html рамка в один пиксель вокруг изображения почти заполнена. а хотелось бы http://homepage.tudelft.nl/19j49/t-SNE_files/mnist_large.jpg Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 22, 2012 Мне не дают посмотреть что у Вас получилось, у меня выдает по первым векторам такое: Вот три вида (проекции на плоскости, задаваемые парами векторов (v0,v1),(v0,v2) и (v1,v2)): #include <iostream> #include <vector> #include <stdio.h> #include "opencv2/core/core.hpp" #include "opencv2/core/gpumat.hpp" #include "opencv2/core/opengl_interop.hpp" #include "opencv2/gpu/gpu.hpp" #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "fstream" #include "iostream" using namespace std; using namespace cv; inline void endian_swap(unsigned short& x) { x = (x>>8) | (x<<8); } inline void endian_swap(unsigned int& x) { x = (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); } // __int64 for MSVC, "long long" for gcc inline void endian_swap(unsigned __int64& x) { x = (x>>56) | ((x<<40) & 0x00FF000000000000) | ((x<<24) & 0x0000FF0000000000) | ((x<<8) & 0x000000FF00000000) | ((x>>8) & 0x00000000FF000000) | ((x>>24) & 0x0000000000FF0000) | ((x>>40) & 0x000000000000FF00) | (x<<56); } void read_mnist_labels(vector<unsigned char>& vec_lbl) { //vector<Mat> vec_img; ifstream file; file.open("C:/MNIST/train-labels.idx1-ubyte",ifstream::in | ifstream::binary); if (file.is_open()) { unsigned int magic_number=0; unsigned int number_of_labels=0; file.read((char*)&magic_number,sizeof(magic_number)); //если перевернуть то будет 2051 endian_swap(magic_number); file.read((char*)&number_of_labels,sizeof(number_of_labels));//если перевернуть будет 10к endian_swap(number_of_labels); cout << "magic_number=" << magic_number << endl; cout << "number_of_labels=" << number_of_labels << endl; for(int i=0;i<number_of_labels;++i) { unsigned char t_ch=0; file.read((char*)&t_ch,sizeof(t_ch)); vec_lbl.push_back(t_ch); } } } void read_mnist(vector<Mat>& vec_img) { //vector<Mat> vec_img; ifstream file; file.open("C:/MNIST/train-images.idx3-ubyte",ifstream::in | ifstream::binary); //file.open("C:/MNIST/t10k-images.idx3-ubyte",ifstream::in | ifstream::binary); if (file.is_open()) { unsigned int magic_number=0; unsigned int number_of_images=0; unsigned int n_rows=0; unsigned int n_cols=0; file.read((char*)&magic_number,sizeof(magic_number)); //если перевернуть то будет 2051 endian_swap(magic_number); file.read((char*)&number_of_images,sizeof(number_of_images));//если перевернуть будет 10к endian_swap(number_of_images); file.read((char*)&n_rows,sizeof(n_rows)); endian_swap(n_rows); file.read((char*)&n_cols,sizeof(n_cols)); endian_swap(n_cols); cout << "magic_number=" << magic_number << endl; cout << "n_rows=" << n_rows << endl; cout << "n_cols=" << n_cols << endl; cout << "number_of_images=" << number_of_images << endl; for(int i=0;i<number_of_images;++i) { Mat temp(n_rows,n_cols,CV_8UC1); for(int r=0;r<n_rows;++r) { for(int c=0;c<n_cols;++c) { unsigned char t_ch=0; file.read((char*)&t_ch,sizeof(t_ch)); //тут идет запись матрицы 28х28 в вектор temp.at<unsigned char>(r,c)= t_ch; //возможно можно как то быстрее копировать построчно? } } vec_img.push_back(temp); } } } //----------------------------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------------------------- void calc_PCA(vector<Mat>& db,int numPrincipalComponents,Mat& EigVec,Mat& Mean) { int total = db[0].rows * db[0].cols; int rows=db[0].rows; int cols=db[0].cols; Mat mat(total, db.size(), CV_32FC1); for(int i = 0; i < db.size(); i++) { Mat X = mat.col(i); db[i].reshape(1, total).col(0).convertTo(X, CV_32FC1, 1/255.); } EigVec=Mat(numPrincipalComponents,total,CV_32FC1); // do pca PCA pca(mat, Mat(), CV_PCA_DATA_AS_COL, numPrincipalComponents); Mat imgDst; imgDst.create( rows, cols*numPrincipalComponents, CV_32FC1 ); imgDst=0; pca.mean.copyTo(Mean); for(int i=0;i<numPrincipalComponents;++i) { Mat temp=(pca.eigenvectors.row(i)); normalize(temp,temp); // Это и есть собственный вектор temp.copyTo(EigVec.row(i)); // --------------------------------------------------- // Этот кусок нужен для того, чтобы были видны картинки // --------------------------------------------------- double m,M; minMaxLoc(temp,&m,&M); if((M-m)!=0) { temp-=m; temp/=(M-m); temp*=255.0; } temp=temp.reshape(1, rows); temp.copyTo(imgDst(Rect(i*cols,0,cols,rows))); // --------------------------------------------------- } imwrite("result.png", imgDst); int f=0; } CvScalar random_color(CvRNG* rng) { int color = cvRandInt(rng); return CV_RGB(color&255, (color>>8)&255, (color>>16)&255); } //----------------------------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------------------------- int main( int argc, char** argv ) { const int NumVectors=3; vector<Mat> MNIST; read_mnist(MNIST); vector<unsigned char> MNIST_L; read_mnist_labels(MNIST_L); int rows=MNIST[0].rows; int cols=MNIST[0].cols; // --------------------------------------------------- // Составили картинку из 100 первых изображений // --------------------------------------------------- Mat imgDst; imgDst.create( 10*rows, 10*cols, CV_8UC1 ); imgDst=0; for(int i=0;i<10;i++) { for(int j=0;j<10;j++) { MNIST[i+j*10].copyTo(imgDst(Rect(i*cols,j*rows,cols,rows))); } } imshow("result",imgDst); // --------------------------------------------------- // Посчитаем собственные векторы возьмем NumVectors с // максимальными собственными числами // --------------------------------------------------- Mat EigVec,mean,result,repared; calc_PCA(MNIST,NumVectors,EigVec,mean); // --------------------------------------------------- // Спроецируем 10 первых цифр на собственные векторы // получаем координаты этих цифр в NumVectors мерном пространстве // а затем восстановим их по этим проекциям. // --------------------------------------------------- for(int i=0; i<10; i++) { // Спроецируем на собственные векторы cv::PCAProject(MNIST[i].reshape(1, rows*cols),mean,EigVec,result); cout << result << endl; // Восстановим по их NumVectors проекциям на собственные оси. cv::PCABackProject(result,mean,EigVec,repared); // переведем обратно в прямоугольный вид // и выведем в файл repared=repared.reshape(1, rows); char str[100]; sprintf(str,"repared_%d.png",i); imwrite(str,repared); } vector<float> x; vector<float> y; for(int i=0; i<60000; i++) { // Спроецируем на собственные векторы cv::PCAProject(MNIST[i].reshape(1, rows*cols),mean,EigVec,result); y.push_back(result.at<float>(1)); x.push_back(result.at<float>(2)); } pair<vector<float>::iterator,vector<float>::iterator> ylimits = minmax_element(y.begin(),y.end()); pair<vector<float>::iterator,vector<float>::iterator> xlimits = minmax_element(x.begin(),x.end()); float w=*xlimits.second-*xlimits.first; float h=*ylimits.second-*ylimits.first; Mat imacl(Size(w/5,h/5),CV_8UC3); cout<< "h=" << h << " w=" << w << endl; imacl=0; CvRNG rng(35435345); CvScalar Colors[256]; for (int i=0;i<256;i++) { Colors[i]=random_color(&rng); } for(int i=0; i<10; i++) { rectangle(imacl,Point(i*10,0),Point(i*10+10,10),Colors[i],-1); } for(int i=0; i<x.size(); i++) { int X=(x[i]-*xlimits.first)/5; int Y=(y[i]-*ylimits.first)/5; imacl.at<Vec3b>(Y,X)[0]=Colors[MNIST_L[i]].val[0]; imacl.at<Vec3b>(Y,X)[1]=Colors[MNIST_L[i]].val[1]; imacl.at<Vec3b>(Y,X)[2]=Colors[MNIST_L[i]].val[2]; } imshow("imacl",imacl); x.clear(); y.clear(); waitKey(0); return 0; }[/code] 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 22, 2012 Кстати, вот здесь точно то, что использовано для получения той картинки : http://homepage.tudelft.nl/19j49/t-SNE.html Плюс к тому Isomap: http://isomap.stanford.edu/ И хорошая статейка: http://axon.cs.byu.edu/Dan/678/miscellaneous/Manifold.example.pdf Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано June 25, 2012 Вот три вида (проекции на плоскости, задаваемые парами векторов (v0,v1),(v0,v2) и (v1,v2)): не понял это вы 3Д проецировали на 3 разных плоскости в 2Д? Кстати, вот здесь точно то, что использовано для получения той картинки : http://homepage.tude...9j49/t-SNE.html Плюс к тому Isomap: http://isomap.stanford.edu/ это то все понятно, но боюсь если не знать как этим пользоваться ничего не выйдет. пока наверно можно хотя бы в матлабе поиграться с PCA и проецировать в 3Д, там кстати его крутить можно? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 25, 2012 Это opencv-шное 2Д, просто разные пары осей беру по X и Y. Можно и в 3д построить (OpenGL) или записать координаты и в матлаб закинуть, там крутить можно. Иногда строю такие вещи в Asymptote качественный вывод (много разных форматов) получается, причем можно 3д в pdf встраивать. Вот в этом куске цифры менял: y.push_back(result.at<float>(1)); x.push_back(result.at<float>(2));[/code] Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано July 13, 2012 пытаюсь воспользоваться этой программой(которая похоже оказалась довольно глючной) http://mldemos.epfl.ch/ в хелпе написано Importing data Generating data in MLDemos is done in three different ways: by manually drawing samples, by projecting image data through PCA (via the Projection panel), or by loading external data. The data format used by the software is ascii-based and contains on the first line the # of samples followed by # of dimensions (only the first 2 dimensions are used in the software). The file then contains #samples lines with the coordinates of each sample followed by a class number (0 ... 255) and a flag (0-3) that allows to determine whether a sample is unused or in the training, validation or test sets. a concrete example would be 4 2 0.10 0.11 0 0 0.14 0.91 0 0 0.43 0.74 1 0 0.28 0.34 1 0 which presents 4 two-dimensional samples, two from class 0 and one from class 1. When the file is saved from MLDemos, the software adds the current algorithm parameters (provided an algorithm was selected), which can be useful for demonstration purposes. If no such information is present, the default algorithm parameters are selected. You should be able to convert your own data to this format with any script. пробую простейший пример 4 2 0.10 0.11 0 0 0.14 0.91 0 0 0.43 0.74 1 0 0.28 0.34 1 0 пробую пример где размерность >2, хотя даже для простейшего примера =2 нормально не работает. даже название классов отображается как то не так вообщем такое ощущение, что либо я что то не так делаю, либо программа вообще не пригодна для данных размерности >2 п.с. качал бинарную версию для винды, возможно сборка из сорцов и их просмотр прояснят что либо, но пока туда лезть не охота, ибо там много зависимостей судя по всему. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 13, 2012 Вообще - то она для размерности 2 и есть. Если больше, то попробуйте язык R (ML-сообщество почему то его очень любит). http://www.r-project.org/ IDE здесь: http://rstudio.org/ Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано July 13, 2012 ну вопервых там написано by projecting image data through PCA (via the Projection panel) откуда же там предполагается брать многомерные данные? а во вторых он даже для 2-мерного случая неправильно загружает(во всяком случае 1 лишнюю строку+ неправильно отображение названий классов) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 13, 2012 Насчет строки, там нет лишнего cr lf в конце файла ? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано July 13, 2012 нет я так тоже пробовал, может там должно быть не cr lf, а что то другое? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 13, 2012 А, ну так там же вначале количество строк и размерность данных указывается (можно попробовать поменять 8 на 7). Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано July 13, 2012 попробовал, такое ощущение, что программе всё равно какое первое число, грузит всё так же, хоть 0 ставь. хотя может быть что то в реестре что то прописалось и теперь из-за этого глюки. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано July 13, 2012 я кстати ваш код так до конца и не понял переписал по своему Вот в этом куске цифры менял: y.push_back(result.at<float>(1)); x.push_back(result.at<float>(2)); ну так numPrincipalComponents было ровно 3? Mat imacl(Size(w/5,h/5),CV_8UC3); почему делим на 5? я наоборот умножал. for(int i=0; i<10; i++) { rectangle(imacl,Point(i*10,0),Point(i*10+10,10),Colors,-1); } не понял что делает. void project_to_2D() { //читаем данные vector<Mat> db; read_data("C:/ICP/MNIST/60k_images.bin",db); //читаем лэйблы (нужно для окраски точек) vector<unsigned char> MNIST_L; read_labels("C:/ICP/MNIST/60k_labels.bin",MNIST_L); int total = db[0].rows * db[0].cols; int numPrincipalComponents=2; //проецируем на 2Д int rows=db[0].rows; int cols=db[0].cols; Mat mat(total, db.size(), CV_32FC1); //составляем всё в общию матрицу for(int i = 0; i < db.size(); i++) { Mat X = mat.col(i); db[i].reshape(1, total).col(0).convertTo(X, CV_32FC1, 1/255.); } // do pca PCA pca(mat, Mat(), CV_PCA_DATA_AS_COL, numPrincipalComponents); //теперь должны спроецировать наши входные данные на наш новый базис //проецируем vector<float> x; vector<float> y; for(int i=0;i<db.size();++i) { Mat temp; Mat res; db[i].reshape(1, rows*cols).convertTo(temp,CV_32FC1,1./255); pca.project(temp,res); x.push_back(res.at<float>(0)); y.push_back(res.at<float>(1)); } //подготавливаем изображение под отрисовку float min_x,max_x,min_y,max_y; minmax_element(min_x, max_x, x); minmax_element(min_y, max_y, y); float w=max_x-min_x; float h=max_y-min_y; Mat imacl(Size(w*200,h*200),CV_8UC3); imacl=0; CvRNG rng(35435345); CvScalar Colors[256]; for (int i=0;i<256;i++) { Colors[i]=random_color(&rng); } for(int i=0; i<x.size(); i++) { int X=(x[i]-min_x)*200; int Y=(y[i]-min_y)*200; if(X>=(int)(w*200)) X= w*200-1; if(Y>=(int)(h*200)) Y= h*200-1; imacl.at<Vec3b>(Y,X)[0]=Colors[MNIST_L[i]].val[0]; imacl.at<Vec3b>(Y,X)[1]=Colors[MNIST_L[i]].val[1]; imacl.at<Vec3b>(Y,X)[2]=Colors[MNIST_L[i]].val[2]; } imwrite("clusters_label_data.png",imacl); } получилось вот что, вроде то же самое, но всё таки хочется куда то это выгружать, чтобы можно было увеличивать уменьшать в риалтайме и были написаны легенды или даже сами знаки. по улучшению можно придумать только поменять вектор признаков или поменять PCA на что либо более сложное. но с другой стороны как это всё оценивать? только на глаз? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 13, 2012 y.push_back(result.at<float>(1)); x.push_back(result.at<float>(2));[/code] Здесь второй собственный вектор совмещается с осью Y, а третий с X. На 5 делил, потому что в экран не помещалось. [code]for(int i=0; i<10; i++) { rectangle(imacl,Point(i*10,0),Point(i*10+10,10),Colors[i],-1); } Легенду рисует в верхнем углу Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано August 21, 2012 //преобразуем через LBP (надо не просто преобразовать, а гистограммы посчитать) vector<Mat> db_lbp(db.size()); for(int i=0;i<db.size();++i) { lbp::OLBP(db[i],db_lbp[i]); } db= db_lbp;// попробовал Local Binary Patterns, но ничего хорошего не выдало, видимо надо посчитать гистограммы, но я пока не понял как. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах