// Original C++ solution (slower):
#include <iostream>

#include <algorithm>

#include <vector>

#define rep(i,n) for(int i = 0 ; i < n ; ++i)

#define rep1(i,n) for(int i = 1 ; i <= n ; ++i)

using namespace std;

typedef long long ll;

const int VMAX=100010;

const ll MOD=1e+9+7;

struct mint{

  ll x;

  mint(ll x=0):x(x%MOD){}

  mint& operator+=(const mint a){

    if((x+=a.x)>=MOD) x-=MOD;

    return *this;

  }

  mint& operator-=(const mint a){

    if((x += MOD-a.x)>=MOD) x-=MOD;

    return *this;

  }

  mint& operator*=(const mint a){

    (x*=a.x)%=MOD;

    return *this;

  }

  mint operator+(const mint a) const{

    mint res(*this);

    return res+=a;

  }

  mint operator-(const mint a) const{

    mint res(*this);

    return res-=a;

  }

  mint operator*(const mint a) const{

    mint res(*this);

    return res*=a;

  }

  mint pow(ll t) const{

    if(!t) return 1;

    mint a = pow(t>>1);

    a*=a;

    if(t&1) a*=*this;

    return a;

  }

  

  //for prime mod

  mint inv() const{

    return pow(MOD-2);

  }

  mint& operator/=(const mint a){

    return (*this) *= a.inv();

  }

  mint operator/(const mint a) const{

    mint res(*this);

    return res/=a;

  }

};



int n;

int x[100010],y[100010];

vector<int> edge[VMAX];

mint dp[100010][2];

bool f[100010];

void add_edge(int from,int to){

  edge[from].push_back(to);

  edge[to].push_back(from);

}

void dfs(int s){

  f[s] = true;

  int ss = edge[s].size();

  dp[s][0] = dp[s][1] = 1;

  rep(i,ss){

    int w = edge[s][i];

    if(f[w]) continue;

    dfs(w);

    dp[s][0] *= dp[w][0] + dp[w][1];

    dp[s][1] *= dp[w][0];

  }

}

int main()

{

  cin >> n;

  rep(i,n-1) cin >> x[i] >> y[i];



  rep(i,n-1) add_edge(--x[i],--y[i]);

  rep(i,n) f[i] = false;



  dfs(0);

  mint res = dp[0][0] + dp[0][1];

  cout << res.x << "\n";

  

  return 0;

}


// Optimized solution to the same problem (faster):
#include <iostream>

#include <algorithm>

#include <vector>

#define rep(i,n) for(int i=0;i<n;++i)

#define rep1(i,n) for(int i=1;i<=n;++i)

using namespace std;

template<class T>bool chmax(T &a, const T &b) { if(a < b){ a = b; return 1; } return 0; }

template<class T>bool chmin(T &a, const T &b) { if(a > b){ a = b; return 1; } return 0; }

typedef long long ll;

const ll MOD=1e+9+7;

struct mint{

  ll x;

  mint(ll x=0):x(x%MOD){}

  mint& operator+=(const mint a){

    if((x+=a.x)>=MOD) x-=MOD;

    return *this;

  }

  mint& operator-=(const mint a){

    if((x += MOD-a.x)>=MOD) x-=MOD;

    return *this;

  }

  mint& operator*=(const mint a){

    (x*=a.x)%=MOD;

    return *this;

  }

  mint operator+(const mint a) const{

    mint res(*this);

    return res+=a;

  }

  mint operator-(const mint a) const{

    mint res(*this);

    return res-=a;

  }

  mint operator*(const mint a) const{

    mint res(*this);

    return res*=a;

  }

  mint pow(ll t) const{

    if(!t) return 1;

    mint a = pow(t>>1);

    a*=a;

    if(t&1) a*=*this;

    return a;

  }

  

  //for prime mod

  mint inv() const{

    return pow(MOD-2);

  }

  mint& operator/=(const mint a){

    return (*this) *= a.inv();

  }

  mint operator/(const mint a) const{

    mint res(*this);

    return res/=a;

  }

};







template <typename X>

struct Node{

  int idx;

  

  Node() = default;



  Node(int idx) : idx(idx) {}

};

template <typename X>

struct Edge{

  int from;

  int to;

  X cost;

  

  Edge() = default;



  Edge(int from, int to, X cost) : from(from), to(to), cost(cost) {}

};

template <typename X>

class Tree{

private:

  int n; // number of node

  vector<vector<Edge<X>>> edge; 



  vector<vector<int>> parent; // parent[i][j] := node followed parent at 2^j times from node[i]

  vector<vector<X>> depth; // depth[i][j] := depth of the node[j] when root is node[i]

  const int MAXLOGN = 20;

  

  mint dp[100010][2];

  

public:

  Tree() = default;



  Tree(int n) : n(n) {

    edge.resize(n);

  }



  Tree(int n, vector<int> a, vector<int> b) : n(n) {

    edge.resize(n);

    rep(i,n-1) {

      add_edge(a[i], b[i]);

      add_edge(b[i], a[i]);  // indirected edge

    }

  }



  Tree(int n, vector<int> a, vector<int> b, vector<X> c) : n(n) {

    edge.resize(n);

    rep(i,n-1) {

      add_edge(a[i], b[i], c[i]);

      add_edge(b[i], a[i], c[i]);  // indirected edge

    }

  }  



  void add_edge(int from, int to, X cost = 1) {

    edge[from].emplace_back(from, to, cost);

  }



  mint DFS(int v, int p, int color) {

    if(dp[v][color].x > 0) return dp[v][color];

    mint res(1);

    for(auto next: edge[v]) {

      int w = next.to;

      if(w == p) continue;

      if(color == 0) {

	res *= (DFS(w, v, 0) + DFS(w, v, 1));

      }

      else {

	res *= DFS(w, v, 0);

      }

    }

    return dp[v][color] = res;

  }

};



int main()

{

  int n;cin >> n;

  vector<int> a(n-1), b(n-1);

  rep(i,n-1) {

    cin >> a[i] >> b[i];

    a[i]--; b[i]--;

  }



  Tree<int> tr(n, a, b);

  cout << (tr.DFS(0, -1, 0) + tr.DFS(0, -1, 1)).x  << "\n";

  

  return 0;

}


// Fastest known solution for this problem: